[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)
- 概述
- 框架结构
- 编译入口(\entries)
- web-compiler.js(web编译)
- web-runtime.js(web运行时)
- web-runtime-wih-compiler.js(web编译运行)
- web-server-renderer.js(web服务器渲染)
- 核心实现 (\core)
- index.js(核心入口)
- config.js(核心配置)
- core\util(核心工具)
- core\observer(双向绑定)
- core\vdom(虚拟DOM)
- core\global-api(核心api)
- core\instance(核心实例)
- 模板编译(\compiler)
- compiler\parser(模板解析)
- events.js(事件解析)
- helper.js(解析助手)
- directives\ref.js(ref指令)
- optimizer.js(解析优化)
- codegen.js(渲染生成)
- index.js(模板编译入口)
- web渲染(\platforms\web)
- compiler(web编译目录)
- runtime(web运行时目录)
- server(web服务器目录)
- util(web工具目录)
- 服务器渲染(\server)
- render-stream.js(流式渲染)
- render.js(服务器渲染函数)
- create-renderer.js(创建渲染接口)
- 框架流程
- Vue初始化
- Vue视图数据绑定
- Vue数据变化刷新
- Vue视图操作刷新
- 框架工具
- 基础工具(\shared)
- 模板编译助手
- 核心实例工具
- Web渲染工具
- 基础原理
- dom
- string
- array
- function
- object
- es6
- 模块(Module)
- 类(Class)
- 函数(箭头)
- 字符串(扩展)
- 代理接口(Proxy)
- 数据绑定基础
- 数据绑定实现
- mvvm简单实现
- mvvm简单使用
- vdom算法
- vdom实现
- vue源码分析资料