VueJS运行机制系列:响应式原理

Posted Node前端

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了VueJS运行机制系列:响应式原理相关的知识,希望对你有一定的参考价值。

来源:https://github.com/answershuto/learnVue/blob/master/docs/%E5%93%8D%E5%BA%94%E5%BC%8F%E5%8E%9F%E7%90%86.MarkDown

响应式原理

这个是vue运行机制第一篇,明天继续

关于Vue.js

Vue.js是一款MVVM框架,上手快速简单易用,通过响应式在修改数据的时候更新视图。Vue.js的响应式原理依赖于Object.defineProperty,尤大大在Vue.js文档中就已经提到过,这也是Vue.js不支持IE8 以及更低版本浏览器的原因。Vue通过设定对象属性的 setter/getter 方法来监听数据的变化,通过getter进行依赖收集,而每个setter方法就是一个观察者,在数据变更的时候通知订阅者更新视图。

将数据data变成可观察(observable)的

那么Vue是如何将所有data下面的所有属性变成可观察的(observable)呢?

 
   
   
 
  1. function observe(value, cb) {

  2.    Object.keys(value).forEach((key) => defineReactive(value, key, value[key] , cb))

  3. }

  4. function defineReactive (obj, key, val, cb) {

  5.    Object.defineProperty(obj, key, {

  6.        enumerable: true,

  7.        configurable: true,

  8.        get: ()=>{

  9.            /*....依赖收集等....*/

  10.            /*Github:https://github.com/answershuto*/

  11.            return val

  12.        },

  13.        set:newVal=> {

  14.            val = newVal;

  15.            cb();/*订阅者收到消息的回调*/

  16.        }

  17.    })

  18. }

  19. class Vue {

  20.    constructor(options) {

  21.        this._data = options.data;

  22.        observe(this._data, options.render)

  23.    }

  24. }

  25. let app = new Vue({

  26.    el: '#app',

  27.    data: {

  28.        text: 'text',

  29.        text2: 'text2'

  30.    },

  31.    render(){

  32.        console.log("render");

  33.    }

  34. })

为了便于理解,首先考虑一种最简单的情况,不考虑数组等情况,代码如上所示。在initData中会调用observe这个函数将Vue的数据设置成observable的。当_data数据发生改变的时候就会触发set,对订阅者进行回调(在这里是render)。

那么问题来了,需要对app._data.text操作才会触发set。为了偷懒,我们需要一种方便的方法通过app.text直接设置就能触发set对视图进行重绘。那么就需要用到代理。

代理

我们可以在Vue的构造函数constructor中为data执行一个代理proxy。这样我们就把data上面的属性代理到了vm实例上。

 
   
   
 
  1. _proxy.call(this, options.data);/*构造函数中*/

  2. /*代理*/

  3. function _proxy (data) {

  4.    const that = this;

  5.    Object.keys(data).forEach(key => {

  6.        Object.defineProperty(that, key, {

  7.            configurable: true,

  8.            enumerable: true,

  9.            get: function proxyGetter () {

  10.                return that._data[key];

  11.            },

  12.            set: function proxySetter (val) {

  13.                that._data[key] = val;

  14.            }

  15.        })

  16.    });

  17. }

我们就可以用app.text代替app._data.text了。


往期推荐:




以上是关于VueJS运行机制系列:响应式原理的主要内容,如果未能解决你的问题,请参考以下文章

vue2 响应式原理保姆级别

vue2 响应式原理保姆级别

vue2 响应式原理保姆级别

你不知道的Vuejs - 深入浅出响应式系统

Vue3官网-高级指南(十七)响应式计算`computed`和侦听`watchEffect`(onTrackonTriggeronInvalidate副作用的刷新时机`watch` pre)(代码片段

VSCode自定义代码片段—— 数组的响应式方法