作为Lubanno7UniverSheet的开发者,在设计API时,我坚定地选择了命令式而非声明式。这并非对声明式的否定,而是基于一个核心目标------让这个基于Univer引擎的电子表格组件,能真正做到"一次开发,全框架兼容"。对需要在React、Vue3、原生JS等多环境中复用的表格工具而言,命令式是实现"无框架壁垒"的唯一解。
一、为什么必须打破框架壁垒?
表格作为前端开发的基础组件,常需在企业内部的多套系统中复用------可能一套用React,一套用Vue3,甚至还有遗留的原生JS项目。如果组件只能适配单一框架,团队就不得不维护多套"功能相似但实现不同"的表格代码,这与"降低开发成本"的初衷背道而驰。
Lubanno7UniverSheet的定位是"通用电子表格组件",核心诉求之一就是:无论开发者用什么技术栈,都能以几乎相同的方式集成和使用。而声明式API从设计上就与框架深度绑定,命令式则能突破这一限制。
二、命令式:实现跨框架通用的唯一路径
声明式API的便捷性,依赖于具体框架的"响应式 runtime"(如Vue的watch
、React的useEffect
),这些机制是框架专属的,无法跨环境复用。而命令式基于原生JS的"类与实例"模式,天然具备"一次编写,多框架运行"的能力------这正是Lubanno7UniverSheet选择命令式的核心原因。
1. 声明式的框架绑定问题
声明式API的实现逻辑与框架强耦合:
- 在Vue中,声明式表格需要通过
props
接收配置,用emit
触发事件,依赖onMounted
/onUnmounted
管理生命周期,这些都是Vue的专属语法; - 在React中,同样的功能需要用
JSX
传递属性,用useState
管理状态,用useEffect
处理副作用,逻辑与Vue版完全不同。
若为了声明式适配多框架,就必须为每个框架重写一套"框架专属包装层",不仅导致代码冗余(核心逻辑之外多维护N套代码),更会让开发者面临"框架切换即API重构"的问题------比如Vue中监听@update-data
事件,到了React中可能要写成onUpdateData
属性,学习成本翻倍。
2. 命令式的跨框架一致性
命令式API基于原生JS的"实例化"逻辑,核心代码与框架无关。Lubanno7UniverSheet的核心功能(表格渲染、数据操作、事件监听)均通过原生JS实现,框架适配仅需"挂载容器"这一步,无需修改核心逻辑。
从代码示例就能直观看到这种一致性:
在React中集成
jsx
import React, { useEffect, useRef } from 'react';
import Lubanno7UniverSheet from 'lubanno7-univer-sheet';
import 'lubanno7-univer-sheet/lib/lubanno7-univer-sheet.css';
const TableComponent = () => {
const containerRef = useRef(null);
const tableInstanceRef = useRef(null);
useEffect(() => {
if (containerRef.current) {
// 初始化配置(与框架无关)
const columns = [{ prop: 'name', label: '姓名' }, /* ... */];
const data = [{ name: '张三' }, /* ... */];
const config = { styleOptions: { width: '100%' } };
// 创建实例(原生JS语法,跨框架一致)
tableInstanceRef.current = new Lubanno7UniverSheet(containerRef.current, {
columns, data, config
});
// 事件监听(一致的on方法)
tableInstanceRef.current.on('tableInitialized', () => {
console.log('表格初始化完成');
});
}
// 销毁实例(一致的dispose方法)
return () => tableInstanceRef.current?.dispose();
}, []);
return <div ref={containerRef} />;
};
在Vue3中集成
vue
<template>
<div ref="containerRef"></div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
import Lubanno7UniverSheet from 'lubanno7-univer-sheet';
import 'lubanno7-univer-sheet/lib/lubanno7-univer-sheet.css';
const containerRef = ref(null);
let tableInstance = null;
onMounted(() => {
if (containerRef.value) {
// 同样的初始化配置(与React版完全一致)
const columns = [{ prop: 'name', label: '姓名' }, /* ... */];
const data = [{ name: '张三' }, /* ... */];
const config = { styleOptions: { width: '100%' } };
// 同样的实例化逻辑(new + 配置参数)
tableInstance = new Lubanno7UniverSheet(containerRef.value, {
columns, data, config
});
// 同样的事件监听(on方法完全复用)
tableInstance.on('tableInitialized', () => {
console.log('表格初始化完成');
});
}
});
// 同样的销毁逻辑(dispose方法一致)
onUnmounted(() => tableInstance?.dispose());
</script>
在原生JS中集成
javascript
import Lubanno7UniverSheet from 'lubanno7-univer-sheet';
import 'lubanno7-univer-sheet/lib/lubanno7-univer-sheet.css';
const container = document.getElementById('table-container');
// 配置与框架环境完全一致
const columns = [{ prop: 'name', label: '姓名' }, /* ... */];
const data = [{ name: '张三' }, /* ... */];
const config = { styleOptions: { width: '100%' } };
// 实例化、事件监听、销毁逻辑与框架中完全相同
const tableInstance = new Lubanno7UniverSheet(container, {
columns, data, config
});
tableInstance.on('tableInitialized', () => {
console.log('表格初始化完成');
});
window.addEventListener('beforeunload', () => {
tableInstance.dispose();
});
可以清晰地看到:无论是React、Vue3还是原生JS,核心代码(配置定义、实例创建、事件监听、销毁)完全一致 。开发者切换框架时,无需修改表格的核心逻辑,只需调整"容器获取"的方式(React用useRef
、Vue用ref
、原生用getElementById
)------这种一致性是声明式无法实现的。
三、命令式≠复杂:兼顾通用性与易用性
可能有人担心:命令式需要手动管理实例,会不会增加使用成本?实际上,Lubanno7UniverSheet通过精心设计的API,让命令式的易用性不输声明式:
- 极简初始化 :一行
new Lubanno7UniverSheet(container, options)
即可创建表格,配置项(columns
/data
/config
)结构清晰,无需学习框架专属语法; - 一致的事件系统 :所有交互(初始化完成、数据更新、单元格点击等)都通过
tableInstance.on(eventName, callback)
监听,逻辑与框架无关; - 明确的资源管理 :通过
dispose()
方法统一销毁实例,避免内存泄漏,在任何环境中都能通过相同的方式释放资源。
这些设计让开发者在享受"跨框架通用"的同时,无需为命令式的"过程控制"付出额外成本。
最后:通用,是对开发者最大的尊重
对开源组件而言,"能被更多人用起来"比"在单一框架中更优雅"更有价值。Lubanno7UniverSheet选择命令式,正是为了让React开发者、Vue开发者、原生JS开发者能共享同一套表格能力,不用因技术栈差异而重复造轮子。
如果你需要在多框架项目中复用电子表格组件,不妨通过npm install lubanno7-univer-sheet
尝试------无论是React的useRef
、Vue的ref
还是原生的DOM选择器,你会发现:真正通用的组件,从不会让你为框架差异烦恼。
项目已在GitHub开源,包含完整文档和演示,欢迎大家体验。