vue-简单例子初始化

1. vue

(function (global, factory) {
    //根据当前环境中用的ADM或COMMONJS格式的模块规范或者未用模块管理规范,将Vue(函数)对象返回给对应变量属性(或全局变量),
    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
    typeof define === 'function' && define.amd ? define(factory) :
    (global.Vue = factory());
}(this, (function () { 'use strict';
.....
return Vue$3;

})
));

1.立即执行函数

  (function(global,factory){

   }(this,(...)) )

  将this和vue的构建函数传入匿名函数,根据当前环境进行vue初始化,如果是ADM模块管理下则传入define函数,Commonjs模块管理输出vue函数给module.exports,否则直接挂在全局变量上。

2.factory()

  初始化Vue框架。

  2.1 cached(fn)

  cached(fn):缓存函数,提供fn缓存处理函数,然后存在内部变量cache中。

  2.2 资源类型 

//资源类型
var ASSET_TYPES = [
'component',//组件
'directive',//指令
'filter'//过滤器
];
//生命周期内的函数钩子
var LIFECYCLE_HOOKS = [
'beforeCreate',
'created',
'beforeMount',
'mounted',
'beforeUpdate',
'updated',
'beforeDestroy',
'destroyed',
'activated',
'deactivated',
'errorCaptured'
];
View Code

  2.3 合并strats

    mergeHook合并LIFECYCLE_HOOKS钩子策略,将父级和子级的钩子函数和props属性合并为数组。

    mergeAssets当存在一个虚拟节点(实例创建),我们需要将构造函数选项和实例选项和父级选项三方式合并。 AssetsType:组件、指令、过滤器

    strats.watch:一个观察者哈希值不应该覆盖另一个观察者的哈希值,所以我们将它们合并为数组。

    其他策略哈希:strats.props ,strats.methods ,strats.inject,strats.computed

  2.4 全局消息通达

    微任务、宏任务触发函数初始化。构建任务

    宏任务macroTimerFunc:异步调用flushCallbacks回调函数列表中的函数setImmediate或MessageChannel或setTimeout。

     微任务microTimerFunc:如果有Promise.then则使用这个构建微任务,否则微任务实际执行宏任务。

  2.5初始化渲染代理initProxy

  

 1 //has代理处理对象
 2   var hasHandler = {
 3     has: function has (target, key) {
 4       var has = key in target;
 5       var isAllowed = allowedGlobals(key) || key.charAt(0) === '_';
 6       if (!has && !isAllowed) {
 7         warnNonPresent(target, key);
 8       }
 9       //key不能是全局变量(或属性)也不能是_打头的‘私有’属性
10       return has || !isAllowed
11     }
12   };
13 //get代理处理对象
14   var getHandler = {
15     get: function get (target, key) {
16       if (typeof key === 'string' && !(key in target)) {
17         warnNonPresent(target, key);
18       }
19       return target[key]
20     }
21   };
22   //
23   initProxy = function initProxy (vm) {
24     if (hasProxy) {//如果()环境内置proxy代理
25       // determine which proxy handler to use
26       var options = vm.$options;  //_withStripped 被卸载?待完善
27       //渲染代理定义,如果vm对象定义中有render等则用get代理处理函数否则使用has代理处理函数
28       var handlers = options.render && options.render._withStripped
29         ? getHandler
30         : hasHandler;
31       vm._renderProxy = new Proxy(vm, handlers);
32     } else {
33       vm._renderProxy = vm;
34     }
35   };
36 
37 
38 ........
39 
40 Vue.prototype._render = function () {
41 
42     .....
43      vnode = render.call(vm._renderProxy, vm.$createElement);
44     ....
45 }    
View Code

this就是vm._renderProxy渲染代理,生成html代码时需要读取数据,代理会过滤非枚举的属性对象。返回 target[key]时,又会触发Object.definePropery拦截。

  2.6 设置渲染帮助函数

    installRenderHelpers

   2.8初始化混合

    initMixin(Vue$3);

    设置 Vue.prototype._init  全局初始化函数

  2.9状态混合

  stateMixin(Vue$3);

  设置$data、$props 只读属性,分别来自_data 、_props。定义全局方法$set、$delete、$watch(用户使用的侦听方法)。

  2.10 事件混合

    eventsMixin(Vue$3);

    在Vue原型上定义$on、$off、$once、$emit事件处理函数。

    $on时将event设置到_events上维护,vm._events[event]。

  2.11 生命周期混合
  lifecycleMixin(Vue$3);

  原型上定义_update、$forceUpdate、$destroy、

  2.12渲染混合
  renderMixin(Vue$3);

  首先installRenderHelpers调用渲染辅助函数,定义$nextTick、_render、

  2.13初始化全局api

  initGlobalAPI:config、 Vue.util 、Vue.set、Vue.delete、Vue.nextTick 、Vue.options、Vue.options.components

  2.13.1 初始化用户插件使用函数

  initUse(Vue);

   Vue.use 初始化插件,plugin.install,加载到Vue上。

  2.13.2 初始化混合
    initMixin$1(Vue);

    Vue.mixin用户混合选项options

  2.13.3 初始化扩展
  initExtend(Vue);  子组件继承

  2.13.4 初始化资源注册
  initAssetRegisters(Vue);

  3.

