Vue組件的實(shí)現(xiàn)原理詳細(xì)分析
渲染組件
一個(gè)組件內(nèi)部必須要使用 render 進(jìn)行渲染,且返回虛擬 DOM
這是一個(gè)最簡(jiǎn)組件實(shí)例
const MyComponent = {
// 組件名稱,可選
name: "MyComponent",
// 組件的渲染函數(shù),其返回值必須為虛擬 DOM
render() {
// 返回虛擬 DOM
return {
type: "div",
children: `我是文本內(nèi)容`,
};
},
};
渲染器中的 mountComponent 函數(shù)完成組件的渲染
function mountComponent(vnode, container, anchor) {
// 通過 vnode 獲取組件的選項(xiàng)對(duì)象,即 vnode.type
const componentOptions = vnode.type;
// 獲取組件的渲染函數(shù) render
const { render } = componentOptions;
// 執(zhí)行渲染函數(shù),獲取組件要渲染的內(nèi)容,即 render 函數(shù)返回的虛擬
const subTree = render();
// 最后調(diào)用 patch 函數(shù)來掛載組件所描述的內(nèi)容,即 subTree
patch(null, subTree, container, anchor);
}
組件更新
組件初始化步驟:
- 取得 data 函數(shù)后用 reactive 將其變成響應(yīng)式的
- render 函數(shù)內(nèi)將 this 指向 state,并將 state 作為第一個(gè)參數(shù)傳入 render 函數(shù)
將渲染任務(wù)包裝到一個(gè)副作用函數(shù) effect 里面,即可實(shí)現(xiàn)響應(yīng)式更新數(shù)據(jù)
若要使每次響應(yīng)式數(shù)據(jù)修改后,effect 僅執(zhí)行一次,則需要引入調(diào)度器概念
這是書中給出的最簡(jiǎn)調(diào)度器實(shí)例
即先把 effect 放入微任務(wù)隊(duì)列,等執(zhí)行棧清空再調(diào)出來執(zhí)行
// 任務(wù)緩存隊(duì)列,set可以自動(dòng)去重
const queue = new Set();
// 一個(gè)標(biāo)志,代表是否正在刷新任務(wù)隊(duì)列
let isFlushing = false;
// 創(chuàng)建一個(gè)立即 resolve 的 Promise 實(shí)例
const p = Promise.resolve();
// 調(diào)度器的主要函數(shù),用來將一個(gè)任務(wù)添加到緩沖隊(duì)列中,并開始刷新隊(duì)列
function queueJob(job) {
// 將 job 添加到任務(wù)隊(duì)列 queue 中
queue.add(job);
// 如果還沒有開始刷新隊(duì)列,則刷新之
if (!isFlushing) {
// 將該標(biāo)志設(shè)置為 true 以避免重復(fù)刷新
isFlushing = true;
// 在微任務(wù)中刷新緩沖隊(duì)列
p.then(() => {
try {
// 執(zhí)行任務(wù)隊(duì)列中的任務(wù)
queue.forEach((job) => job());
} finally {
// 重置狀態(tài)
isFlushing = false;
queue.clear = 0;
}
});
}
}
父子組件
這是一個(gè)簡(jiǎn)單的父子組件代碼
// 子組件
<template>
<MyComponent :title="title" />
</template>
// 父組件
const vnode = {
type: MyComponent,
props: {
title: 'A Big Title'
}
}
父組件更新導(dǎo)致子組件更新(被動(dòng)更新)過程:
- 父組件自更新
- 渲染器檢查 subTree 發(fā)現(xiàn)存在 vnode,則調(diào)用 patchComponent 實(shí)現(xiàn)子組件更新
setup函數(shù)
setup 函數(shù)為配合組合式 API 所引入的
他有如下兩種返回值形式
// 返回函數(shù)
const comp = {
setup() {
return () => {
return {
type: "div",
children: "give up for vuejs",
};
};
},
};
// 返回對(duì)象
const comp = {
setup() {
const count = ref(0);
return {
count,
};
},
render() {
return {
type: "div",
children: `count is ${this.count}`,
};
},
};
setup 接收兩個(gè)參數(shù),分別是 props 以及 setupContext
setupContext 包含以下四個(gè)主要對(duì)象
- slots 插槽
- emit 自定義事件
- attrs 自定義屬性
- expose 暴露
emit 實(shí)現(xiàn)
只需要實(shí)現(xiàn)一個(gè) emit 函數(shù)并將其添加到 setupContext 對(duì)象中
到此這篇關(guān)于Vue組件的實(shí)現(xiàn)原理詳細(xì)分析的文章就介紹到這了,更多相關(guān)Vue組件實(shí)現(xiàn)原理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
談?wù)剬?duì)vue響應(yīng)式數(shù)據(jù)更新的誤解
本篇文章主要介紹了談?wù)剬?duì)vue響應(yīng)式數(shù)據(jù)更新的誤解,深入了解了vue響應(yīng)式數(shù)據(jù),有興趣的可以了解一下2017-08-08
element-ui中el-cascader動(dòng)態(tài)加載和默認(rèn)值詳解
vue+elementUI項(xiàng)目中el-cascader級(jí)聯(lián)選擇器使用頻率非常高,下面這篇文章主要給大家介紹了關(guān)于element-ui中el-cascader動(dòng)態(tài)加載和默認(rèn)值的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-05-05
Vue自定義復(fù)制指令 v-copy功能的實(shí)現(xiàn)
這篇文章主要介紹了Vue自定義復(fù)制指令 v-copy,使用自定義指令創(chuàng)建一個(gè)點(diǎn)擊復(fù)制文本功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-01-01
vue-router路由與頁(yè)面間導(dǎo)航實(shí)例解析
vue-router 是一個(gè)插件,需要在 Vue 的全局引用中通過 Vue.use()將它引用到 Vue 實(shí)例當(dāng)中。接下來通過本文給大家分享vue-router路由與頁(yè)面間導(dǎo)航,需要的朋友參考下吧2017-11-11

