共计 1190 个字符,预计需要花费 3 分钟才能阅读完成。
作者:心叶
时间:2019-07-18 10:34
本文章构思的实现方法在 github 上有对应的项目已经实现,项目依旧在不断改进中:abandon.js
核心方法说明
Object.defineProperty(obj,key,{get(){// todo1},
set(newValue){// todo2}
});
比如 obj 是一个 json,其有一个值 key,也就是 obj.key。我们可以通过上面的方法对设置和获取 obj.key 的时候进行拦截处理,而这就是 js 部分双向绑定的核心。
设计思路
页面 → JS
监听输入框的输入时间,如果有输入,就主动改变 js 中的值,这样,页面到 js 这一条路就通了。
JS → 页面
js 部分通过前面说的 Object.defineProperty 方法,对需要双向绑定的数据进行拦截,发现数据改变的时候,就主动去修改页面显示,这样,js 到页面这一条路就通了。
难点
上面的说明看起来很简单,然而,事实并非如此,主要有下面几个问题(其实主要是设计的问题):
- js 数据改变了,你怎么知道应该修改页面中哪些地方?
- 页面的表达式可能很复杂,如何解析
- 数组或对象如何监听
实现
主体对象
控制整个流程,余下的都是由这里协调资源。
let Abandon = function (options) {
// 管理的数据(双向绑定)this._data = options.data || {};
// 对维护的数据进行监听
this.__observe();
// 获取挂载点
this.$el = $$(options.el)[0];
// 编译结点
this.__compile();}
数据拦截者 observe.js
对象 options 的 data 中定义的 key 的编辑会在这里拦截,通知专门处理变化情况的(同步视图和数据)。
export default function(){for (let key in this._data) {
// 定义拦截钩子
Object.defineProperty(this._data, key, {get() {// todo},
set(newValue) {// todo}
});
};
编译程序 compile.js
简单点说,就是分析结点中的内容,有没有定义的指令等,根据结点内容追加需要管理的东西。
export default function(){
let nodes = this.$el.childNodes;
for (let i = 0; i < nodes.length; i++) {
// 如果不是文本结点,继续编译
if (node.nodeType !== 3) {// todo}
// 开始正式解析一个结点(分为文本结点和非文本结点)// 解析的意思就是标记需要管理的属性,文本等
if (node.nodeType === 3) {// 如果是文本} else {// 如果不是文本}
}
};
后记
上面力求简单,具体的代码没有显示出来,如果需要看具体代码,请去 github/abandon.js 上查看。
正文完