源码中文社区

源码内容

config

optionMergeStrategies
silent: false
productionTip: true
devtools: true
performance: false
errorHandler: null
warnHandler: null
ignoredElements: []
keyCodes: {}
isReservedTag: ƒ (a, b, c)
isReservedAttr: ƒ (a, b, c)
isUnknownElement: ƒ (a, b, c)
getTagNamespace: ƒ noop(a, b, c)
parsePlatformTagName: ƒ (_)
mustUseProp: ƒ (a, b, c)
_lifecycleHooks: (10) ["beforeCreate", "created", "beforeMount", "mounted", "beforeUpdate", "updated", "beforeDestroy", "destroyed", "activated", "deactivated"]

warn、tip、formatComponentName、repeat、generateComponentTrace

判断浏览器环境

var inBrowser = typeof window !== 'undefined';
var UA = inBrowser && window.navigator.userAgent.toLowerCase();
var isIE = UA && /msie|trident/.test(UA);
var isIE9 = UA && UA.indexOf('msie 9.0') > 0;
var isEdge = UA && UA.indexOf('edge/') > 0;
var isAndroid = UA && UA.indexOf('android') > 0;
var isIOS = UA && /iphone|ipad|ipod|ios/.test(UA);
var isChrome = UA && /chrome\/\d+/.test(UA) && !isEdge;

new _Set()

has: ƒ has()
add: ƒ add()
delete: ƒ delete()
clear: ƒ clear()
entries: ƒ entries()
forEach: ƒ forEach()
values: ƒ values()
keys: ƒ values()

new Dep()

id: 2
subs: []
__proto__:
    addSub: ƒ addSub(sub)
    removeSub: ƒ removeSub(sub)
    depend: ƒ depend()
    notify: ƒ notify()

strats = config.optionMergeStrategies

propsData: ƒ (parent, child, vm, key)
el: ƒ (parent, child, vm, key)
data: ƒ ( parentVal, childVal, vm )
beforeCreate: ƒ mergeHook( parentVal, childVal )
created: ƒ mergeHook( parentVal, childVal )
beforeMount: ƒ mergeHook( parentVal, childVal )
mounted: ƒ mergeHook( parentVal, childVal )
beforeUpdate: ƒ mergeHook( parentVal, childVal )
updated: ƒ mergeHook( parentVal, childVal )
beforeDestroy: ƒ mergeHook( parentVal, childVal )
destroyed: ƒ mergeHook( parentVal, childVal )
activated: ƒ mergeHook( parentVal, childVal )
deactivated: ƒ mergeHook( parentVal, childVal )
components: ƒ mergeAssets(parentVal, childVal)
directives: ƒ mergeAssets(parentVal, childVal)
filters: ƒ mergeAssets(parentVal, childVal)
watch: ƒ (parentVal, childVal)
computed: ƒ (parentVal, childVal)
inject: ƒ (parentVal, childVal)
methods: ƒ (parentVal, childVal)
props: ƒ (parentVal, childVal)
provide: ƒ mergeDataOrFn( parentVal, childVal, vm )

perf = inBrowser && window.performance;

VNode

tag: undefined
data: undefined
children: undefined
text: undefined
elm: undefined
ns: undefined
context: undefined
functionalContext: undefined
key: undefined
componentOptions: undefined
componentInstance: undefined
parent: undefined
raw: false
isStatic: false
isRootInsert: true
isComment: false
isCloned: false
isOnce: false
asyncFactory: undefined
asyncMeta: undefined
isAsyncPlaceholder: false

Watcher

componentVNodeHooks

init
prepatch
insert
destroy

initMixin

_init
    initLifecycle(vm);
    initEvents(vm);
    initRender(vm);
    callHook(vm, 'beforeCreate');
    initInjections(vm);
    initState(vm);
    initProvide(vm);
    callHook(vm, 'created');
    ...
    vm.$mount(vm.$options.el);

stateMixin

$data、$props、$set、$delete 、$watch

eventsMixin

$on、$once、$off、$emit

lifecycleMixin

_update、$forceUpdate、$destroy

renderMixin

$nextTick、_render
Vue.prototype._o = markOnce;
Vue.prototype._n = toNumber;
Vue.prototype._s = toString;
Vue.prototype._l = renderList;
Vue.prototype._t = renderSlot;
Vue.prototype._q = looseEqual;
Vue.prototype._i = looseIndexOf;
Vue.prototype._m = renderStatic;
Vue.prototype._f = resolveFilter;
Vue.prototype._k = checkKeyCodes;
Vue.prototype._b = bindObjectProps;
Vue.prototype._v = createTextVNode;
Vue.prototype._e = createEmptyVNode;
Vue.prototype._u = resolveScopedSlots;
Vue.prototype._g = bindObjectListeners;