以上是vue自身初始化,下面用户使用vue

new Vue

生命周期函数:

mergeOptions:合并实例的components、directives、filters等属性。

initProxy: vm._renderProxy = new Proxy(vm, handlers);如果vm  vue实例是带render的组件实例则添加gethandler处理函数,否则添加hashandler

beforecreate之前:初始化vue实例代理、初始化化声明周期,初始化事件,初始化渲染

created之前:初始化注入、初始化state状态(data/props)、初始化provide

function Vue$3 (options) {
  if ("development" !== 'production' &&
    !(this instanceof Vue$3)
  ) {
    warn('Vue is a constructor and should be called with the `new` keyword');
  }
  this._init(options);
}

1.vm._uid  

  Vue节点的uid唯一编号设置,并给特殊的Vue节点设置_isVue标记,避免被监听。

  1.1初始化内部组件或者合并参数选项

  initInternalComponent(vm, options); :  如果options参数中表明是一个组件则初始化内部组件。优化内部组件实例化,因为动态选项合并很慢,并且内部组件选项都不需要特殊处理。

vm.constructor.options主要由之前VUE自执行时初始化的内容:components组件、directives指令、filters过滤。

  1. components:{KeepAlive: {…}, Transition: {…}, TransitionGroup: {…}}
  2. directives:{model: {…}, show: {…}}
  3. filters:{}

 resolveConstructorOptions :如果没有super父级继承属性,则直接返回上面三个属性(另_base)

mergeOptions (parent,child,vm) 然后将父级选项和子级选项合并,

首先检查child.components(如果child下还有组件的话)中的组件名称是否有效,无效则会给出提示信息或根据配置提示函数做处理。

   1.1.1 规范化属性

    normalizeProps(child, vm); 驼峰化属性名称

  normalizeInject(child, vm); 规范化注入属性对象options.inject
  normalizeDirectives(child);规范化指令,如果指令对象的某个属性值是函数则将该属性绑定到一个对象{ bind: def, update: def },其中def就是原指令函数。

  child.extends 将子组件中的选项内容合并到父组件上去。

  child.mixins Mixin 钩子与组件自身钩子同名时,Mixin 钩子按照传入顺序依次调用,并在调用组件自身的钩子之前被调用。

  mergeField ()根据默认初始的components、directives、filters、_base(Vue$3)四个选项属性的各自策略将parent和child响应的属性合并

  然后再将子组件中含有的属性和父组件中没有的属性合并到父组件(第一次newVue的时候的父级是之前加载vue就执行产生的默认四个选项的属性对象)中。

1.2 initProxy

  vm._renderProxy = new Proxy(vm, handlers);如果vm  vue实例是带render的组件实例则添加gethandler处理函数,否则添加hashandler。比如new Vue直接传el而不是手动添加render函数则对vue实例加_renderProxy 代理。

1.3    initLifecycle(vm);

  找到vm父节点并将该vue实例存入父节点的children中。

  vm节点挂父节点、根节点 vm.$parent = parent;

  初始化children节点

  $refs相关参数、_watcher、_inactive、相关标记:_directInactive、_isMounted标记、_isDestroyed、_isBeingDestroyed

  

1.4 initEvents(vm)

  根据 listeners = vm.$options._parentListeners;添加组件更新监听器,

   Vue.prototype.$on  : 将事件处理函数挂在vm._events的事件对象上  (vm._events[event] || (vm._events[event] = [])).push(fn);

1.5 initRender(vm);

  初始与渲染相关的属性_vnode、 _staticTrees、解析$slots插槽、$scopedSlots

  vm._c :封装了createElement 创建元素关键函数,主要是内部使用

  vm.$createElement:也封装了vm.$createElement函数,可供外部调用

  defineReactive:添加对$attrs 和$listeners 属性对象 建立双向绑定

回调beforecreate钩子

 callHook(vm, 'beforeCreate');

2. create部分

2.1initInjections(vm);

  初始化注入:

2.2  initState(vm);

  初始组件的  vm._watchers  监听器,props、methods、data、computed、watch

   initData (vm):

    mergedInstanceDataFn 合并数据对象函数,对data添加代理 proxy(vm, "_data", key);,key的来源是vm.$options.data;的data的关键字, proxy在vm对象上对获取_data上的key属性进行属性代理劫持,将key直接挂在vue实例的第一层,如果调用vm.key时,从target的_data的对应key上获取。

    observe(data, true /* asRootData */);为options中的data,尝试给一个value值创建观察者实例,如果成功观察,返回新的观察者,如果值已经有一个观察者,则返回现有的观察者。

  initProvide(vm); 

以上  callHook(vm, 'created'); 回调created事件。

3. 装载el节点

   vm.$mount(vm.$options.el);

  Vue$3.prototype.$mount

  将 template/el 转换成 render function,如果是el,则使用  template = getOuterHTML(el);获取html模板,

   createCompileToFunctionFn 解析模板

    var compiled = compile(template, options);将模板解析为一个对象,

    res.render = createFunction(compiled.render, fnGenErrors);

v-show :调用toggleDisplay

猜你喜欢

转载自www.cnblogs.com/xiaozhuyuan/p/8981073.html