vue3.2.20
vue3.2.20源码地址
使用pnpm install 反向安装
根目录下的package.json文件的scripts脚本小的dev属性 新增sourcemap
"dev": "node scripts/dev.js --sourcemap",
/packages/vue/examples/test.html 在html文件内部引入vue.global.js 就可以调试源码啦
<script src="../dist/vue.global.js"></script>
reactive原理
如果不是浅对象,则需要进一步代理,在get中有个isObject做判断,但是和vue2不同的是,这里如果没有值访问到更加深层的对象属性,就没有触发get里面的进一步深层次代理 就是懒代理 没有访问就不代理 访问了就代理
const toProxy = new WeakMap()
const toRaw = new WeakMap()
const isObject = val => val !== null && typeof val === 'object'
function reactive(obj) {
if (typeof obj !== 'object' && obj != null) {
return obj
}
if (toProxy.has(obj)) {
return toProxy.get(obj)
}
if (toRaw.has(obj)) {
return obj
}
const observed = new Proxy(obj, {
get(target, key, receiver) {
const res = Reflect.get(target, key, receiver)
console.log(`获取${key}:${res}`)
return isObject(res) ? reactive(res) : 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
}
})
toProxy.set(obj, observed)
toRaw.set(observed, obj)
return observed
}
测试代码
const state = reactive({
foo: 'foo',
bar: { a: 1 }
})
state.foo
state.foo = 'fooooooo'
state.dong = 'dong'
delete state.dong
console.log(reactive(state) === state)
toRefs
对比mixins,好处显而易见:
- time来源清晰
- 不会与data、props等命名冲突
const { createApp, reactive, onMounted, toRefs } = Vue;
createApp({
template: "<p>time: {{time}}</p>",
setup() {
const state = reactive({ time: new Date() })
onMounted(() => {
setInterval(() => {
state.time = new Date()
}, 1000)
})
const { time } = toRefs(state)
return { time }
}
}).mount('#app')
|