以下是Vue结构体声明的核心代码,是跨平台共享的核心代码。为什么说是跨平台共享呢?这主要是指不同的平台(web和weex)会在vue.prototype上丰富自己的特性(属性和方法),比如比较重要的__patch__方法,以及平台特定的组件和指令。从'./init'导入{initMixin}从'./state'导入{stateMixin}从'./render'导入{eventsMixin}从'./events'导入{lifecycleMixin}从'./lifecycle'import{warn}from'../util/index'functionVue(options){if(process.env.NODE_ENV!=='production'&&!(thisinstanceofVue)){warn('Vue是一个构造函数,应该用`new`关键字调用')}this._init(options)}initMixin(Vue)stateMixin(Vue)eventsMixin(Vue)lifecycleMixin(Vue)renderMixin(Vue)exportdefaultVue其中各种Mixin主要丰富原型链属性或者上面的方法:initMixin:Declarevue.prototype.init后面会读到,见prototypeinitstateMixin:declarevue.prototype.[$data|$props]属性,以及$set,$delete,$watch方法eventsMixin:声明vue.prototype.[$on|优惠价|$一次|$emit]方法,让vm本身具备注册和触发事件的能力lifecycleMixin:declarevue.prototype.[_update|$强制更新|$destroy]方法renderMixin:声明vue.prototype.[_render|$nextTick]方法,以及一系列内部helpers工具函数,通过(_字母)别名方法切换到Web平台视角首先,我们只看web平台目录,添加[_patch_|$挂载到vue.prototype]方法,并安装特定于平台的指令和组件来构建Vue.options。原型init的主要部分是:initLifecycle(vm)initEvents(vm)initRender(vm)callHook(vm,'beforeCreate')initInjections(vm)//解析数据前的注入/propsinitState(vm)initProvide(vm)//resolveprovideafterdata/propscallHook(vm,'created')还有一部分是:看。第一部分:initLifecycle:声明vm实例属性[$parent|$根|$孩子|$参考|观察者|在父级的$children中注册子级vminitEvents:声明vm实例属性[_events|_hasHookEvent],并更新组件事件侦听器或注销事件initRender:声明vm实例属性[_vnode|_静态树|$选项|$vnode|$插槽|$scopedSlots|_c|$创建元素|$属性|$listeners],其中$attrs和$listeners是响应式属性,但是很浅。也就是defineReactive声明的时候,指定shallow为true,看看defineReactive。在某些情况下,保持声明键的原始getter和setter方面。传入shallow来控制对象的key的值是否需要继续包含在响应式管理中。具体来说,通过闭包Dep示例将密钥合并到响应系统中。通过dep.depend把target:[Watcher]放到自己的subs中好像调用了watcher的addDep方法,这个方法会判断是否已经依赖了depdepend(){if(Dep.target){Dep.target.addDep(this)}}本质上最终还是调用了dep的addSub方法addDep(dep:Dep){constid=dep.idif(!this.newDepIds.has(id)){this.newDepIds.add(id)this.newDeps.push(dep)if(!this.depIds.has(id)){dep.addSub(this)}}}这样,dep就有了watcher(viasubs),watcher那里同样是dep(通过newDepIds)Dep类Dep类有一个静态属性target,代表当前的watcher,全局唯一。一次只会有一个正在进行的观察者,但目标观察者是一个堆栈并且具有匹配的推送和弹出。操作,分别对应pushTarget和popTarget,这种设计可以支持嵌套调用和watcher处理。Dep类通过depend方法与watcher建立双向关联,watcher通过dep的addSub方法关联dep,dep类通过dep的removeSub方法取消关联。Dep类使用notify方法通知关联的wathcer[]代表Dep进行更新和操作。响应式系统中observed的所有Dep实例统一分配Uid,即Uid++Watcher类watcher分为renderWatcher和userWatcher,两者都会关联到vm的_watchers[]列表中,renderWatcher还会关联vm的_watcherlazy-watcher的值,通过Watcher的evaluate设置Dep的notify来触发watcher的更新,区分几种情况。如果它是惰性的,则会设置脏标志。如果是sync,则直接同步执行getter,执行cb回调。在其他情况下,queueWatcherWatcher的get执行会在执行getter之前pushTarget进行初始化分析,这样如果getter执行中有相关的dep.depend,就会关联当前watcher和depWatcher。监听路径的解析算法是简单的a.b.c属性点切分,但是解析后的结果是一个closurewatcher的回调执行只有在其值发生变化,或者值为对象,或者是deep时才会执行。具有一定惰性的queueWatcher的算法是如果watcher队列还没有被flush过。只需添加它。如果已经flush但是还没有到,就查找替换刚刚flush的待执行队列,否则将下一波队列安排到nextTick。Watcher代表响应式系统中的订阅者。所有Watcher实例统一进行Uid赋值,即Uid++callHook:执行对应的hook函数和vm自身的hook事件监听(如vm.$on('hook:created'))initInjections:简称initState:声明vm实例属性[_watchers],用于状态系统中的props、methods、data、computed、watch等概念初始化initProvide:简称callHook:同上
