完成一个浅易的vue

《完成一个浅易的vue》

1./compiler ⽬目次是编译模版;

2./core ⽬目次是 Vue.js 的核⼼心(也是后⾯面的重点);

3./platforms ⽬目次是针对核⼼心模块的 ‘平台’ 模块;

4./server ⽬目次是处置惩罚理服务端衬着;

5./sfc ⽬目次处置惩罚理单⽂文件 .vue;

6./shared ⽬目次供应全局⽤用到的⼯东西函数。

Vue.js 的组成是由 core + 对应的 ‘平台’ 补充代码组成(自力构建和运行时构建 只是 platforms 下 web 平台的两种挑选)。
《完成一个浅易的vue》

vue的双向数据绑定

双向绑定(响应式道理)所触及到的手艺

1. Object.defineProperty
2. Observer
3. Watcher
4. Dep
5. Directive

1. Object.defineProperty

var obj = {};
var a;
Object.defineProperty(obj,'a',{
  get: function(){
    console.log('get val');
    return a;
  },
  set: function(newVal){
    console.log('set val:' + newVal);
    a = newVal;
  }
});
obj.a // get val;   相当于<span>{{a}}</span>
obj.a = '111'; // set val:111  相当于<input v-model="a">

《完成一个浅易的vue》
setter 触发音讯到 Watcher watcher帮助关照 Directive 更新DOM,DOM中修正了数据 也会关照给 Watcher,watcher 帮助修正数据。

2. Observer

观察者形式是软件设计形式的一种。
在此种形式中,一个目的对象治理一切相依于它的观 察者对象,并且在它本身的状况转变时主动发出关照。
这一般透过呼唤各观察者所供应的 要领来完成。此种形式一般被用来及时事宜处置惩罚系统。
定阅者形式触及三个对象:
发布者、主题对象、定阅者,三个对象间的是一对多的关联,
每当主题对象状况发作转变时,其相干依靠对象都邑获得关照,并被自动更新。
看一个简朴的示例:

《完成一个浅易的vue》

《完成一个浅易的vue》
vue里边怎样操纵的呢? vue observer

《完成一个浅易的vue》
《完成一个浅易的vue》
《完成一个浅易的vue》

  1. watcher

《完成一个浅易的vue》

《完成一个浅易的vue》

  1. Dep

《完成一个浅易的vue》

  1. Directive

《完成一个浅易的vue》

《完成一个浅易的vue》
《完成一个浅易的vue》

《完成一个浅易的vue》

弄邃晓道理和架构以后,我们来完成一个简朴的vue双向数据绑定

《完成一个浅易的vue》

1.这个Vue是从哪里来的呢?

《完成一个浅易的vue》
是经由过程上述要领实例化的一个对象;然则里边有两个未知生物 observe ? Compile?
《完成一个浅易的vue》
observe中写的是双向绑定的中心道理就是Object.defineProperty

经由过程set,get来设置值与猎取值

把text属性绑定到vue实例上面去运用

那个中的Dep又是什么呢?

《完成一个浅易的vue》
增加定阅者跟关照定阅更新

再来看一下Compile中写的什么吧

function Compile(node, vm) {
  if (node) {
    this.$frag = this.nodeToFragment(node, vm);
    return this.$frag;
  }
}
Compile.prototype = {
  nodeToFragment: function (node, vm) {
    var self = this;
    var frag = document.createDocumentFragment(); // 建立一段html文档片断
    var child;

    while (child = node.firstChild) {
      self.compileElement(child, vm);
      frag.append(child); // 将一切子节点增加到fragment中
    }
    return frag;
  },
  compileElement: function (node, vm) {
    var reg = /\{\{(.*)\}\}/;

    //节点范例为元素
    if (node.nodeType === 1) {
      var attr = node.attributes;
      // 剖析属性
      for (var i = 0; i < attr.length; i++) {
        if (attr[i].nodeName == 'v-model') {
          var name = attr[i].nodeValue; // 猎取v-model绑定的属性名
          node.addEventListener('input', function (e) {
            // 给响应的data属性赋值,进而触发该属性的set要领
            // 触发set vm[name]
            vm[name] = e.target.value;
          });
          // node.value = vm[name]; // 将data的值赋给该node
          new Watcher(vm, node, name, 'value');
        }
      };
    }
    //节点范例为text
    if (node.nodeType === 3) {
      if (reg.test(node.nodeValue)) {
        var name = RegExp.$1; // 猎取匹配到的字符串
        name = name.trim();
        // node.nodeValue = vm[name]; // 将data的值赋给该node
        new Watcher(vm, node, name, 'nodeValue');
      }
    }
  },
}

哦,本来Compile中是衬着html的啊。个中的Watcher是否是监控节点变化,然后给Dep关照的呢?

function Watcher(vm, node, name, type) {
    Dep.target = this;
    this.name = name; //text
    this.node = node; // 节点
    this.vm = vm; // vue实例
    this.type = type; //nodeValue 当前节点的值
    this.update();
    Dep.target = null;
}

Watcher.prototype = {
    update: function() {
        this.get();
        var batcher = new Batcher();
        batcher.push(this);
        // this.node[this.type] = this.value; // 定阅者实行响应操纵
    },
    cb:function(){
        this.node[this.type] = this.value; // 定阅者实行响应操纵
    },
    // 猎取data的属性值
    get: function() {
        this.value = this.vm[this.name]; //触发响应属性的get
    }
}

哎呦,我们猜对了呢,如许双向数据绑定立时就要完成了,只剩一个Vue.nextTick()的处所了

/**
 * 批处置惩罚组织函数
 * @constructor
 */
function Batcher() {
    this.reset();
}

/**
 * 批处置惩罚重置
 */
Batcher.prototype.reset = function () {
    this.has = {};
    this.queue = [];
    this.waiting = false;
};

/**
 * 将事宜增加到行列中
 * @param job {Watcher} watcher事宜
 */
Batcher.prototype.push = function (job) {
    if (!this.has[job.name]) {
        this.queue.push(job);
        this.has[job.name] = job;
        if (!this.waiting) {
            this.waiting = true;
            setTimeout(() => {
                this.flush();
            });
        }
    }
};

/**
 * 实行并清空事宜行列
 */
Batcher.prototype.flush = function () {
    this.queue.forEach((job) => {
        job.cb();
    });
    this.reset();
};

看完后是否是以为超简朴呢?

vue3版本将做出庞大的变化,把Dep跟Watcher都干掉了,html直接跟数据举行绑定,等vue3出来后,在写一篇关于vue的文章吧

看完后能帮我点个赞吗?

    原文作者:前端陈晨
    原文地址: https://segmentfault.com/a/1190000017522003
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