zoukankan      html  css  js  c++  java
  • vue源码解析实例(一)

     vue.js文件

    config属性解析

    var config = ({
        optionMergeStrategies: Object.create(null),
        //是否发出警告
        silent: false,
         //启动时显示生产模式提示消息
        productionTip: "development" !== 'production',
        //是否启用devtools
        devtools: "development" !== 'production',
        //是否记录性能
        performance: false,
        //用于监视程序错误的错误处理程序
        errorHandler: null,
        //用于监视程序警告的警告处理程序
        warnHandler: null,
        //忽略某些自定义元素
        ignoredElements: [],
        //v-on为自定义用户关键字
        keyCodes: Object.create(null),
        //检查是否保留了标记,以便不能将其注册为组件。  
        isReservedTag: no,
        //检查是否保留了属性,以便它不能用作组件属性。
        isReservedAttr: no,
        //检查标记是否为未知元素。
        isUnknownElement: no,
        //获取元素的名称空间
        getTagNamespace: noop,
        //解析特定平台的实际标记名称
        parsePlatformTagName: identity,
        //检查属性是否必须使用属性(例如value)绑定
        mustUseProp: no,
        //异步执行更新。用于Vue测试Utils,如果设置为false,这将显著降低性能
        async: true,
        //由于遗留原因而暴露
        _lifecycleHooks: LIFECYCLE_HOOKS
      });

     //生命周期

    LIFECYCLE_HOOKS
    var SSR_ATTR = 'data-server-rendered';
    //这边有个vue SSR的定义。服务端渲染
    
      var ASSET_TYPES = [
        'component',
        'directive',
        'filter'
      ];
    //组件可以拥有的资产类型列表,这边有几个过滤器,自定义,组件的定义,后面看到后打锚点
    
      var LIFECYCLE_HOOKS = [
        'beforeCreate',
        'created',
        'beforeMount',
        'mounted',
        'beforeUpdate',
        'updated',
        'beforeDestroy',
        'destroyed',
        'activated',
        'deactivated',
        'errorCaptured',
        'serverPrefetch'
      ];
    //生命周期的钩子
    解析简单的路径。
    首先定义了一个正则。其中source属性返回一个字符串,该字符串包含regexp对象的源文本,并且它不包含两边的两个正斜杠和任何标志。
    test() 方法检查字符串是否匹配bailRE
    segments将path用split分割成字符串数组,一个循环(obj)是什么?
      var unicodeRegExp = /a-zA-Zu00B7u00C0-u00D6u00D8-u00F6u00F8-u037Du037F-u1FFFu200C-u200Du203F-u2040u2070-u218Fu2C00-u2FEFu3001-uD7FFuF900-uFDCFuFDF0-uFFFD/;
    

      

      var bailRE = new RegExp(("[^" + (unicodeRegExp.source) + ".$_\d]"));
      function parsePath (path) {
        if (bailRE.test(path)) {
          return
        }
        var segments = path.split('.');
        return function (obj) {
          for (var i = 0; i < segments.length; i++) {
            if (!obj) { return }
            obj = obj[segments[i]];
          }
          return obj
        }
      }
     

     

    公开util

    // exposed util methods.
        // NOTE: these are not considered part of the public API - avoid relying on
        // them unless you are aware of the risk.
        Vue.util = {
          warn: warn,
          extend: extend,
          mergeOptions: mergeOptions,
          defineReactive: defineReactive$$1
        };

    1.warn

     var warn = noop;
        warn = function (msg, vm) {
          var trace = vm ? generateComponentTrace(vm) : '';
    
          if (config.warnHandler) {
            config.warnHandler.call(null, msg, vm, trace);
          } else if (hasConsole && (!config.silent)) {
            console.error(("[Vue warn]: " + msg + trace));
          }
        };
    warn是一个function,初始化的时候,只定义了一个noop方法,如果在开发环境,这个warn是可以接收两个参数,一个是msg,一个是vm,msg不用说,大家都知道这里是一个提示信息,vm就是实例化的vue对象,或者是实例化的vue对象的某一个属性。
    接下来是一个三元表达式trace,用来判断调用warn方法时,是否有传入了vm,如果没有,返回的是空,如果有,那么就返回generateComponentTrace这个function,这个方法初始化的值也是noop,什么都没有做,目的是解决流量检查问题
    如果config.warnHandler被使用者变更成了值,不在是null,那么就把config.warnHandler的this指向null,其实就是指向的window,再把msg, vm, trace传给config.warnHandler
    否则判断当前环境使用支持cono1.sle并且开启了警告,如果开启了,那就把警告提示信息打印出来
    2.extend
    /**
       * Mix properties into target object.
       */
      function extend (to, _from) {
        for (var key in _from) {
          to[key] = _from[key];
        }
        return to
      }

    这个方法是用于做继承操作的,接收两个值to, _from,将属性_from混合到目标对象to中,如果to存在_from中的属性,则直接覆盖,最后返回新的to

    3.mergeOptions

    将两个选项对象合并为一个新对象,用于实例化和继承的核心实用程序(这是一个很重要的方法,在后面多处会用到,所以建议大家仔细看这里)

    /**
       * Merge two option objects into a new one.
       * Core utility used in both instantiation and inheritance.
       */
      function mergeOptions (parent,child,vm) {
        {
          checkComponents(child);
    //检查组件是否是有效的名字---不能是h5元素标签
        }
    
        if (typeof child === 'function') {
          child = child.options;
        }
    //如果child是一个function的话,则把child自己指向child的options属性
    
        normalizeProps(child, vm);
    //camelize:
    //把名称格式为“xx-xx”的变为“xxXx”,这里接收的是当前的props属性值,一个字符串
    
        normalizeInject(child, vm);
        normalizeDirectives(child);
    
    //normalizeProps:规范属性,确保所有的props的规范都是基于对象的
    
        // Apply extends and mixins on the child options,
        // but only if it is a raw options object that isn't
        // the result of another mergeOptions call.
        // Only merged options has the _base property.
        if (!child._base) {
          if (child.extends) {
            parent = mergeOptions(parent, child.extends, vm);
          }
          if (child.mixins) {
            for (var i = 0, l = child.mixins.length; i < l; i++) {
              parent = mergeOptions(parent, child.mixins[i], vm);
            }
          }
        }
    
        var options = {};
        var key;
        for (key in parent) {
          mergeField(key);
        }
        for (key in child) {
          if (!hasOwn(parent, key)) {
            mergeField(key);
          }
        }
        function mergeField (key) {
          var strat = strats[key] || defaultStrat;
          options[key] = strat(parent[key], child[key], vm, key);
        }
        return options
      }

    4.defineReactive(拦截属性)

    function defineReactive$$1 (
        obj,
        key,
        val,
        customSetter,
        shallow
      ) {
        var dep = new Dep();
    
        var property = Object.getOwnPropertyDescriptor(obj, key);
    // getOwnPropertyDescriptor 返回描述对象
        if (property && property.configurable === false) {
          return
        }
    //property.configurable === false,不可扩展
    
        // cater for pre-defined getter/setters
        var getter = property && property.get;
        var setter = property && property.set;
        if ((!getter || setter) && arguments.length === 2) {
          val = obj[key];
        }
    
        var childOb = !shallow && observe(val);
        Object.defineProperty(obj, key, {
          enumerable: true,
          configurable: true,
          get: function reactiveGetter () {
            var value = getter ? getter.call(obj) : val;
    //有没有自定义的get函数
            if (Dep.target) {
              dep.depend();
              if (childOb) {
                childOb.dep.depend();
                if (Array.isArray(value)) {
                  dependArray(value);
                }
              }
            }
            return value
          },
          set: function reactiveSetter (newVal) {
            var value = getter ? getter.call(obj) : val;
            /* eslint-disable no-self-compare */
            if (newVal === value || (newVal !== newVal && value !== value)) {
              return
            }
            /* eslint-enable no-self-compare */
            if (customSetter) {
              customSetter();
            }
            // #7981: for accessor properties without setter
            if (getter && !setter) { return }
            if (setter) {
              setter.call(obj, newVal);
            } else {
              val = newVal;
            }
            childOb = !shallow && observe(newVal);
            dep.notify();
          }
        });
      }

     Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。

    这里,其实就是用来实现响应式数据的核心之一,主要做的事情就是数据的更新, Object.defineProperty() 
    多多关照,多多指教,共同成长 ---嘉煠
  • 相关阅读:
    二叉树——Java实现
    Java实现单链表的增删查改及逆置打印
    常见排序——Java实现
    [导入]Interesting Finds: 2007.12.10
    [导入]Interesting Finds: 2007.12.09
    [导入]Interesting Finds: 2007.12.12
    [导入]Interesting Finds: 2007.12.06
    [导入]Interesting Finds: 2007.12.07
    [导入]Interesting Finds: 2007.12.04
    [导入]Interesting Finds: 2007.12.05
  • 原文地址:https://www.cnblogs.com/jiayeyuan/p/14447567.html
Copyright © 2011-2022 走看看