每日前端夜话0xA6
每日前端夜话,陪你聊前端。
每天晚上18:00准时推送。
正文共:2251 字
预计阅读时间:10 分钟
作者:Daybrush
翻译:疯狂的技术宅
来源:medium
跨框架组件(Cross Framework Component (CFC))是一种支持各种框架的基于单个通用模块有效结构。
跨框架组件用到了跨平台的方法。 跨平台是一种允许你在各种平台(操作系统,设备)上使用单一源代码的结构,可以通过 Xamarin、Flutter、NativeScript 和 React Native 等工具在 iOS、Android 和 Windows 中使用。
跨框架组件在 React、Angular、Vue 等中也可作为单个原生组件使用。
在框架中使用传统的原生组件有两种方法:
- 简单包装现有的原生组件
- 创建新的框架组件
简单包装现有的原生组件
第一个方法(现有原生组件的简单包装)是用户最常用的方法。因为它非常简单易行。
但是,当DOM中没有变化(add
/remove
/move
)时,这是一个合适的方法。因为框架会将你的数据同步到DOM。但是,如果原生组件操纵 DOM,则会阻止框架与 DOM 同步。
这时框架中的数据和 DOM 之间的关系会变得混乱。实际上,从组件中删除 DOM 可能会导致以下错误:
React中的DOM错误
因为框架正在寻找已被删除的 DOM。所以如果你想使用现有原生组件的简单包装,就不要操作 DOM。
创建一个新的框架组件
第二个方法(创建一个新的框架组件)是为特定框架创建一个的新的组件。但是把现有的原生组件再次专用于框架又有什么不对呢?
当然由于创建了特定于框架的组件,因此框架的所需功能可以正常工作。但是如果把现有的原生组件重新创建为框架组件,则维护会变得非常困难,因为每个框架中都有多份代码。所以从没有原生组件的框架组件重新开始是一个的好方法。
egjs 【https://naver.github.io/egjs】已经开始考虑使用跨框架组件来解决上述两种方法中存在的问题。
以下是跨框架组件如何解决问题以及如何将其应用于原生组件的方法。
跨框架组件的原理
正如我之前所说的,框架需要与 DOM 同步,但原生组件会干扰同步。
因此跨框架组建不会操纵原生组件中的 DOM。而且在从框架同步到 DOM 之后,会再次将同步的 DOM 同步到数据。
这样,你可以通过清晰的同步顺序来获取所需的数据,而不会造成相互中断。那么我们该怎样从 DOM 同步到数据呢?
它还做用于组件上,用来将框架与 DOM 同步。
以相同的方式同步
假设存在框架数据 1, 2, 3, 4, 5, 6
,DOM 中的数据顺序为 1, 2, 3, 4, 5, 6
,组件数据的顺序为 1,2,3,4,5,6
。
如果你要把框架数据 6
移动到框架数据 3
前面。
然后,通过同步 DOM 中的框架数据,DOM 中的 元素 6 移动到元素 3 前面。
最后,同步最后的 DOM,原生组件中的数据 6
也移动到数据 3
的前面。
你可以用与框架相同的方式同步它。但是我不知道如何与 React、Angular 或 Vue 同步,并且 React、Angular 和 Vue 使用的所有方法都不一样。因此,你可以创建类似的方法并使结果相同,而不是以相同的方式创建它。
ListDiffer
ListDiffer 是一个比较库,用于检测列表(或数组)中的更改并跟踪更改的进度。
在React、Angular 和 Vue 中肯定有类似的比较函数来跟踪变更过程。
但是,egjs 创建了 ListDiffer,这是一个可以在 React、Angular 和 Vue 中使用的库,并通过这个库进行同步。可以在以下文章中找到更多信息:【https://medium.com/p/27793f0c6f4a?source=post_page---------------------------】
这能够允许你从 DOM 同步到 组件,而不必知道如何在框架中使用它。
在跨平台的情况下,为了在各种操作系统上进行操作,这需要一个 supporter 将框架 API 与操作系统 API 进行连接。
跨框架组件也是如此。在各种框架下运行需要一个 supporter,可以将 ListDiffer API与框架 API连接起来。
- 用于React:react-children-differ
- 用于 Angular:ngx-children-different
- 用于 Vue:vue-children-different
使用 list-different API,可以轻松创建React、Angular和Vue组件。
跨框架组件的准备工作
应用跨框架组件有两种方法:使用数据跟踪(效率处理方法)和不使用数据跟踪(一步处理方法)。
使用数据跟踪(效率处理方法)
使用数据跟踪是一种尽可能减少处理次数的好方法。
- ListDIffer for Framework
- 渲染外化选项
- 插入方法
- 删除方法
原生组件的内部 DOM 操作必须是可选的,以便使现有的原生组件成为跨框架组件。此方法称为渲染外部化选项。当你使用原生组件时将会使用 DOM 方法,例如 appendChild 和 removeChild,但在框架中你可以通过激活渲染外化选项来阻止 DOM 方法,例如 appendChild 和 removeChild。
你可以按以下顺序编写代码来使用它: removed
> ordered
> added
:
const { removed, added, ordered, pureChanged, list } = result;
removed.forEach(index => {
inst.remove(index);
});
ordered.forEach(([from, to], i) => {
inst.remove(from);
inst.insert(to, list[pureChanged[i][1]]);
});
added.forEach(index => {
inst.insert(index, list[index]);
});
removed
是你想要的索引数组。通过 remove 方法从索引中删除数据。ordered
是要移动的数组起始索引和结束索引。remove 方法允许你通过从该索引中删除数据,并将其添加到将通过 insert 方法访问的索引来移动数字。added
是要添加的索引数组。通过 insert 方法将数据添加到索引中。
如果方法匹配,则实际上只需要通过复制/粘贴这段代码就行了。
不使用数据跟踪(一步处理方法)
不使用数据跟踪是批量处理的好方法**。
要实现“不使用数据跟踪方法”需要以下项目:
- ListDIffer for Framework
- 渲染外化选项
- 同步方法
使用数据跟踪的方法中有一个 insert 方法,一个 remove 方法,但是不使用数据跟踪的方法需要一个用来进行批处理的同步方法。
如果你不想使用数据跟踪,可以根据情况省略它,并记住处理顺序 maintained
> added
。
以不使用数据跟踪的方式创建 Flicking 3,以下代码是 Flicking 的一部分。
代码语言:javascript复制function sync(result) {
const { maintained, removed, added, list } = result;
const prevItems = this.items;
const newItems = [];
maintained.forEach(([beforeIndex, afterIndex]) => {
newItems[afterIndex] = prevItems[beforeIndex];
});
added.forEach(i => {
newItems[i] = new Item(list[i]);
});
this.items = newItems;
this.recaculateItems();
}
使用 maintain
,你只能导入先前数据的维护部分,并通过 added
添加新数据。
Flicking 的最后一个方法 caculateSize()
批量获取 DOM 的大小。如果使用“数据跟踪”,则每次都会进行布局操作,并且可能会出现性能问题。
Flicking 3
Flick
由三个关键框架支持:react-flicking
,ngx-flicking
和 vue-flicking
,并且可以使用 Flicking 的大部分功能。
总结
本文介绍了跨框架组件的特性、原理和用法。
InfiniteGrid
也将要使用跨框架组件的方法。它提供了有限的 React 支持,但你很快就会看到在 React、Angular 和 Vue 组件中提供的大量功能。
许多人在使用 egjs,而且正在用到许多框架中,如React、Angular 和 Vue。以前它需要花费两倍的时间来进行处理,因为它是用两组代码进行管理的。将来,Flicking
和 InfiniteGrid
将被集成到跨框架组件结构中,为你的查询提供可靠的响应,让你更快地满足各种功能的需求。
原文:https://medium.com/naver-fe-platform/how-to-make-cross-framework-component-ee76d76708b1