以下是手写虚拟DOM diff算法和Vue3响应式原理的实现代码:
virtual-dom-diff.js
class VNode {
constructor(tag,props,children){
this.tag = tag
this.props = props || {}
this.children = children || []
this.key = props?props.key :undefined
}
}
function diff(oldVNode,newVNode){
//1.如果标签不同,直接替换整个节点
if(oldVNode.tag !==newVNode.tag){
return {type:'REPLACE',node:newVNode}
}
//2.比较属性差异
const propsPatches = diffProps(oldVNode.props, newVNode.props)
//3.比较子节点差异
const childrenPatches = diffChildren(oldVNode.children,newVNode.children)
return {
type:'UPDATE',
props:propsPatches,
children:childrenPatches
}
}
function diffProps(oldProps,newProps){
const patches = {}
//找出变化的属性
for(const key in newProps){
if(oldProps[key] !==newProps[key]){
patches[key] = newProps[key]
}
}
//找出被删除的属性
for(const key in oldProps){
if(!newProps.hasOwnProperty(key)){
patches[key] = null
}
}
return patches
}
function diffChildren(oldChildren,newChildren){
const patches = []
const len = Math.max(oldChildren.length,newChildren.length)
for(let i = 0 ; i<len;i++){
if(!oldChildren[i]){
patches.push({type:'ADD',node:newChildren[i]})
}else if(!newChildren[i]){
patches.push({type:'REMOVE',index:i})
}else{
patches.push(diff(oldChildren[i],newChildren[i]))
}
}
return patches
}
虚拟DOM diff算法实现功能:
创建虚拟DOM节点类VNode
实现节点差异比较(diff函数)
属性差异比较(diffProps)
子节点差异比较(diffChildren)
vue3-reactive.js
const targetMap = new WeakMap()
let activeEffect = null
function track(target ,key ){
if(!activeEffect) return
let depsMap = targetMap.get(target)
if(!depsMap){
targetMap.set(target,(depsMap = new Map()))
}
let dep = depsMap.get(key)
if(!dep){
depsMap.set(key,(dep = new Set()))
}
dep.add(activeEffect)
}
function trigger(target ,key){
const depsMap =targetMap.get(target)
if(!depsMap) return
const dep = depsMap.get(key)
if(dep){
dep.forEach(effect => effect())
}
}
function reactive(obj){
return new Proxy(obj,{
get(target,key,receiver){
track(target,key)
return Reflect.get(target,key,receiver)
},
set(target,key,value,receiver){
const oldValue = target[key]
const result = Reflect.set(target,key,value,receiver)
if(oldValue !==value){
trigger(target,key)
}
return result
}
})
}
function effect(fn){
activeEffect = fn
fn()
activeEffect = null
}
Vue3响应式原理实现功能:
使用Proxy实现数据劫持
依赖收集系统(targetMap)
追踪依赖(track)
触发更新(trigger)
响应式对象创建(reactive)
副作用函数(effect)