xiaofuzi / deep-in-vue

从源码的角度看vue的成长历程。

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

数据驱动更新原理补充说明

xiaofuzi opened this issue · comments

为了更好的了解数据驱动更新原理,我们先来要理解如下几个组成部分:

  • data
  • template
  • directive
  • binding

data -> template

模板使用data中的数据来实现动态渲染,如下所示:

Template

<div id='app'>
      <h2 v-text='hello'></h2>
</div>

Data

new TinyVue(
      data: {
             hello: 'Hello World!'
     }
)

模板中的v-text='hello'会渲染为data.hello的值,记得到如下的html.

<div id='app'>
      <h2 v-text='hello'>Hello World!</h2>
</div>

那么这里两者是怎么关联的呢?就是通过binding来实现的,如下就是一个简单的binding:

Binding

var binding = {
      value: '',
      directives: []
}

每一个binding都会对应一个data中的key,如v-text='hello'中的 hello 就是一个key.

在TinyVue实例中,会将所有的binding以binding对应的key为键值存储起来,这样当key对应的data数据更新的时候就能取出对应的binding,而binding又记录了关联的directive,从而就知道如何去更新UI了。

Bindings对象:

var vm = new TinyVue(
      data: {
             hello: 'Hello World!'
     }
);

var binding = {
      value: '',
      directives: [textDirective]
};

vm._bindings = {
       hello: binding
}

vm.hello = 'hi, girl!';

当执行 vm.hello='hi, girl!'后,会触发hello的setter操作,然后在setter操作中取出对应的binding(已经存储在vm._bindings中),

var binding = vm._bindings['hello'];

得到binding后,就可以执行绑定的指令的更新操作来更新UI了。

binding.directies.forEach(function(directive){
      direcitve.update();
})

如上所示就完成了数据驱动界面的响应。

direcitve 说明

可以简单的将指令(directive)当做一个函数即可,如 text 指令:

    /**
    * 对应于 v-text 指令
    */
    text: function (value) {
        this.el.textContent = value || '';
    }

指令和dom节点的绑定是在解析模板的时候完成得,解析得到directive后,在directive中存储dom节点。

directive.el = el;

即text指令的update函数,当执行 directive.update函数的时候,就会更新关联dom节点的文本内容。

详细实现可参考源码

niu bai bai