Vuex原理
1.Vuex初始化import Vuex的时候,引用的是一个对象,定义在index.js中,他同样存在一个install方法,install中通过混入一个beforeCreate钩子函数,将options.store保存在所有组件的$store中,这个options.store就是实例化的Store对象。所以我们可以通过this.$store访问到这个实例。
1.1 Store实例化1234567891011121314151617181920212223const moduleA = { state: { ... }, mutations: { ... }, actions: { ... }, getters: { ... }}const moduleB = { state: { ... }, mutations: { ... }, actions: { ... }, getters: { ...
Vue全局API原理
1.Vue.util123456Vue.util = { warn, extend, mergeOptions, defineReactive,};
Vue.util是Vue内部的工具方法,不推荐业务组件去使用,因为可能随着版本发生变动,不开发第三方Vue插件会比较少用
2.Vue.set/Vue.delete123456789101112131415161718192021222324export function set(target: Array<any> | Object, key: any, val: any): any { // 如果是数组 直接调用我们重写的splice方法 可以刷新视图 if (Array.isArray(target) && isValidArrayIndex(key)) { target.length = Math.max(target.length, key); target.splice(key, 1, val); return val; ...
Vue计算属性原理
1.计算属性的初始化12345678910111213function initComputed(vm) { const computed = vm.$options.computed; const watchers = (vm._computedWatchers = {}); //用来存放计算watcher for (let k in computed) { const userDef = computed[k]; //获取用户定义的计算属性 const getter = typeof userDef === "function" ? userDef : userDef.get; //创建计算属性watcher使用 // 创建计算watcher lazy设置为true watchers[k] = new Watcher(vm, getter, () => {}, { lazy: true }); defineComputed(vm, k, u ...
Vue监听属性原理
1.监听属性的初始化12345678910111213141516171819202122232425262728// 初始化watchfunction initWatch(vm) { let watch = vm.$options.watch; for (let k in watch) { const handler = watch[k]; //用户自定义watch的写法可能是数组 对象 函数 字符串 if (Array.isArray(handler)) { // 如果是数组就遍历进行创建 handler.forEach((handle) => { createWatcher(vm, k, handle); }); } else { createWatcher(vm, k, handler); } }}// 创建watcher的核心function createWatcher(vm, exprO ...
Vue模板组件原理
123456789101112131415161718192021222324252627// 全局组件 Vue.component("parent-component", { template: `<div>我是全局组件</div>`, }); // Vue实例化 let vm = new Vue({ el: "#app", data() { return { aa: 1, }; }, // render(h) { // return h('div',{id:'a'},'hello') // }, template: `<div id="a"> hello 这是我自己写的Vue{{aa} ...
Vue的mixin原理
1.定义全局Mixin函数12345678910import {mergeOptions} from '../util/index'export default function initMixin(Vue){ Vue.mixin = function (mixin) { // 合并对象 this.options=mergeOptions(this.options,mixin) };}};initMixin(Vue);//在Vue的入口文件引入initMixin方法
2.mergeOptions方法1234567891011121314151617181920212223242526//先定义生命周期,合并生命周期,然后为生命周期队列添加合并方法//mixin核心方法export function mergeOptions(parent, child) { const options = {}; // 遍历父亲 for (let k i ...
Vue的Diff算法原理
1.patch核心渲染方法改写1const isRealElement = oldVnode.nodeType;//oldVnode是真实DOM代表初次渲染
当oldNode为真实DOM即初次渲染,反之为虚拟DOM,更新过程需要使用diff算法,算法中,判断新旧标签是否一致,同级比较,不一致则新替换旧。如果旧节点为文本节点,直接替换标签文本内容。如果不符合以上两种情况,直接把旧的虚拟DOM对应的真实DOM赋值给新的虚拟DOM的EL属性。其中包括子节点判断。diff算法主要进行同级比较!2.updateProperties更新属性1234567891011121314151617181920const newProps = vnode.data || {};//新的vnode属性const el = vnode.el;//真实节点for (const k in oldProps) { //新节点没有,则把老节点属性移除 if (!newProps[k]) { el.removeAttribute(k); } ...
Vue异步更新原理
1.watcher更新的改写1234567891011export default class Watcher { update() { // 每次watcher进行更新的时候 是否可以让他们先缓存起来 之后再一起调用 // 异步队列机制 queueWatcher(this); } run() { // 真正的触发更新 this.get(); }}
在update更新方法中加入异步队列的机制
2.queueWatcher实现队列机制123456789101112131415161718192021222324let queue = [];let has = {};function flushSchedulerQueue() { for (let index = 0; index < queue.length; index++) { // 调用watcher的run方法 执行真正的更新操作 queue[index].run ...
Vue响应式更新原理
1.定义Watcher123456789101112131415161718192021// 全局变量id 每次new Watcher都会自增let id = 0;export default class Watcher { constructor(vm, exprOrFn, cb, options) { this.vm = vm; this.exprOrFn = exprOrFn; this.cb = cb; //回调函数 比如在watcher更新之前可以执行beforeUpdate方法 this.options = options; //额外的选项 true代表渲染watcher this.id = id++; // watcher的唯一标识 // 如果表达式是一个函数 if (typeof exprOrFn === "function") { this.getter = exprOrFn; } // 实例化就会默认调用get方法 this.get( ...
虚拟DOM渲染原理
1.组件挂载入口通过compile转化成render之后,调用mountComponent核心方法进行组件实例的挂载。该函数与生命周期相关,位于beforeMount和mounted生命周期钩子之间。
2.核心方法mountComponent12345678910export function mountComponent(vm, el) { // 上一步模板编译解析生成了render函数 // 下一步就是执行vm._render()方法 调用生成的render函数 生成虚拟dom // 最后使用vm._update()方法把虚拟dom渲染到页面 // 真实的el选项赋值给实例的$el属性 为之后虚拟dom产生的新的dom替换老的dom做铺垫 vm.$el = el; // _update和._render方法都是挂载在Vue原型的方法 类似_init vm._update(vm._render());}
核心方法mountComponent中主要调用vm._render和vm._updatte函数进行实例挂载
3.render函数转化成虚拟DO ...