vue响应式原理

发布时间:2019-05-16 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了vue响应式原理脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

1.数据双向绑定及响应式

(1).Object.defineProperty
该方法是Object对象定义属性的方法,可以修改属性默认的特性

/*参数解释:
obj表示目标对象,即属性所在的对像;
key表示属性名;
最后一个参数表示属性的描述符对象
*/
Object.defineProperty(obj, key, {
  configurable: false, //属性是否可以被删除或修改,默认为false
  enumerable: false, //属性是否可枚举,默认为false
  writeable: true, //属性的值能否修改,默认为true
  value: 'yayaya', //包含该属性的数据值
  get: function() {}, //获取属性的方法
  set: function() {} //设置属性的方法
})

(2).观察者模式(发布-订阅)
(3).举例解析双向绑定
<1>.响应式基本原理
例1:
基本思路:渲染视图 <=监听每个data的数据变化 <=遍历data中的每一项 <=获取数据

html中代码:
    <!DOCTYPE html>
    <html>
      <head>
        <title>demo</title>
      </head>
      <body>
        <div id="demo">
      </body>
    </html>
    <script type="text/javascript" src="vue2.js"></script>
    <script>
    //new 一个 Vue 对象,就会将 data 中的数据进行「 响应式」化
    var v = new Vue({
      el: '#demo',
      data: {
        name: '123'
      },
    })
    v._data.name = '456';
    </script>

vue2.js中代码:

function Vue(options) { //获取数据
  this._data = options.data;
  observe(this._data);
}

function observe(value) { //遍历data中的每一项
  //先不考虑value为数组的复杂情况
  if (!value || typeof value !== 'object') return;
  Object.keys(value).forEach(function(propertyName) {
    defineReactive(value, propertyName, value[propertyName])
  })
}

function defineReactive(obj, key, val) { //监听每个data的数据变化
  console.log('defineReactive==parameter', obj, key, val)
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    set: function(newVal) {
      console.log('newVal', newVal);
      if (val == newVal) return;
      update(); //如果新修改的值和原来的值不同就重新渲染页面
    },
    get: function() {
      return val;
    }
  })
}

function update() {
  console.log("update view===")
}

输出结果:

vue响应式原理

小结:从data到视图view的响应式原理主要用到的是Object.definePorperty对数据进行劫持,再更新视图

<2>.依赖收集
1>为什么要有依赖收集

例1:
var globalData = {
  name: 'yayaya',
  age: '26'
}
var vue1 = new Vue({
  data: {
    name: globalData.name
  }
})
var vue2 = new Vue({
  data: {
    name: globalData.name
  }
}) 

vue响应式原理

假如我们修改了globalData中name的值,那么vue1和vue2实例中用到全局name的地方都需要更新,这个时候就需要依赖收集,告诉观察者哪些实例下的数据需要更新.

2>.依赖收集的实现过程

1.订阅者Dep:Dep的主要作用是存放Watcher观察者对象 
function Dep() {
 //添加观察者watcher
  this.subs = [];
  this.addSub = function(sub) {
    this.subs.push(sub);
    console.log("sub==", sub);
  }
  //通知Watcher更新视图
  this.notify = function() {
    this.subs.forEach(function(s) {
      s.update()
    });
  }
}
Dep.target = null;

2.观察者Watcher:主要作用是监听数据变化更新视图
function Watcher() {
  Dep.target = this; //在new 一个Watcher 对象时将该对象赋值给Dep.target,在get 中会用到
  this.update = function() {
    console.log('updata view===')
  }
}

3.在defineReactivez和Vue中实现依赖收集
 function defineReactive(obj, key, val) { //监听data中的数据变化
  var dep = new Dep();//实例化一个订阅者
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    set: function(newVal) {
      //在set时发送通知给Watcher,重新渲染视图
      console.log("set start===");
      if (val == newVal) return;
      dep.notify(); //如果新修改的值和原来的值不同就重新渲染页面
    },
    get: function() {
      //get时添加依赖
      console.log("get start===");
      dep.addSub(Dep.target); //把watcher实例添加到依赖中
      return val;
    }
  })
}

function Vue(options) { //获取数据
  this._data = options.data;
  observe(this._data);
  new Watcher();
  console.log("this._data.name", this._data.name)
}

function observe(value) { //遍历data中的每一项
  //先不考虑value为数组的复杂情况
  if (!value || typeof value !== 'object') return;
    Object.keys(value).forEach(function(propertyName) {
    defineReactive(value, propertyName, value[propertyName])
  })
}

4.组件中的代码
var v = new Vue({
  el: '#demo',
  data: {
    name: '123'
  },
})
console.log("name is changing")
v._data.name = '456';

输出结果:

vue响应式原理

小结:
首先vue在observe中注册并调用get,在get中,将Watcher实例通过addSub方法添加到dep的subs数组中,这完成了依赖添加的过程; 当数据变化时,调用Object.defineProperty中的set方法,判断数据是否发生改变,如果改变了,就调用dep中的notify方法通知Watcher,Watcher知道数据变化更新数据.

vue响应式原理

脚本宝典总结

以上是脚本宝典为你收集整理的vue响应式原理全部内容,希望文章能够帮你解决vue响应式原理所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签:Vue