vuereact源码思考之双向绑定

5次阅读

共计 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 上查看。

正文完
 0