设为首页 加入收藏

TOP

Vue.js 源码分析(四) 基础篇 响应式原理 data属性(一)
2019-09-17 18:58:54 】 浏览:61
Tags:Vue.js 源码 分析 基础 响应 原理 data 属性

官网对data属性的介绍如下:

意思就是:data保存着Vue实例里用到的数据,Vue会修改data里的每个属性的访问控制器属性,当访问每个属性时会访问对应的get方法,修改属性时会执行对应的set方法。

Vue内部实现时用到了ES5的Object.defineProperty()这个API,也正是这个原因,所以Vue不支持IE8及以下浏览器(IE8及以下浏览器是不支持ECMASCRIPT 5的Object.defineProperty())。

以一个Hello World为例,如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="https://cdn.bootcss.com/vue/2.5.16/vue.js"></script>
    <title>Document</title>
</head>
<body>
    <div id="app">{{message}}</div>
    <button id="b1">测试按钮</button>
    <script>
        var app = new Vue({
            el:'#app',
            data:{                                                    //data里保存着Vue实例的数据对象,这里只有一个message,值为Hello World!
                message:"Hello World!"     
            }
        })
        document.getElementById('b1').addEventListener('click',function(){         //在b1这个按钮上绑定一个click事件,内容为修正app.message为Hello Vue!
            app.message='Hello Vue!';
        })
    </script>
</body>
</html>

显示的内容为:

当我们点击测试按钮后,Hello World!变成了Hello Vue!:

注:对于组件来说,需要把data属性设为一个函数,内部返回一个数据对象,因为如果只返回一个对象,当组件复用时,不同的组件引用的data为同一个对象,这点和根Vue实例不同的,可以看官网的例子:点我点我

 

 源码分析


 Vue实例后会先执行_init()进行初始化(4579行),如下:

writer by:大沙漠 QQ:22969969

  Vue.prototype._init = function (options) {   
    var vm = this;
    // a uid
    vm._uid = uid$3++;

    /**/
    if (options && options._isComponent) {        //这是组件实例化时的分支,暂不讨论
     /**/
    } else {                                      //根Vue实例执行到这里
      vm.$options = mergeOptions(           //这里执行mergeOptions()将属性保存到vm.$options
        resolveConstructorOptions(vm.constructor),
        options || {},
        vm
      );
    }
    /* istanbul ignore else */
    {
      initProxy(vm);
    }
    // expose real self
    vm._self = vm;
    initLifecycle(vm);
    initEvents(vm);
    initRender(vm);
    callHook(vm, 'beforeCreate');
    initInjections(vm); // resolve injections before data/props
    initState(vm);
    /**/
  };

mergeOptions会为每个不同的属性定义不同的合并策略,比如data、props、inject、生命周期函数等,统一放在mergeOptions里面合并,执行完后会保存到Vue实例.$options对象上,例如生命周期函数会进行数组合并处理,而data会返回一个匿名函数:

    return function mergedInstanceDataFn () {     //第1179行,这里会做判断,如果data时个函数,则执行这个函数,当为组件定义data时会执行到这里 // instance merge
      var instanceData = typeof childVal === 'function'
        ? childVal.call(vm, vm)
        : childVal;
      var defaultData = typeof parentVal === 'function'
        ? parentVal.call(vm, vm)
        : parentVal;
      if (instanceData) {
        return mergeData(instanceData, defaultData)
      } else {
        return defaultData
      }
    }

接下来返回到_init,_init()会执行initState()函数对props, methods, data, computed 和 watch 进行初始化,如下:

function initState (vm) { //第3303行
  vm._watchers = [];
  var opts = vm.$options;
  if (opts.props) { initProps(vm, opts.props); }
  if (opts.methods) { initMethods(vm, opts.methods); }
  if (opts.data) {              //如果定义了data,则调用initData初始化data
    initData(vm);                 
  } else {
    observe(vm._data = {}, true /* asRootData */);
  }
  if (opts.computed) { initComputed(vm, opts.computed); }
  if (opts.watch && opts.watch !== nativeWatch) {
    initWatch(vm, opts.watch);
  }
}

initData()对data属性做了初始化处理,如下:

function initData (vm) {
  var data = vm.$options.data;
  data = vm._data = typeof data === 'function'        //先获取data的值,这里data是个函数,也就是上面说的第1179行返回的匿名函数,可以看到返回的数据对象保存到了当前实例的_data属性上了
    ? getData(data, vm)
    : data || {};
  if (!isPlainObject(data)) {
    data = {};
    "
首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇canvas的基础入门 下一篇react-cli

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目