zoukankan      html  css  js  c++  java
  • vue computed 源码分析

    我们来看看computed的实现。最简单的一个demo如下:

    <html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    </head>
    <body>
    <div id="app">
      <div name="test">{{computeA}}</div>
    
    </div>
    </body>
    <script src="vue.js"></script>
    <script type="text/javascript">
      new Vue({
      el: '#app',
      data: function () {
        return {
          firstName: 111,
          lastName: 222
        }
      },
      computed: {
        computeA: function () {
          return this.firstName + ' ' + this.lastName
        }
      },
      created(){
        setTimeout(
          () => {
            this.firstName = 333;
          },1000
        )
      }
    })
    </script>
    </html>
    

      

    1在初始化实例创建响应式的时候。对options中的computed做了特殊处理:

    function initComputed (vm, computed) {
      var watchers = vm._computedWatchers = Object.create(null);
    
      for (var key in computed) {
        var userDef = computed[key];
        var getter = typeof userDef === 'function' ? userDef : userDef.get;
        {
          if (getter === undefined) {
            warn(
              ("No getter function has been defined for computed property "" + key + ""."),
              vm
            );
            getter = noop;
          }
        }
        // create internal watcher for the computed property.
        watchers[key] = new Watcher(vm, getter, noop, computedWatcherOptions);//为每一个computed项目订制一个watcher
    
        // 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)) {
          defineComputed(vm, key, userDef);
        } 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);
          }
        }
      
    
    function defineComputed (target, key, userDef) {
      if (typeof userDef === 'function') {
        sharedPropertyDefinition.get = createComputedGetter(key);
        sharedPropertyDefinition.set = noop;
      } else {
        sharedPropertyDefinition.get = userDef.get
          ? userDef.cache !== false
            ? createComputedGetter(key)
            : userDef.get
          : noop;
        sharedPropertyDefinition.set = userDef.set
          ? userDef.set
          : noop;
      }
      Object.defineProperty(target, key, sharedPropertyDefinition);
    }
    
    function createComputedGetter (key) {//构造该computed的get函数
      return function computedGetter () {
        var watcher = this._computedWatchers && this._computedWatchers[key];
        if (watcher) {
          if (watcher.dirty) {
            watcher.evaluate();//收集该watcher的订阅
          }
          if (Dep.target) {
            watcher.depend();//同一为这一组订阅再加上组件re-render的订阅(该订阅负责更新组件)
          }
          return watcher.value
        }
      }
    }
    

      组件初始化的时候。computed项和data中的分别建立响应式。data中的数据直接对属性的get,set做数据拦截。而computed则建立一个新的watcher,在组件渲染的时候。先touch一下这个computed的getter函数。将这个watcher订阅起来。这里相当于这个computed的watcher订阅了firstname和lastname。touch完后。Dep.target此时又变为之前那个用于更新组件的。再通过watcher.depend()将这个组统一加上这个订阅。这样一旦firstname和lastname变了。同时会触发两个订阅更新。其中一个便是更新组件。重新re-render的函数。

  • 相关阅读:
    phpwind管理权限泄露漏洞
    CGI Hack与Webshell研究资料整理
    深入浅出net泛型编程[转载]
    加上checkbox的treeview控件源程序
    BCB消息消息机制
    开源ZPU介绍
    带复选框可以多选的组合框控件 TCheckCombobox,非常完美
    别人用delphi写的很简单实用的多列功能的treeview treelistview
    智能DVR视频监控系统,源代码
    delphi事件参数sender的用法例程
  • 原文地址:https://www.cnblogs.com/smzd/p/8624272.html
Copyright © 2011-2022 走看看