张家界建设网站制作,城口网站建设,河北seo技术交流,石家庄最新轨迹Vue3的响应式原理解析
Vue2响应式原理回顾
// 1.对象响应化#xff1a;遍历每个key#xff0c;定义getter、setter
// 2.数组响应化#xff1a;覆盖数组原型方法#xff0c;额外增加通知逻辑
const originalProto Array.prototype
const arrayProto Object.create(orig…Vue3的响应式原理解析
Vue2响应式原理回顾
// 1.对象响应化遍历每个key定义getter、setter
// 2.数组响应化覆盖数组原型方法额外增加通知逻辑
const originalProto Array.prototype
const arrayProto Object.create(originalProto);[push, pop, shift, unshift, splice, reverse, sort].forEach(method {arrayProto[method] function () {originalProto[method].apply(this, arguments)notifyUpdate()}})
function observe (obj) {if (typeof obj ! object || obj null) {return}// 增加数组类型判断若是数组则覆盖其原型if (Array.isArray(obj)) {Object.setPrototypeOf(obj, arrayProto)} else {const keys Object.keys(obj)for (let i 0; i keys.length; i) {const key keys[i]defineReactive(obj, key, obj[key])}}
}
function defineReactive (obj, key, val) {observe(val) // 解决嵌套对象问题Object.defineProperty(obj, key, {get () {return val},set (newVal) {if (newVal ! val) {observe(newVal) // 新值是对象的情况val newValnotifyUpdate()}}})
}
function notifyUpdate () {console.log(页面更新!)
} vue2响应式弊端 响应化过程需要递归遍历消耗较大 新加或删除属性无法监听 数组响应化需要额外实现 Map、Set、Class等无法响应式 修改语法有限制 Vue3响应式原理剖析
vue3使用ES6的Proxy特性来解决这些问题。
function reactive (obj) {if (typeof obj ! object obj ! null) {return obj}// Proxy相当于在对象外层加拦截// http://es6.ruanyifeng.com/#docs/proxyconst observed new Proxy(obj, {get (target, key, receiver) {// Reflect用于执行对象默认操作更规范、更友好// Proxy和Object的方法Reflect都有对应// http://es6.ruanyifeng.com/#docs/reflectconst res Reflect.get(target, key, receiver)console.log(获取${key}:${res})return res},set (target, key, value, receiver) {const res Reflect.set(target, key, value, receiver)console.log(设置${key}:${value})return res},deleteProperty (target, key) {const res Reflect.deleteProperty(target, key)console.log(删除${key}:${res})return res}})return observed
}
//代码测试
const state reactive({foo: foo,bar: { a: 1 }
})
// 1.获取
state.foo // ok
// 2.设置已存在属性
state.foo fooooooo // ok
// 3.设置不存在属性
state.dong dong // ok
// 4.删除属性
delete state.dong // ok嵌套对象响应式
测试嵌套对象不能响应
// 设置嵌套对象属性
react.bar.a 10 // no ok添加对象类型递归 // 提取帮助方法const isObject val val ! null typeof val objectfunction reactive (obj) {//判断是否对象if (!isObject(obj)) {return obj}const observed new Proxy(obj, {get (target, key, receiver) {// ...// 如果是对象需要递归return isObject(res) ? reactive(res) : res},//...}避免重复代理
重复代理比如 reactive(data) // 已代理过的纯对象 reactive(react) // 代理对象 解决方式将之前代理结果缓存get时直接使用
const toProxy new WeakMap() // 形如obj:observedconst toRaw new WeakMap() // 形如observed:objfunction reactive (obj) {//...// 查找缓存避免重复代理if (toProxy.has(obj)) {return toProxy.get(obj)}if (toRaw.has(obj)) {return obj}const observed new Proxy(...)// 缓存代理结果toProxy.set(obj, observed)toRaw.set(observed, obj)return observed}// 测试效果console.log(reactive(data) state)console.log(reactive(state) state)✨原创不易还希望各位大佬支持一下\textcolor{blue}{原创不易还希望各位大佬支持一下}原创不易还希望各位大佬支持一下 点赞你的认可是我创作的动力\textcolor{green}{点赞你的认可是我创作的动力}点赞你的认可是我创作的动力 ⭐️ 收藏你的青睐是我努力的方向\textcolor{green}{收藏你的青睐是我努力的方向}收藏你的青睐是我努力的方向 ✏️ 评论你的意见是我进步的财富\textcolor{green}{评论你的意见是我进步的财富}评论你的意见是我进步的财富