petite-vue源碼剖析-ref的工作原理
- 2022 年 3 月 15 日
- 筆記
- javascript
ref
內部的工作原理十分簡單,其實就是將指令ref
、:ref
或v-bind:ref
標識的元素實例存儲到當前作用域的$refs
對象中,那麼我們就可以通過this.$refs
獲取對應的元素實例。但由於作用域繼承上有點小竅門,所以我們能從this.$refs
獲取的元素實例還是需要注意一下。下面讓我為你一一道來吧!
深入ref
工作原理
//文件 ./src/directives/ref.ts
export const ref: Directive = ({
el,
ctx: {
scope: { $refs }
},
get,
effect
}) => {
let prevRef: any
effect(() => {
// 獲取指向元素的屬性名稱
const ref = get()
$refs[ref] = el
// 由於屬性名稱是可以動態生成的(:ref="name"),若新舊對應的屬性名稱不同,則清理舊屬性
if (prevRef && ref != prevRef) {
delete $refs[prevRef]
}
prevRef = ref
})
return () => {
prevRef && delete $refs[prevRef]
}
}
這段實現是不是言簡意賅呢?現在讓我們把目光轉向上下文對象(Context)的構建吧
//文件 ./src/context.ts
export const createScopedContext = (ctx: Context, data = {}) => {
onst parentScope = ctx.scope
const mergedScope = Object.create(parentScope)
Object.defineProperties(mergedScope, Object.getOwnPropertyDescriptors(data))
// $refs構成$refs對象的原型鏈
mergedScope.$refs = Object.create(parentScope.$refs)
// ......
}
$refs構成$refs對象的原型鏈,那麼我們就可以這樣引用元素實例
createApp({
App: {
$template: `
<div ref="container">
<div v-scope="Modal"></div>
</div>
`,
Modal: {
$template: `
<button @click="handleHide">Hide</button>
`,
handleHide() {
this.$refs.container.style.display = 'none'
}
}
}
}).mount('[v-scope]')
總結
下一篇《petite-vue源碼剖析-優化手段template詳解》我們將著手解決petite-vue在線模板和在線渲染造成用戶體驗待優化的問題,敬請期待。
尊重原創,轉載請註明來自://www.cnblogs.com/fsjohnhuang/p/16006899.html 肥仔John