Vue源码
文章平均质量分 64
神奇大叔
这个作者很懒,什么都没留下…
展开
-
vue Ref 和 Reactive 原理解析
vue Ref 和 Reactive 原理解析。原创 2024-07-28 21:58:34 · 294 阅读 · 0 评论 -
createSignal 无虚拟 vdom 响应式数据源简单实现
createSignal 无虚拟 vdom 响应式数据源简单实现。原创 2024-03-20 18:53:27 · 385 阅读 · 0 评论 -
vue diff 前后缀+最长递增子序列算法
【代码】vue diff 前后缀+最长递增子序列算法。原创 2023-08-06 16:30:26 · 487 阅读 · 0 评论 -
vue diff 双端比较算法
【代码】vue diff 双端比较算法。原创 2023-08-05 15:59:50 · 580 阅读 · 0 评论 -
Vuex 源码解析
如下基于vuex 4.1.0版本。原创 2022-12-21 17:48:02 · 736 阅读 · 0 评论 -
vue provide和inject原理解析
通过原型链实现的传参provide实例上挂载的provides要么是直接拿的父实例上的provides要么是创建的一个原型指向父实例provides的对象export function provide(key, value) { // 获取当前组件实例 const currentInstance: any = getCurrentInstance() if(currentInstance) { // 获取当前组件实例上provides属性 l原创 2022-03-05 22:04:14 · 688 阅读 · 0 评论 -
Vuex、Vue.install实现
Vuex的基本框架import Vue from 'vue'import Vuex from 'vuex'Vue.use(Vuex)export default new Vuex.Store({ state: { }, mutations: { }, actions: { }, modules: { }})========================================import Vue from 'vue'import App fro原创 2021-12-06 16:09:17 · 946 阅读 · 0 评论 -
vue3.0 reactive和shallowReact响应式源码实现
shallowReact: 因为只实现第一层,所以直接new Proxy代理即可 reactive: 因为要实现深层次数据劫持,所以需要递归 递归注意情况: 当是普通值时,因为普通值所处的对象已经被Proxy代理,所以无需设置直接返回, 如果是数组:需要遍历出数组中的对象,使其变成响应式的 如果是对象:需要遍历出属性中的对象,使其变成响应式的效果图:代码示例://定义处理器const reactiveHandler = { get(target,proper原创 2021-04-10 22:10:14 · 276 阅读 · 0 评论 -
vue3.0 shallowReadonly和readonly响应式源码实现
在处理器中只需要取消掉set和deleteProperty的功能即可效果图:代码示例://readonly相关处理器const readonlyHandler = { get(target,property) { console.log('读取了'+property+"属性") const result = Reflect.get(target, property); return result; }, set(target, property, valu原创 2021-04-11 16:31:52 · 170 阅读 · 0 评论 -
vue3.0 shallowRef和ref响应式源码实现
ref和reactive相比,ref通过setter和getter进行数据劫持代码示例:function shallowRef(target) { return { _value: target, get value() { console.log('读取数据'); return this._value; }, set value(val) { console.log('修改数据'); this._value =原创 2021-04-11 17:01:23 · 583 阅读 · 0 评论 -
vue3.0 isReadonly、isRef、isReactive和isProxy响应式源码实现
ref判断: 往返回的对象中添加一个_is_ref:true的标识isReadonly和isReactive都是Proxy代理的: 故在对应的Proxy处理器的get中,添加属性property==='_is_reactive'判断,并返回true,故通过访问_is_reactive属性标识即可isProxy判断为isReadonly或isReactive即可代码示例:function ref(target) { if (target && typeof target原创 2021-04-11 17:15:05 · 651 阅读 · 0 评论 -
vue3 diff算法优化
事件缓存:将事件缓存,可以理解为变成静态的了添加静态标记:Vue2 是全量 Diff,Vue3 是静态标记 + 非全量 Diff静态提升:创建静态节点时保存,后续直接复用使用最长递增子序列优化了对比流程:Vue2 里在 updateChildren() 函数里对比变更,在 Vue3 里这一块的逻辑主要在 patchKeyedChildren() 函数里,具体看下面事件缓存<button @click="handleClick">按钮</button>编译后结果ex.原创 2021-12-14 15:35:14 · 4509 阅读 · 1 评论 -
vue 插槽slot解析
普通插槽//子组件 : (假设名为:child)<template> <div class='child'> 我在子组件里面 <slot></slot> <slot name="one"></slot> </div></template>//父组件:(引用子组件 child)<template> <div class= 'app'>原创 2021-12-17 14:59:48 · 678 阅读 · 0 评论 -
vue 双向绑定中观察者模式
在数据劫持之外最重要的部分就是Dep和Watcher,这其实是一个观察者模式。用最简单的代码实现以下Vue的观察者模式: 通过watcher.evaluate()将自身实例赋值给Dep.target 调用dep.depend()将dep实例将watcher实例push到dep.subs中 通过数据劫持,在调用被劫持的对象的set方法时,调用dep.subs中所有的watcher.update()// 观察者class Dep { constructor() { this原创 2021-11-22 17:44:28 · 449 阅读 · 0 评论 -
vue 计算属性部分参考实现
computed: { b() { return this.data.a + 100 }, },参考小程序理解:// behavior.jsmodule.exports = Behavior({ lifetimes: { created() { this._originalSetData = this.setData // 原始 setData this.setData = this._setData // 封装后的 setDa..原创 2021-09-18 15:46:09 · 114 阅读 · 0 评论 -
Vue.set源码
先判断如果是数组,并且下标合法,就直接使用重写过的 splice 替换如果是对象,并且 key 存在于 target 里,说明是对已有属性进行set,就替换值就行了如果没有 ob,说明不是一个响应式对象,直接赋值返回,不进行响应式操作是一个响应式对象,再把新属性变成响应式,并派发更新export function set (target: Array<any> | Object, key: any, val: any): any { if (process.env.NODE_EN.原创 2021-12-14 11:52:46 · 162 阅读 · 0 评论 -
vue nextTick源码解析
<template> <div>{{ name }}</div></template><script>export default { data() { return { name: "" } }, mounted() { console.log(this.$el.clientHeight) // 0 this.name = "jeff" console.log(this.$原创 2021-12-10 10:44:40 · 1225 阅读 · 0 评论 -
diff算法(四指针图文版、类名事件等更新)
创建虚拟DOM对象{ tag: '',// 元素标签 children: [],// 子元素 text: '',// 子元素是文本节点的话,保存文本 el: null,// 对应的真实dom key, //节点的key ...}h函数根据接收的参数返回虚拟dom对象即可export const h = (tag, data = {},children) => { let text = '' let el let key原创 2022-01-07 16:29:21 · 837 阅读 · 0 评论 -
虚拟dom和diff算法源码实现
介绍 snabbdom库,vue的虚拟节点参照的是这个库 1、虚拟dom:用javaScript对象描述dom的层次结构,dom中的一切属性都在虚拟dom中有对应的属性 虚拟dom具有的属性: { children:, 子节点 data:, 标签上的属性 elm:, 对应的真实dom节点 key:, 节点的唯一标识 sel:, 标签名 text:, 文本内容 } 渲染函数: h('标签名',{归属属性:{属性:'值'}原创 2021-04-15 16:58:38 · 242 阅读 · 0 评论 -
vue 响应式源码版(偏收集依赖)
触发依赖:用到响应式对象某个属性的,template模板上的内容,以及手写的watcher的回调等收集依赖:会在组件挂载mounted前,调用updateComponent方法之后会生成渲染的虚拟dom,这个过程中会访问 vm 上的数据,就触发了数据对象的 getter,进行首次的依赖收集在之后的setter改变后,就会触发依赖更新视图export function mountComponent (...): Component { // 调用生命周期钩子函数 callHook(vm,原创 2021-12-16 20:09:07 · 876 阅读 · 0 评论 -
vue 数据响应式原理(偏响应式)
数据变化:原创 2021-04-04 13:21:59 · 332 阅读 · 2 评论 -
vue 自定义watcher源码解析
initWatch始化数据会执行initWatch,initWatch的核心是createWatcherfunction initWatch (vm, watch) { for (var key in watch) { var handler = watch[key]; // handler可以是数组的形式,执行多个回调 if (Array.isArray(handler)) { for (var i = 0; i < handler原创 2022-01-16 16:34:05 · 427 阅读 · 0 评论 -
vue 响应式数组收集依赖源码解析
数组方法的重写var arrayProto = Array.prototype;// 新建一个继承于Array的对象var arrayMethods = Object.create(arrayProto);// 数组拥有的方法var methodsToPatch = [ 'push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse']; methodsToPatch.forEach(function原创 2022-01-16 15:43:01 · 315 阅读 · 0 评论 -
vue 响应式收集依赖、计算属性收集依赖源码解析
实例化响应式对象// initData function initData(data) { ··· observe(data, true)}// observefunction observe(value, asRootData) { ··· ob = new Observer(value); return ob}// 观察者类,对象只要设置成拥有观察属性,则对象下的所有属性都会重写getter和setter方法,而getter,setting方法会进行依赖的收集和派发更原创 2022-01-14 15:52:03 · 535 阅读 · 0 评论 -
vue computed计算属性源码解析
主要特性是如果计算属性依赖的值不发生变化 页面更新的时候不会重新计算 计算结果会被缓存 可以用此 api 来优化性能基本使用:<script> // Vue实例化 let vm = new Vue({ el: "#app", data() { return { aa: 1, bb: 2, cc: 3, }; }, // render(h) { // return h('原创 2021-12-17 18:36:23 · 751 阅读 · 0 评论 -
vue 数据初始化响应式源码解析、简易响应式系统实现
initState进行props,methods,data,computed和watch数据的初始化处理,并将他们转换为响应式对象export function initMixin (Vue: Class<Component>) { // 在原型上添加 _init 方法 Vue.prototype._init = function (options?: Object) { // 保存当前实例 const vm: Component = this // 合并原创 2022-01-13 16:01:38 · 344 阅读 · 0 评论 -
vue keep-alive二次渲染缓存优化策略、生命周期源码分析
首次渲染实例化会执行挂载$mount的过程,这一步会执行keep-alive选项中的render函数render函数在初始渲染时,会将渲染的子vnode进行缓存。同时对应的子真实节点也会被缓存到vnode中。基本使用<div id="app"> <button @click="changeTabs('child1')">child1</button> <button @click="changeTabs('child2')">chi原创 2022-01-26 22:07:58 · 1723 阅读 · 1 评论 -
vue keep-alive首次渲染缓存过程源码解析
基本使用<div id="app"> <button @click="changeTabs('child1')">child1</button> <button @click="changeTabs('child2')">child2</button> <keep-alive> <component :is="chooseTabs"> </component&g原创 2022-01-26 17:19:58 · 1360 阅读 · 0 评论 -
vue 动态组件源码分析
基本使用// vue<div id="app"> <button @click="changeTabs('child1')">child1</button> <button @click="changeTabs('child2')">child2</button> <button @click="changeTabs('child3')">child3</button> <component :is原创 2022-01-26 16:52:33 · 856 阅读 · 0 评论 -
vue 异步组件、函数式组件源码解析
我们往往会把一些非首屏的组件设计成异步组件,部分不影响初次视觉体验的组件也可以设计为异步组件基本使用:Vue中允许用户通过工厂函数的形式定义组件,这个工厂函数会异步解析组件定义,组件需要渲染的时候才会触发该工厂函数,加载结果会进行缓存,以供下一次调用组件时使用。// 全局注册:Vue.component('asyncComponent', function(resolve, reject) { require(['./test.vue'], resolve)})// 局部注册:var原创 2022-01-12 15:59:50 · 663 阅读 · 0 评论 -
vue 组件创建挂载过程源码分析
基本使用:<script> // 全局组件 Vue.component("parent-component", { template: `<div>我是全局组件</div>`, }); // Vue实例化 let vm = new Vue({ el: "#app", data() { return { aa: 1, }; }, // render(h) { //.原创 2021-12-20 15:45:33 · 659 阅读 · 0 评论 -
vue 虚拟dom转换真实dom源码解析
当不断的通过JS修改DOM时,不经意间会触发到渲染引擎的回流或者重绘,这个性能开销是非常巨大的。因此为了降低开销,我们需要做的是尽可能减少DOM操作,当我们想用JS脚本大批量进行DOM操作时,会优先作用于Virtual DOM这个JS对象,最后通过对比将要改动的部分通知并更新到真实的DOM。尽管最终还是操作真实的DOM,但Virtual DOM可以将多个改动合并成一个批量的操作,从而减少 DOM 重排的次数,进而缩短了生成渲染树和绘制所花的时间。Vnode构造函数var VNode = function原创 2022-01-11 16:01:45 · 994 阅读 · 0 评论 -
vue v-model源码解析
基本使用<div id="app"> <input type="text" v-model="value1"></div>new Vue({ el: '#app', data() { return { value1: '' } }})回顾一下模板到真实节点的过程模板解析成AST树;AST树生成可执行的render函数;render函数转换为Vnode对象;根据Vnode对象生成真实的Dom节点。AS原创 2022-01-19 17:40:30 · 1983 阅读 · 0 评论 -
vue 模板编译解析和挂载过程源码解析
第一种就是经过模板编译生成 render 函数第二种是我们自己在组件里定义了 render 函数,这种会跳过模板编译的过程<template></template> 这个是模板,不是真实的 HTML,浏览器是不认识模板的,所以我们需要把它编译成浏览器认识的原生的 HTML这一块的主要流程就是:提取出模板中的原生 HTML 和非原生 HTML,比如绑定的属性、事件、指令等等经过一些处理生成 render 函数render 函数再将模板内容生成对应的 vnode再经过.原创 2021-12-14 17:35:09 · 901 阅读 · 0 评论 -
vue Proxy数据代理进行校验部分源码解析
initProxy数据拦截的思想除了为构建响应式系统准备,它也可以为数据进行筛选过滤,我们接着往下看初始化的代码,在合并选项后,vue接下来会为vm实例设置一层代理,这层代理可以为vue在模板渲染时进行一层数据筛选Vue.prototype._init = function(options) { // 选项合并 ... { // 对vm实例进行一层代理 initProxy(vm); } ...}initProxy//原创 2022-01-09 17:06:51 · 805 阅读 · 0 评论 -
vue 生命周期源码解析
源码版本:2.6Vue2 完整的生命周期大致可分成四个阶段:初始化阶段:为 Vue 实例初始化一些事件、属性和响应式数据等模板编译阶段:把我们写的 模板编译成渲染函数 render挂载阶段:把模板渲染到真实的 DOM 节点上,以及数据变更时执行更新操作销毁阶段:把组件实例从父组件中删除,并取消依赖监听和事件监听初始化阶段:new Vue()这个阶段做的第一件事,就是用 new 创建一个 Vue 实例对象new Vue({ el:'#app', store,原创 2021-12-01 17:41:13 · 815 阅读 · 0 评论 -
vue minxin实现、生命周期合并策略
定义全局 Mixin 函数// src/global-api/mixin.jsimport {mergeOptions} from '../util/index'//初始化mixin方法,即往Vue上挂载minxin方法,核心是mergeOptionsexport default function initMixin(Vue){ Vue.mixin = function (mixin) { // 合并对象 this.options=mergeOptions(this原创 2021-12-20 11:52:00 · 1500 阅读 · 0 评论 -
vue 选项合并策略源码分析
合并规则Vue针对每个规定的选项都有定义好的合并策略,例如data,component,mounted等。如果合并的子父配置都具有相同的选项,则只需要按照规定好的策略进行选项合并即可。选项不存在默认的合并策略,处理的原则是有子类配置选项则默认使用子类配置选项,没有则选择父类配置选项。function Vue (options) { if (process.env.NODE_ENV !== 'production' && !(this instanceof Vue) ) {原创 2022-01-09 16:45:28 · 722 阅读 · 0 评论 -
vue 选项初始化流程源码分析(原型属性方法定义、静态方法定义、内置选项、合并场景、规则校验)
function Vue (options) { if (process.env.NODE_ENV !== 'production' && !(this instanceof Vue) ) { warn('Vue is a constructor and should be called with the `new` keyword') } this._init(options)}// 定义Vue原型上的init方法(内部方法)initMixin(Vue);//原创 2022-01-09 15:18:14 · 539 阅读 · 0 评论