ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
[TOC] ****** ## 6 [\core\instance\] 实例核心目录 ### 6-1 目录层次 ~~~ \core\instance\ index.js ;核心实例接口 lifecycle.js ;核心生命周期接口 proxy.js ;核心代理接口 state.js ;核心状态接口 events.js ;核心事件接口 render.js ;核心渲染接口 ~~~ ![](https://box.kancloud.cn/2016-05-06_572bf787b395e.jpg) ### 6-2 (index.js) 核心实例接口 >[info] import ~~~ ;(导入)代理,状态,渲染,事件,生命周期,基础工具 import { initProxy } from './proxy' import { initState, stateMixin } from './state' import { initRender, renderMixin } from './render' import { initEvents, eventsMixin } from './events' import { initLifecycle, lifecycleMixin, callHook } from './lifecycle' import { nextTick, mergeOptions } from '../util/index' ~~~ >[info] module ~~~ ;全局uid let uid = 0 ;Vue._init()初始化接口 Vue.prototype._init = function (options) { // a uid this._uid = uid++ // a flag to avoid this being observed this._isVue = true // merge options this.$options = mergeOptions( this.constructor.options, options || {}, this ) ;初始化代理 if (process.env.NODE_ENV !== 'production') { initProxy(this) } else { this._renderProxy = this } ;初始化生命周期,事件 initLifecycle(this) initEvents(this) ;回调init钩子 callHook(this, 'init') ;初始化Vue内部状态 initState(this) ;回调created钩子 callHook(this, 'created') ;初始化渲染 initRender(this) } ;Vue.$nextTick()接口 Vue.prototype.$nextTick = function (fn) { nextTick(fn, this) } ;安装其他核心实例接口 stateMixin(Vue) eventsMixin(Vue) lifecycleMixin(Vue) renderMixin(Vue) ~~~ >[info] export ~~~ (导出)Vue实例化接口 export default function Vue (options) { this._init(options) } ~~~ ![](https://box.kancloud.cn/2016-05-06_572bf787b395e.jpg) ### 6-3 (lifecycle.js) 核心生命周期接口 >[info] import ~~~ ;(导入)监视器接口,基础攻击,依赖接口,虚拟机DOM接口 import Watcher from '../observer/watcher' import { warn, validateProp, remove } from '../util/index' import { observerState } from '../observer/index' import { updateListeners } from '../vdom/helpers' ~~~ >[info] module ~~~ ;生命周期(lifecycle)初始化接口 export function initLifecycle (vm) { ;初始化参数$options const options = vm.$options ;父节点与根节点 vm.$parent = options.parent vm.$root = vm.$parent ? vm.$parent.$root : vm if (vm.$parent) { vm.$parent.$children.push(vm) } ;孩子节点,索引对象 vm.$children = [] vm.$refs = {} ;状态初始化 vm._isDestroyed = false vm._isBeingDestroyed = false } ;生命周期安装接口 export function lifecycleMixin (Vue) { ;1 Vue._mount() VM挂载dom节点接口 Vue.prototype._mount = function () { ;检查渲染函数 if (!this.$options.render) { this.$options.render = () => this.$createElement('div') if (process.env.NODE_ENV !== 'production') { if (this.$options.template) { warn( 'You are using the runtime-only build of Vue where the template ' + 'option is not available. Either pre-compile the templates into ' + 'render functions, or use the compiler-included build.', this ) } else { warn( 'Failed to mount component: template or render function not defined.', this ) } } } ;渲染静态树 const staticRenderFns = this.$options.staticRenderFns if (staticRenderFns) { this._staticTrees = new Array(staticRenderFns.length) for (let i = 0; i < staticRenderFns.length; i++) { this._staticTrees[i] = staticRenderFns[i].call(this._renderProxy) } } ;this._watcher,this._update(),this._mounted状态修改 this._watcher = new Watcher(this, this._render, this._update) this._update(this._watcher.value) this._mounted = true ;ready钩子回调处理 if (this.$root === this) { callHook(this, 'ready') } return this } ; 2 Vue._update() 刷新节点接口 Vue.prototype._update = function (vnode) { ;检查挂载状态,调用节点刷新前beforeUpdate钩子 if (this._mounted) { callHook(this, 'beforeUpdate') } ;父节点 const parentNode = this.$options._parentVnode vnode.parent = parentNode ;调用this.__patch__生成虚拟节点this._vnode if (!this._vnode) { this.$el = this.__patch__(this.$el, vnode) } else { this.$el = this.__patch__(this._vnode, vnode) } this._vnode = vnode ;挂载到父级节点上 if (parentNode) { parentNode.elm = this.$el } ;调用更新完后updated钩子 if (this._mounted) { callHook(this, 'updated') } } ; 3 Vue._updateFromParent() 从父节点刷新接口 Vue.prototype._updateFromParent = function (propsData, listeners, parentVnode, renderChildren) { this.$options._parentVnode = parentVnode this.$options._renderChildren = renderChildren if (propsData && this.$options.props) { observerState.shouldConvert = false const propKeys = this.$options.propKeys for (let i = 0; i < propKeys.length; i++) { const key = propKeys[i] this[key] = validateProp(this, key, propsData) } observerState.shouldConvert = true } if (listeners) { const oldListeners = this.$options._parentListeners this.$options._parentListeners = listeners updateListeners(listeners, oldListeners || {}, (event, handler) => { this.$on(event, handler) }) } } ; 4 Vue.$forceUpdate() 强制刷新接口 Vue.prototype.$forceUpdate = function () { this._watcher.update() } ; 5 Vue.$destroy() 强制销毁接口 Vue.prototype.$destroy = function () { if (this._isDestroyed) { return } callHook(this, 'beforeDestroy') this._isBeingDestroyed = true const parent = this.$parent if (parent && !parent._isBeingDestroyed) { remove(parent.$children, this) } if (this._ref) { this._context.$refs[this._ref] = undefined } let i = this._watchers.length while (i--) { this._watchers[i].teardown() } if (this._data.__ob__) { this._data.__ob__.removeVm(this) } this._isDestroyed = true callHook(this, 'destroyed') this.$off() } } ~~~ >[info] export ~~~ ;(导出)生命周期初始化接口 export function initLifecycle (vm){} ;(导出)生命周期安装接口 export function lifecycleMixin (Vue) {} ;(导出)钩子回调接口 export function callHook (vm, hook) {} ~~~ ![](https://box.kancloud.cn/2016-05-06_572bf787b395e.jpg) ### 6-4 (proxy.js) 核心代理接口 >[info] import ~~~ ;基础工具 import { warn, makeMap } from '../util/index' ~~~ >[info] module ~~~ ;声明三个变量 let hasProxy, proxyHandlers, initProxy ;实现三个功能函数 if (process.env.NODE_ENV !== 'production') { const allowedGlobals = makeMap( 'Infinity,undefined,NaN,isFinite,isNaN,' + 'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' + 'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl' ) ;判断平台是否支持Proxy功能 hasProxy = typeof Proxy !== 'undefined' && Proxy.toString().match(/native code/) ;注册Proxy的处理函数 proxyHandlers = { has (target, key) { const has = key in target const isAllowedGlobal = allowedGlobals(key) if (!has && !isAllowedGlobal) { warn( `Trying to access non-existent property "${key}" while rendering.`, target ) } return !isAllowedGlobal } } ;初始化代理initProxy() 注册vm._renderProxy属性 initProxy = function initProxy (vm) { if (hasProxy) { vm._renderProxy = new Proxy(vm, proxyHandlers) } else { vm._renderProxy = vm } } } ~~~ >[info] export ~~~ ;(导出)initProxy()作为注册 vm._renderProxy属性接口 export { initProxy } ~~~ ![](https://box.kancloud.cn/2016-05-06_572bf787b395e.jpg) ### 6-5 (state.js) 核心状态接口 >[info] import ~~~ ;(导入)Watcher,Dep,observer,util等接口 import Watcher from '../observer/watcher' import Dep from '../observer/dep' import { observe, defineReactive, observerState, proxy, unproxy } from '../observer/index' import { warn, hasOwn, isArray, isPlainObject, bind, validateProp } from '../util/index' ~~~ >[info] module ~~~ ;Vm内部状态初始化接口 ;包括Props,Data,Computed,Methods,Watch等属性的初始化 export function initState (vm) { vm._watchers = [] initProps(vm) initData(vm) initComputed(vm) initMethods(vm) initWatch(vm) } ;(1) Props属性初始化 function initProps (vm) { ;获取初始化props参数 const props = vm.$options.props const propsData = vm.$options.propsData ;检查是否存在props,然后进行初始化 if (props) { ;获取props的keys, const keys = vm.$options.propKeys = Object.keys(props) ;判断当前vm是否是根节点,标记其状态 const isRoot = !vm.$parent observerState.shouldConvert = isRoot ;注册propsData到props中 for (let i = 0; i < keys.length; i++) { const key = keys[i] defineReactive(vm, key, validateProp(vm, key, propsData)) } ;根节点状态标记 observerState.shouldConvert = true } } ;(2) Data属性初始化 function initData (vm) { ;获取初始化data参数 let data = vm.$options.data data = vm._data = typeof data === 'function' ? data() : data || {} ;参数有效性检查 if (!isPlainObject(data)) { data = {} process.env.NODE_ENV !== 'production' && warn( 'data functions should return an object.', vm ) } ;获取Data的keys const keys = Object.keys(data) let i = keys.length ;注册keys键到vm while (i--) { proxy(vm, keys[i]) } ;进行数据监视 observe(data, vm) } ;空函数声明 function noop () {} ;(3) Computed属性初始化 function initComputed (vm) { ;获取初始化computed参数 const computed = vm.$options.computed ;检查初始化参数并进行处理 if (computed) { ;computed属性信息合成 for (const key in computed) { const userDef = computed[key] const def = { enumerable: true, configurable: true } if (typeof userDef === 'function') { def.get = makeComputedGetter(userDef, vm) def.set = noop } else { def.get = userDef.get ? userDef.cache !== false ? makeComputedGetter(userDef.get, vm) : bind(userDef.get, vm) : noop def.set = userDef.set ? bind(userDef.set, vm) : noop } ;注册computed属性到vm Object.defineProperty(vm, key, def) } } } ;生成computed的get函数 function makeComputedGetter (getter, owner) { ;生成watcher const watcher = new Watcher(owner, getter, null, { lazy: true }) return function computedGetter () { if (watcher.dirty) { watcher.evaluate() } if (Dep.target) { watcher.depend() } return watcher.value } } ;(4) Method属性初始化 function initMethods (vm) { ;获取初始化methods参数 const methods = vm.$options.methods ;绑定method到vm if (methods) { for (const key in methods) { vm[key] = bind(methods[key], vm) } } } ;(5) Watch属性初始化 function initWatch (vm) { ;获取初始化watch参数 const watch = vm.$options.watch ;检查watch参数,创建watch注册到vm if (watch) { for (const key in watch) { const handler = watch[key] if (isArray(handler)) { for (let i = 0; i < handler.length; i++) { createWatcher(vm, key, handler[i]) } } else { createWatcher(vm, key, handler) }function createWatcher (vm, key, handler) { let options if (isPlainObject(handler)) { options = handler handler = handler.handler } if (typeof handler === 'string') { handler = vm[handler] } vm.$watch(key, handler, options) } } } } ;创建watch注册到vm function createWatcher (vm, key, handler) { let options if (isPlainObject(handler)) { options = handler handler = handler.handler } if (typeof handler === 'string') { handler = vm[handler] } vm.$watch(key, handler, options) } ;状态操作安装接口 export function stateMixin (Vue) { ;$vm.data注册 Object.defineProperty(Vue.prototype, '$data', { get () { return this._data }, set (newData) { if (newData !== this._data) { setData(this, newData) } } }) ;Vue.$watch注册 Vue.prototype.$watch = function (fn, cb, options) { options = options || {} options.user = true const watcher = new Watcher(this, fn, cb, options) if (options.immediate) { cb.call(this, watcher.value) } return function unwatchFn () { watcher.teardown() } } } ;_data属性的修改函数 function setData (vm, newData) { ;获取data比较参数 newData = newData || {} const oldData = vm._data vm._data = newData ;遍历删除不存在的key let keys, key, i keys = Object.keys(oldData) i = keys.length while (i--) { key = keys[i] if (!(key in newData)) { unproxy(vm, key) } } ;注册添加的key keys = Object.keys(newData) i = keys.length while (i--) { key = keys[i] if (!hasOwn(vm, key)) { proxy(vm, key) } } ;强制刷新处理 oldData.__ob__.removeVm(vm) observe(newData, vm) vm.$forceUpdate() } ~~~ >[info] export ~~~ ;(导出)状态初始化接口 export function initState (vm){} ;(导出)状态操作安装接口 export function stateMixin (Vue){} ~~~ ![](https://box.kancloud.cn/2016-05-06_572bf787b395e.jpg) ### 6-6 (events.js) 核心事件接口 >[info] import ~~~ ;(导入)数组转换,vdom的事件接口 import { toArray } from '../util/index' import { updateListeners } from '../vdom/helpers' ~~~ >[info] module ~~~ ;事件初始化接口 export function initEvents (vm) { ;创建vm._events vm._events = Object.create(null) ;获取初始化_parentListeners参数 const listeners = vm.$options._parentListeners ;检查参数是否存在并安装事件监听接口 if (listeners) { updateListeners(listeners, {}, (event, handler) => { vm.$on(event, handler) }) } } ~~~ ~~~ ;事件操作安装接口 export function eventsMixin (Vue) { ;Vue.$on()事件安装接口 Vue.prototype.$on = function (event, fn) { (this._events[event] || (this._events[event] = [])) .push(fn) return this } ;Vue.$once()事件安装接口 Vue.prototype.$once = function (event, fn) { const self = this function on () { self.$off(event, on) fn.apply(this, arguments) } on.fn = fn this.$on(event, on) return this } ;Vue.$off()事件注销接口 Vue.prototype.$off = function (event, fn) { ;获取参数 if (!arguments.length) { this._events = Object.create(null) return this } ;注册 const cbs = this._events[event] if (!cbs) { return this } ;注销所有事件回调 if (arguments.length === 1) { this._events[event] = null return this } ;特殊事件注销 let cb let i = cbs.length while (i--) { cb = cbs[i] if (cb === fn || cb.fn === fn) { cbs.splice(i, 1) break } } return this } ;Vue.$emit()事件触发接口 Vue.prototype.$emit = function (event) { ;获取事件回调接口 let cbs = this._events[event] ;调用事件对应回调 if (cbs) { cbs = cbs.length > 1 ? toArray(cbs) : cbs const args = toArray(arguments, 1) for (let i = 0, l = cbs.length; i < l; i++) { cbs[i].apply(this, args) } } } } ~~~ >[info] export ~~~ ;(导出)事件初始化接口 export function initEvents (vm) {} ;(导出)事件操作安装接口 export function eventsMixin (Vue) {} ~~~ ### 6-7 (render.js) 核心渲染接口 >[info] import ~~~ (导入)vdom操作接口与基础攻击 import createElement from '../vdom/create-element' import { flatten } from '../vdom/helpers' import { bind, isArray, isObject, renderString } from 'shared/util' import { resolveAsset } from '../util/options' ~~~ >[info] module ~~~ ;渲染实例 export const renderState = { activeInstance: null } ;渲染初始化接口 export function initRender (vm) { ;创建vm_vnode,vm_mounted,vm._staticTress, vm._vnode = null vm._mounted = false vm._staticTrees = null ;创建vm.$slots,vm.$createElement vm.$slots = {} vm.$createElement = bind(createElement, vm) ;检查初始化el参数,并调用vm.$mount实现挂载 if (vm.$options.el) { vm.$mount(vm.$options.el) } } ;渲染操作安装接口 export function renderMixin (Vue) { ;Vue._render()接口 Vue.prototype._render = function () { ;保存上个渲染实例,设置当前渲染实例 const prev = renderState.activeInstance renderState.activeInstance = this ;获取render,_renderChildren渲染参数 const { render, _renderChildren } = this.$options ;检查_renderChildren渲染参数,调用resolveSlots() if (_renderChildren) { resolveSlots(this, _renderChildren) } ;虚拟vnode const vnode = render.call(this._renderProxy) ;恢复上个渲染实例 renderState.activeInstance = prev ;返回虚拟vnode return vnode } ;Vue.__h__()渲染接口 Vue.prototype.__h__ = createElement ;Vue.__toString__()渲染接口 Vue.prototype.__toString__ = renderString const identity = _ => _ ;Vue.__renderFilter__()渲染接口 Vue.prototype.__resolveFilter__ = function (id) { return resolveAsset(this.$options, 'filters', id, true) || identity } ;Vue.__renderList__()渲染接口 Vue.prototype.__renderList__ = function (val, render) { let ret, i, l, keys, key if (isArray(val)) { ret = new Array(val.length) for (i = 0, l = val.length; i < l; i++) { ret[i] = render(val[i], i, i) } } else if (typeof val === 'number') { ret = new Array(val) for (i = 0; i < val; i++) { ret[i] = render(i + 1, i, i) } } else if (isObject(val)) { keys = Object.keys(val) ret = new Array(keys.length) for (i = 0, l = keys.length; i < l; i++) { key = keys[i] ret[i] = render(val[key], i, key) } } return ret } ;Vue.__registerRef__()渲染接口 Vue.prototype.__registerRef__ = function (key, ref, vFor, remove) { const refs = this.$refs if (remove) { if (vFor) { remove(refs[key], ref) } else { refs[key] = undefined } } else { if (vFor) { if (refs[key]) { refs[key].push(ref) } else { refs[key] = [ref] } } else { refs[key] = ref } } } } function resolveSlots (vm, renderChildren) { if (renderChildren) { const children = flatten(renderChildren()) const slots = { default: children } let i = children.length let name, child while (i--) { child = children[i] if ((name = child.data && child.data.slot)) { const slot = (slots[name] || (slots[name] = [])) if (child.tag === 'template') { slot.push.apply(slot, child.children) } else { slot.push(child) } children.splice(i, 1) } } vm.$slots = slots } } ~~~ >[info] export ~~~ ;(导出)渲染实例 export const renderState={} ;(导出)渲染初始化接口 export function initRender (vm) {} ;(导出)渲染安装接口 export function renderMixin (Vue) {} ~~~ ![](https://box.kancloud.cn/2016-05-06_572bf6c0146bf.png)