乱写 我也不是很明白(草稿暂存)

Vue首次渲染过程

第一步、Vue初始化,实例成员、静态成员
首先进行vue的初始化,即初始化实例成员及静态成员.

第二步、new Vue()
初始化结束以后,调用vue的构造函数new Vue(),在构造函数中调用this._init()方法

第三步、this.init()
this.init()相当于整个项目的入口,在这个方法中,最终调用vm.$mount()

**第四步、vm. m o u n t ( ) ∗ ∗ 这 个 mount()** 这个 mount()mount()是src/platform/web/entry-runtime-with-compiler.js中定义的,核心作用是把模板编译为render函数,判断是否有render选项,如果没有,则会获取template选项,如果template也没有,会把el中的内容作为模板,通过compileToFunctions()方法将模板编译为render函数,编译好以后,将render存入到options.render中。

**第五步、vm. m o u n t ( ) ∗ ∗ 调 用 s r c / p l a t f o r m s / w e b / r u n t i m e / i n d e x . j s 文 件 中 的 mount()** 调用src/platforms/web/runtime/index.js文件中的 mount()src/platforms/web/runtime/index.jsmount方法,这个方法中会重新获取el,因为如果是运行时版本的话,是不会走entry-runtime-with-compiler.js这个入口中获取el,所以如果是运行时版本的话,我们会在runtime/index.js的$mount()中重新获取el。

第六步、mountComponent(this,el)
这个方法在src/core/instance/lifecycle.js中定义的,首先判断是否有render选项,如果没有但是传入了模板,并且当前是开发环境,则发出警告(运行时版本不支持编译器),触发beforeMount钩子函数(开始挂载之前),定义updateComponents函数但是并未调用,这个函数中调用render()和update()两个方法,render是生成虚拟dom,update是将虚拟dom转化为真实dom并挂载到页面上,

创建Watcher实例对象,创建时,传递函数updateComponents,然后调用get方法,创建完毕后,触发钩子函数mounted(),挂载结束,返回vue实例。

第七步、Watcher.get()
创建完watcher,会调用一次get,在get方法中会调用updateComponent(),updateComponent会调用实例化时传入的render()或者是编译模板以后生成的render(),返回vnode。然后调用vm._update(),调用vm.__patch__方法,将虚拟dom转化为真实dom并挂载到页面上,将生成的真实dom记录到vm.$el()中。

Vue响应式原理简述

数据响应式是指,当数据发生变化自动更新视图,不需要手动操作dom,

第一步、入口,initState()
vm状态的初始化,整个响应式是从init方法中开始的,在init方法中,调用initState方法初始化状态,在initState方法中调用initData(),将data属性注入到vue实例上,并且调用observe()将其转化为响应式对象,observe是响应式的入口

第二步、observe(value)
位于src/core/observer/index.js,首先判断value是否是对象,如果不是对象直接返回,判断value对象是否有

ob,如果有证明value已经做过响应化处理,是响应式数据,则直接返回,如果没有,则在第三步创建observer对象,并将其返回。

第三步、Observe()
位于src/core/observer/index.js,给value对象定义不可枚举的__ob__属性,记录当前的observer对象,进行数组的响应化处理,设置数组中的方法push、pop、sort等,这些方法会改变原数组,所以当这些方法被调用的时候,会发送通知,找到observe对象中的dep,调用dep.notify()方法,然后调用数组中的每一个成员,对其进行响应化处理,如果成员是对象,也会将转化为响应式对象,如果value是对象的话,会调用walk(),遍历对象中的每一个成员,调用defineReactive()

第四步、defineReactive
src/core/observer/index.js,为每一个属性创建dep对象,如果当前属性是对象,递归调用observe().

getter:为每一个属性收集依赖,如果当前属性是对象,也为对象的每一个属性收集依赖,最终返回属性值。

setter:保存新值,如果新值是对象,则调用observe,派发更新(发送通知),调用dep.notify()

第五步、依赖收集
在watcher对象的get方法中调用pushTarget,会把当前的watcher记录Dep.target属性,访问的data成员的时候收集依赖,访问值的时候会调用defineReactive的getter中收集依赖,把属性对应的watcher对象添加到dep的subs数组中,如果属性是对象,则给childOb收集依赖,目的是子对象添加和删除成员时发送通知。

第六步、Watcher
当数据发生变化时,会调用dep.notify(),调用watcher对象的update()方法,在update方法中会调用queueWatcher(),方法中会判断watcher是否被处理,如果没有,则将其添加到queue队列中,并调用flushSchedulerQueue()刷新任务队列,在flushSchedulerQueue中,会触发beforeUpdate钩子函数,然后调用watcher.run(),然后清空上一次的依赖,触发actived钩子函数,触发update钩子函数。

Vue模板编译的过程

模板编译的主要目的是将模板template转化为渲染函数render

抽象语法树:AST,使用对象的形式描述树形的代码结构

模板编译是将模板字符串首先转化为AST对象,然后优化AST对象,优化的过程是在标记静态根节点,然后吧优化号的AST对象转化为字符串形式的代码,最终把字符串形式代码通过newFunction转化为匿名函数,这个匿名函数就是最终生成的函数render函数,模板编译就是啊模板字符串转化为渲染函数。

入口函数,compileToFunctions(template…)

1、check cache

先从缓存中加载编译好的render函数, 读取缓存中的CompiledFunctionResult对象,如果有直接返回,缓存中没有,则调用compile(template,options)

2、compile

合并options, baseCompile(template.trim(),finalOptions)

3、 baseCompile(template.trim(),finalOptions)

parse(),将模板字符串首先转化为AST对象
optimize()
标记AST tree中的静态sub trees
检测到静态子树,设置为静态,不需要在每次重新渲染的时候重新生成节点
patch阶段跳过静态子树
generate(),AST tree生成js的创建代码

4、compileToFunctions(template…)

继续把上一步中生成的字符串形式js代码转化为函数

  • createFunction()
  • options.render = render
  • options.staticRenderFns = staticRenderFns
  • render和staticRenderFns 初始化完毕,挂载到vue实例的options对应的属性中
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值