设为首页 加入收藏

TOP

Vue.js 源码分析(六) 基础篇 计算属性 computed 属性详解(一)
2019-09-17 18:48:34 】 浏览:35
Tags:Vue.js 源码 分析 基础 计算 属性 computed 详解

模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护,比如:

    <div id="example">{{ message.split('').reverse().join('') }}</div>
    <script>
        var app = new Vue({
            el:'#example',
            data:{message:'hello world'}
        })
    </script>

这样模板不再是简单的声明式逻辑,必须看一段时间才能意识到,对于这些复杂逻辑,需要使用计算属性,例如:

    <div id="example">{{ reversedMessage}}</div>
    <script>
        var app = new Vue({
            el:'#example',
            data:{message:'hello world'},
            computed:{
                reversedMessage:function(){return this.message.split('').reverse().join('')}
            }
        })
    </script>

在模板中可以把computed当作data属性来使用

computed是一个对象,每个键是计算属性的值,值有两种使用方法:值是一个函数,或者值是一个包含get和set的对象

 

 源码分析


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

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) {              
    initData(vm);                 
  } else {
    observe(vm._data = {}, true /* asRootData */);
  }
  if (opts.computed) { initComputed(vm, opts.computed); }   //如果定义了computed,则调用initComputed初始化computed if (opts.watch && opts.watch !== nativeWatch) {
    initWatch(vm, opts.watch);
  }
}
initComputed函数如下:
var computedWatcherOptions = {lazy: true};                  //计算属性的配置信息
function initComputed (vm, computed) {                      //第3424行
  // $flow-disable-line
  var watchers = vm._computedWatchers = Object.create(null);            //定义一个空对象,没有原型的,用于存储所有计算属性对应的watcher
  // computed properties are just getters during SSR
  var isSSR = isServerRendering();

  for (var key in computed) {                                           //遍历每个计算属性
    var userDef = computed[key];                                            //将计算属性的值保存到userDef里面
    var getter = typeof userDef === 'function' ? userDef : userDef.get;     //如果userDef是一个函数则赋值给getter,否则将userDef.get赋值给getter
    if ("development" !== 'production' && getter == null) {
      warn(
        ("Getter is missing for computed property \"" + key + "\"."),
        vm
      );
    }

    if (!isSSR) {
      // create internal watcher for the computed property.
      watchers[key] = new Watcher(                                          //创建一个内部的watcher给计算属性用
        vm,
        getter || noop,
        noop,
        computedWatcherOptions
      );
    }

    // component-defined computed properties are already defined on the
    // component prototype. We only need to define computed properties defined
    // at instantiation here.
    if (!(key in vm)) {                                                     //如果key在vm中没有定义 注:组件的计算属性在模块加载的时候已经被定义在了原型上面了
      defineComputed(vm, key, userDef);                                       //则执行defineComputed()函数
    } else {
      if (key in vm.$data) {
        warn(("The computed property \"" + key + "\" is already defined in data."), vm);
      } else if (vm.$options.props && key in vm.$options.props) {
        warn(("The computed property \"" + key + "\" is already defined as a prop."), vm);
      }
    }
  }
}

writer by:大沙漠 QQ:22969969

 
 

注:对于计算属性的Watcher来说,它的lazy属性为true,因此new watcher()结尾时不会执行get()方法,而是直接返回undefined(在3127行)(求值会等到该计算属性被调用时才求值的)

回到initComputed()函数,defineComputed()定义如下:

function defineComputed (     //第3465行
  target,
  key,
  userDef
) {
  var shouldCache = !isServerRendering();
  if (typeof userDef === 'function') {            //如果userDef为函数,则默认为get
    sharedPropertyDefinition.get
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇cnblogs停止更新,同步到个人博客.. 下一篇跳转常规 -- 为什么不要使用404、..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目