KeepAlive

name: "keep-alive"
abstract: true
props: {include: Array(3), exclude: Array(3)}
created: ƒ created()
destroyed: ƒ destroyed()
watch: {include: ƒ, exclude: ƒ}
render: ƒ render()

builtInComponents = {
KeepAlive: KeepAlive
}

initGlobalAPI

initUse(Vue);
initMixin$1(Vue);
initExtend(Vue);
initAssetRegisters(Vue);

nodeOps

createElement: ƒ createElement$1(tagName, vnode)
createElementNS: ƒ createElementNS(namespace, tagName)
createTextNode: ƒ createTextNode(text)
createComment: ƒ createComment(text)
insertBefore: ƒ insertBefore(parentNode, newNode, referenceNode)
removeChild: ƒ removeChild(node, child)
appendChild: ƒ appendChild(node, child)
parentNode: ƒ parentNode(node)
nextSibling: ƒ nextSibling(node)
tagName: ƒ tagName(node)
setTextContent: ƒ setTextContent(node, text)
setAttribute: ƒ setAttribute(node, key, val)

ref

create: ƒ create(_, vnode)
update: ƒ update(oldVnode, vnode)
destroy: ƒ destroy(vnode)

directives

create: ƒ updateDirectives(oldVnode, vnode)
update: ƒ updateDirectives(oldVnode, vnode)
destroy: ƒ unbindDirectives(vnode)

baseModules = [ref, directives]

attrs = {

create: updateAttrs,
update: updateAttrs

}

klass = {

create: updateClass,
update: updateClass

}

events = {

create: updateDOMListeners,
update: updateDOMListeners

}

domProps = {

create: updateDOMProps,
update: updateDOMProps

}

style = {

create: updateStyle,
update: updateStyle

}

platformModules = [attrs, klass, events, domProps, style, transition]

modules = platformModules.concat(baseModules)

patch = createPatchFunction({

nodeOps: nodeOps,
modules: modules

})

transitionProps = {

name: String,
appear: Boolean,
css: Boolean,
mode: String,
type: String,
enterClass: String,
leaveClass: String,
enterToClass: String,
leaveToClass: String,
enterActiveClass: String,
leaveActiveClass: String,
appearClass: String,
appearActiveClass: String,
appearToClass: String,
duration: [Number, String, Object]

}

patch

$mount

compile 编译

compileToFunctions

|-- parse 解析
|-- optimize 优化
|-- generate 生成

概念

UI = render(state)

state 和 UI 都是用户定的,不变的是这个 render() ==> vue

变化侦测:追踪状态

Angular 中是通过`脏值检查流程`来实现变化侦测
在 React 是通过`对比虚拟DOM`来实现变化侦测

Object.defineProperty

实现数据的读写观察

Observer

Observer类会通过递归的方式把一个对象的所有属性都转化成可观测对象

在 getter 中收集依赖,在 setter 中通知依赖更新

依赖管理器 Dep 

Watcher

Array 拦截器

虚拟 DOM

用一个JS对象来描述一个DOM节点

VNode 类:
注释节点
文本节点
元素节点
组件节点
函数式组件节点
克隆节点

DOM-Diff ===> patch

创建节点,删除节点和更新节点

render

  • 抽象语法数(AbstractSyntaxTree,AST)
  1. 模板解析阶段:将一堆模板字符串用正则等方式解析成抽象语法树AST;
  2. 优化阶段:遍历AST,找出其中的静态节点,并打上标记;
  3. 代码生成阶段:将AST转换成渲染函数;
  • 优化

在AST中找出所有静态节点并打上标记;
在AST中找出所有静态根节点并打上标记;

生命周期流程

  1. new Vue()
  2. vm_init
    -> 初始化 lifecycle
    -> 初始化 Events
    -> 初始化 Render
    -> 调用钩子 beforeCreate
    -> 初始化 State
     -> 依赖收集 (props\data\computed\watch\methods)
    -> 调用钩子 created
    挂载组件 vm.$mount
  3. vm.$mount
    -> compile()
    -> 调用钩子 beforeMount
    -> new Watcher
     -> vm_render createElement -> VNode Tree
     -> vm_update 渲染真实DOM
    -> 调用钩子 mount
  4. compile()
    -> parse -> AST
    -> optimize 优化
    -> generate 生成
  5. render function
    – touch –> getter\setter –> watcher – > update
    – VDOM Tree
  6. patch()
    -> patchVnode
    -> updateChikldren
  7. Real Dom