created

beforeCreate

beforeMount

mounted

1

怎么编译:

ast =  parse(template()

code = generate(ast)

renderFn = new Function(code)

=> renderFn() =>VNode

modifier

  • .stop
  • .prevent
  • .once
  • .passive


@keyup.enter

@keyup.enter.exact


.sync



.lazy

.number

.trim

data()

props:

computed:

watch:

inject/resolve

method

observable()

watcher('path', vm, noop)

initLifecycle

initEvent

func render():VNode

patch(pre, cur)

生成vm.$el

用vm.$el 替换el

update(){} 和nextTick()


nextTick():

  • 所有的子组件都已经渲染好


修改data

调用destroy()

beforeDestroy

销毁完成

更新数据

vm._watcher执行,patch,更新dom

beforeUpdate

更新完成

activited

deactivited

forceupdate

updateComponent = () => {
  vm._update(vm._render(), hydrating)
}
更新view

vm.$el = vm.__patch__(prevVnode, vnode)

new Watcher(vm, updateComponent, noop, {
  before () {
    if (vm._isMounted && !vm._isDestroyed) {
      callHook(vm, 'beforeUpdate')
    }
  } 
}, true /* isRenderWatcher */)


为什么不能在watch里使用箭头函数,我觉得没毛病啊。

不存在找不到的情况

compiler

{
  ast,
  render: code.render,
  staticRenderFns: code.staticRenderFns
}
declare type CompiledResult = {
  ast: ?ASTElement;
  render: string;
  staticRenderFns: Array<string>;
  stringRenderFns?: Array<string>;
  errors?: Array<string | WarningMessage>;
  tips?: Array<string | WarningMessage>;
};
function optimize(ast){
     // 找出静态节点,
// 做上标志
}
function parse(template, option):ASTElment {

}

reactive

notify()

for(let i = 0; i< subs.length -1 ;i--){

   watcher.update()

}

watcher.update()

queueWatcher

queue

  • sort()

object.defineProperty

  1. watcherQueue:所有的watcher放入此队列。


this._update(this.render())
updateComponetWatcher =  new Watcher(vm, updateComponent, noop, {
before () {
if (vm._isMounted && !vm._isDestroyed) {
callHook(vm, 'beforeUpdate')
}
}
}, true /* isRenderWatcher */)


vm._watcher == updateComponetWatcher

2. callbacks队列:准确叫法应该是nextTickCallbackQueue

  1. 存放下一个tick中所有需要执行的任务
  2. 包括flushWatcherQueue

解析nextTick()中的回调为什么一定在本次更新之后发。

  • nextTick


因为nextTick中的回调,都在下个tick中执行。所有本次tick执行,会把dom也更新了

sync会立刻执行

watcherQueue.

nextTick(flushWatcherQueue)

nextTick

flashCallback()执行callbacks中的回调

(包括flushWatcherQueue)

如果vm._watcher被执行(updateComponent)

执行就会触发所有'updated'事件

dep


1.watcher:

watcher.run()

2.如果不是watcher,

直接执行

结束

newValue = watcher.get()。 //重新收集依赖 => 如果是dom更新。

则get = () => this._update(this._render())


如果newValue !=oldVaue || isObject(newValue) || deep

都执行回调 

(回调中可能调用nextTick()方法,存入下一个tick中要执行的事件)

vdom(diff算法)

// 返回patch只有的VNode
func patch(preVNode, curVNode):VNode {
   if(preVnode不存在) {
        // 直接创建一个新的element。 return
    }
   if(curVNode不存在) {
     // 删除之前的节点 return
   }

  两个都存在。比较元素本身。
   if(是同一个节点){
     pathVNode(preVNode, curVNode)
  } else{
    // 用新节点替换掉老节点
  }


}

双端比较

func patchVNode(preVnode, vnode) {
 if(vnode.istatic() && preVNode.isstatic) {
   // 直接替换?
 }

 if(是文本节点) {
    //有变化就直接替换
 } else {
     // 真正打补丁的地方
     // 修改preVNode对应elements的属性
 }
  // 处理children
    判断子节点是否存在。3种情况.
    if(新老vnode的children都存在){
       updateChildren()
    }
 
}

node.type

//双端比较。主要处理位置的移动。diff算法
func updateChildren(parentEle,oldChildren:VNode[],children:VNode[]) {
   while(oldStart<oldEnd && newStart < newEnd) {
      // oldStart, oldEnd
      // newStart newEnd
      if(sameVNode(oldStart,newStart)){
         patch(),oldStart++,nweStart++
      }...一共4种情况
      else {
        c = oldChildren.find((child) => sameVnode(child,newChildren[0]))
        把c移动到开头。
        newStart++;
     }
}

   ///a b c d
   //a b c

  //a b c d 
  // a b c d e

 // a b C d
// a C d b



} 

vm._update

updated事件

VNode

struct VNode {


   text: 是否是文本节点. 如何判断的。在哪里判断的?

}

静态节点:                    

v-pre/文本节点?

vue源码剖析

vue源码剖析

2019-10-29 22:56:14 0 82
这里是评论

相关推荐