vue源码初看

文章目录

  • 前言
  • 一、 Vue 首次渲染的过程
  • 二、Vue 响应式原理
  • 三、虚拟 DOM 中 Key 的作用和好处
  • 四、Vue 中模板编译的过程
  • 总结


前言

本篇文章仅记录着个人初看vue源码的粗浅立即

一、 Vue 首次渲染的过程

1.vue初始化它的实例成员和静态成员
2.在初始化结束的时候调用vue的构造函数new Vue()
3.在构造函数中调用this._init()这个函数,这个函数是整个vue的入口
4.在_init函数中调用了vm. m o u n t , 这 个 mount,这个 mount,mount在src\platforms\web\entry-runtime-with-compiler.js中,首先判断是否传入
render函数,如果没有会获取template选项,如果template还没有,会把el中的内容作为模板,把模板编译成render函数,
通过compileFunction()函数生成render()渲染函数,然后把render函数存入到options选项中 options.render=render
5.然后调用src\platforms\web\runtime\index.js下的KaTeX parse error: Undefined control sequence: \core at position 110: …(this,el)函数在src\̲c̲o̲r̲e̲\instance\liftc…createElement),调用用户实例化Vue传入的render()或者编译template生成的render(),
当render()执行完后,返回生成的VNode(虚拟dom),然后调用vm._update(vnode,…),_update方法调用了vm.patch(vm. e l , v n o d e ) 方 法 , 这 个 方 法 就 是 把 v n o d e 这 个 虚 拟 d o m 转 化 成 真 实 d o m , 并 且 挂 载 在 页 面 中 , 会 把 生 成 的 真 实 d o m 设 置 到 v m . el,vnode)方法,这个方法就是 把vnode这个虚拟dom转化成真实dom,并且挂载在页面中,会把生成的真实dom设置到vm. el,vnode),vnodedomdomdomvm.el中
Watcher实例创建完后触发mounted钩子函数,挂载结束,最终返回vm(Vue实例)

二、Vue 响应式原理

1.首先从Vue实例的init方法开始,在init中先调用initState初始化vue实例的状态,在initState方法中调用了initData,initData是把data属性注入到Vue实例上,
并且调用observe把data对象转成响应式的对象
2.observe(value)接收一个要处理的对象,位置是在src\core\observer\index.js中,判断value是否是对象,如果不是直接返回,再判断value对象是否有__ob__属性,
如果有的话,代表之前做过响应式处理直接返回,如果没有则为这个value对象创建observer对象,最后把这个observer对象返回
3.创建observer对象,需要找到Oberver这个类,位置在src\core\observer\index.js文件下,在这个类的构造函数中,首先会给value对象定义不可枚举的__ob__属性,
并且把当前observer对象记录到当前__ob__属性里,然后进行数组的响应化处理和对象的响应化处理,数组的响应化处理是设置数组的特殊的几个方法,比如pop,shift,sort等,
这些方法会改变原数组,当这些方法被调用的时候要去发送通知notify,发送通知是找到数组对象对应的ob(observer对象),再找到这个observer中的dep,调用dep.notify方法,
更改完数组的这些方法后,遍历数组的每一个成员对每一个成员再去调用observe,如果这个成员也是对象的话也会把这个对象转成响应式的对象。如果当前value是对象的话。此时
会调用walk方法,walk方法就是遍历对象的属性,对每一个属性调用defineReactive方法
4.defineReactive方法位置在src\core\observer\index.js,在此方法中会为每一个属性创建dep对象,让dep去收集依赖,如果当前属性是对象的话会调用observe,然后给属性定义
getter和setter,在getter中去收集依赖,如果这个属性的值是对象,它也要为这个子对象收集依赖,最后返回属性的值,在setter中,先把新值保存下来,如果新值是对象的话,也要调用
observe,然后发送通知调用dep.notify
5.收集依赖的时候首先会执行watcher对象的get方法,get方法中会调用pushTarget方法,此方法会把当前watcher对象记录到Dep.target属性中,访问data中的属性的时候去收集依赖,
当访问属性的时候会触发defineReactive中的getter,在getter中会收集依赖,会把属性对应的watcher添加到dep的subs数组中,就是为属性收集依赖,如果这个属性的值也是对象,
此时要创建一个childOb对象,要为这个子对象收集依赖,目的是子对象发生变化的时候可以发送通知
6.当数据发送变化的时候,会调用dep.notify发送通知,它会调用watcher对象的update方法,update方法会去调用queueWatcher方法,queueWatcher方法会去判断watcher是否被处理了,
如果没有被处理会添加到quene队列中,并调用flushSchedulerQuene方法,此方法是刷新任务队列作用,在此方法中,会触发beforeUpdate钩子函数,然后调用watcher.run这个方法,
在run方法中会调用watcher.get方法,get方法会调用watcher.getter方法,getter()方法调用updateComponent,这种情况是渲染watcher。然后清空上一次的依赖,重置watcher中的一些状态,
接着触发actived钩子函数和updated钩子函数

三、虚拟 DOM 中 Key 的作用和好处

设置key属性,便于跟踪每个节点的身份,从而重新重用排序现有元素,减少操作dom的次数

四、Vue 中模板编译的过程

1.入口函数compileToFunctions(template,…),先从缓存加载编译好的render函数,如果缓存没有调用compile(template,options)开始编译
2.在compile(template,options)函数中,首先合并选项options,然后调用baseCompile(template.trim(),finalOptions)编译模板,compile核心是合并选项options,真正处理模板
是在baseCompile函数中完成的
3.baseCompile函数首先调用parse把模板字符串template转成AST tree(AST对象/抽象语法树),然后调用optimize对抽象语法树进行优化,标记AST tree静态语法树所有sub trees静态根节点,
静态根节点不需要每次被重绘,patch过程中会跳过静态根节点,最后调用generate,把优化后的AST tree(AST对象),转化成JS字符串代码
4.compile执行完后,会返回到入口函数compileToFunctions中,它里面通过调用createFunction会把字符串的JS代码转成函数,当render和staticRenderFns创建完毕,它们最终都会被挂载到
Vue实例的options选项对应的属性上
5.在模板不要写过多的无意义的空格和换行,否则生成的AST 对象会保存这些空格和换行,存储在内存中(vue3.0不会保存空格和换行)

总结

学海无涯,初看vue的博大精深,感叹大佬的思维严谨

你可能感兴趣的:(大前端学习)