vue源码相关log...

1、响应式处理

let vm = new Vue({
     data() {
        return {
            name:'张三',
            age: 18,
            info:{  c: 'xxx' }
        }
     }
})

vue对传入得options挂载到vm上,执行initState(),总的初始化函数,初始化顺序为props、methods、data、computed、watch。

执行proxy方法,将_data上的数据代理到vm上,方便this.xxx访问。

observe(data),核心方法,递归遍历对象,通过defineReactive方法对对象属性的get、set进行拦截


image.png
问题 为什么对象数组分开处理

因为对象的属性一般不对太多,递归劫持完全是可行的,但是数组的个数不确定,如果太多(成千上万)每一个都去劫持get、set会影响性能。
所以对象deineProperty劫持,数组用变异方法去处理

遗留问题

对象的新增key 删除key 监听不到
数组只能通过变异方法去操作能触发响应式,arr[1]=xxx 不行,操作length也不行

2、模板渲染
查找options选项是否有el,没有再去$mount挂载,有el则为根节点
查找options是否有render函数,没有再去找template模板,再没有再去获取el的outHtml,最后都会转换成render函数

通过将template转换成render函数,也就是compileToFunctions方法

const render = compileToFunctions(template)
// 把生成的render函数赋值到options的render属性上
options.render = render
// compiler/index.js

const { parse } = require('./parse.js')
const { generate } = require('./codegen.js')

function compileToFunctions (template) {

    // 把传进来的template传入parse函数中,并生成抽象语法树(AST)
    // 抽象语法数是一个描述dom结构的树结构,包括html,css,js代码
    // 使用变量ast接收AST
    let ast = parse(template)

    // 把上面生成的AST传入generate函数中
    // 生成一个render格式的函数代码
    // 格式大概是类似_c('div',{id:"app"},_c('div',undefined,_v("hello"+_s(name)),_c('span',undefined,_v("world"))))
    // _c代表创建元素,_v代表创建文本,_s代表文Json.stringify--把对象解析成文本
    let code = generate(ast)


    // 使用with改变this指向,可以方便code里去获取this(也就是Vue实例)里的数据
    let renderFn = new Function(`with(this){return ${code}}`)

    // 返回这个生成的render函数
    return renderFn
}

module.exports = {
    compileToFunctions: compileToFunctions
}

let ast = parse(template) 模板转换成ast语法树,
let code = generate(ast) ast转换成render函数所需的语法 返回

3、挂载$mount
mountComponent执行render函数 生成vnode,
vnode就是个对象,包含{ tag,data,children,key,text }之类的属性,
patch(oldVnode, vnode)方法执行,将vnode转换成真实dom,挂载完成。

初次挂载总结

new Vue对options进行初始化,对data进行递归遍历监听get、set,编译template时,触发属性的get方法,get中对有dep对watcher进行收集,在set时候通过dep.notify(),循环watcher进行页面更新,也就触发了对应的响应式,编译完成template生成vnode,通过patch方法将vnode转换成真实dom挂载到页面上,挂载完成。

vue computed原理

首先Watcher有三种类型
渲染Watcher: data里的变量监听,负责通知html重新渲染
computed Watcher:负责通知conputed里的依赖此变量的属性进行修改
user Watcher: watch对象里面定义的key,通知对应的变量函数执行

defineReactive函数中,每个对象都会实例化自己的dep = new Dep(),get时会把watcher收集进dep里,watcher也会收集dep,互相收集是因为computed没有自己的dept,要用他依赖的dept去做更新

image.png

lazy:true的配置是conputed的缓存,第一次使用会进行计算值,并且用value去缓存值,dirty改为false,依赖不更新,dirty一直是false,就会一直去取value的值,就是缓存的原理。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 传送门vue技术揭秘:https://ustbhuangyi.github.io/vue-analysis/v2/...
    拾钱运阅读 691评论 0 2
  • vue面试题 一、vue优点 1.轻量级框架:只关注视图层,是一个构建数据的视图集合,大小只有几十kb; 2.简单...
    没糖_cristalle阅读 1,633评论 0 3
  • Vue.js面试题整理 一、什么是****MVVM****? MVVM是Model-View-ViewModel的...
    EmilWong阅读 273评论 0 0
  • 注: 路人读者请移步 => Huang Yi 老师的Vue源码阅读点这里, 我写这一篇笔记更倾向于以自问自答的形式...
    Xinxing_Li阅读 1,438评论 0 0
  • Vue.js实现原理 初始化创建Vue实例对象init过程会初始化生命周期,初始化事件中心,初始化渲染、执行bef...
    阿_洛阅读 271评论 0 0