エッグは、vue3.0関連の知識を学ぶために、最近の意図の前に書き込むようになり、物事を学ぶの精神に沿って、最良の方法は、それの書き込みを模倣することですので、vue3.0の簡易版を書くために自分で行うには、彼らはミニvue3.0と呼ばれる 大きな助けの理解のvue3.0またはvue2.xのコア原則の感触は、それを共有するように。主に、テンプレートのコンパイル、レスポンシブ、コンポーネントのレンダリング処理などが含まれ、リポジトリのアドレスは、、welcome starです!
コンポーネントレンダリングの原則
この記事では、vue3.0のコンポーネント・レンダリングのプロセスを簡単に紹介します。コンポーネント・レンダリングの原理をわかりやすく説明するために、簡単な例と組み合わせて全体のプロセスを説明します。
よりシンプルなレンダリング工程図
より複雑なレンダリング
マウントポイントを
<div id="app"></div>
ルートコンポーネントは次のように定義されます。
const rootComponent = {
template: `<div class="parent">
<div :class="data.class">コンポーネントの内容をレンダリングする</div>
</div>`,
setup() {
// reactive 役割は、データの応答性を設定することである
const data = reactive({
class: 'demo'
})
return {
data
}
}
}
アプリのグローバルコンテキストの作成
まず、App Global Contextを以下のように作成します:
const appContext = {
mixins: [], // グローバルミキシンを格納する
components: {}, // グローバルコンポーネントを格納する
directives: {}, // グローバルコマンドを格納する
}
コンポーネントVNodeを作成します。
const rootVnode = {
type: rootComponent, // typesubTreeの値には、divやコンポーネントオプションオブジェクトなどの文字列を指定できる。
props: {},
children: {},
component: null, // コンポーネントのインスタンス
appContext: appContext // グローバルコンテキストを取得する。
}
appContext: グローバル・コンポーネント、命令のグローバル・コンテキスト。コンポーネントを生成するために render 関数が実行されるときに、グローバル・コンポーネント、命令を解析するために使用されます。この例では、コンポーネントのオブジェクトを定義します。
VNodeに従ってルート・コンポーネントをレンダリングします。
コンポーネントインスタンスの作成
コンポーネント VNode に基づいてコンポーネント・インスタンスを初期化します。
const instance = {
vnode: rootVnode,// コンポーネントvnode
parent: null,// 親コンポーネントのインスタンスは、この例ではnullである
appContext, // グローバルコンテキスト
type: rootVnode.type, // ノードタイプ
subTree: null, // コンポーネント内のVNodeツリーをレンダリングする
render: null,
proxy: null,
data: {},
props: {},
setupState: {},
// グローバルコンポーネントと命令を継承する
components: Object.create(appContext.components),
directives: Object.create(appContext.directives),
ctx: { _: instance }
}
ctx: この ctx 属性は、インスタンス自身を実行コンテキストとしてテンプレートをレンダリングするために使用されます。
コンポーネントインスタンス関連プロパティの初期化
// テンプレートレンダリングレンダリング関数を設定する
const Component = instance.type // コンポーネントのオプション
if (!Component.render && Component.template && compile) {
// render関数のテンプレートをコンパイルする
Component.render = compile(Component.template)
}
if (!Component.render) {
throw Error('テンプレートが正しいかどうか確認してほしい。')
}
instance.render = Component.render
// render関数が呼ばれたときに、レンダリングコンテキストを設定する。
instance.proxy = new Proxy(instance.ctx, {
get({ _: instance }, key) {
const { setupState } = instance
// setupState
if (setupState[key] && hasOwn(setupState, key)) {
return setupState[key]
}
},
set({ _: instance }, key, val) {
const { setupState } = instance
if (setupState[key] && hasOwn(setupState, key)) {
setupState[key] = val
}
},
})
const { setup } = Component
// セットアップ関数を呼び出す
if (setup) {
const setupResult = setup()
// ここでは、応答性を設定する
instance.setupState = reactive(setupResult)
}
コンパイル関数のコードでは、mini-vue3.0原則の特定の実装にコンパイルします。
この記事の例に基づいて、render、setupStateを取得します。
// _c VNodeを作成する
instance.render = function () { return _c('div',
{class: "parent"},
[_c('div',
{class: this.data.class},
[_c('text', {value: 'コンポーネントの内容をレンダリングする'})]
)]
)
}
instance.setupState = {
dataProxy: {
class: 'demo'
}
}
コンポーネントコンテンツのレンダリング
// レンダリングコンポーネントの効果は、依存関係の収集のための応答関数であり、コンポーネントの更新の更新関数を設定する。
// effect vue2と同等.x ウォッチャー
instance.update = effect(function componentEffect() {
// コンポーネントテンプレートをレンダリング、コンポーネントサブツリーVNodeを取得すると同時に、依存関係のコレクションを完了するには、インスタンス.proxy 実際には、プロキシは自己生成コンポーネントである
const subTree = (instance.subTree = instance.render.call(instance.proxy, instance.proxy))
// コンポーネントサブツリーVNodeに従って、コンポーネントの内容をレンダリングする
mountElement(subTree, container, anchor, instance)
rootVnode.el = subTree.el
instance.isMounted = true
})
// VNodeによると、特定のDom要素を作成する
// container 親 Dom 要素は、この例では id である。="app"
const mountElement = (vnode, container, anchor, parentComponent) => {
const { type, props, children } = vnode
let el
// テキストノードの特別な処理
if (type === 'text') {
el = vnode.el = document.createTextNode(props.value)
} else {
el = vnode.el = document.createElement(type)
// マウントされたサブツリーの再帰的レンダリング
if (children) {
mountChildren(vnode.children, el, null, parentComponent)
}
// ここでの props は Dom 要素の props である。
if (props) {
for (const key in props) {
el.setAttribute(key, props[key])
}
}
}
// DOMに挿入する
document.appendChild(container, el, anchor)
}
この記事の例でルート・コンポーネントから得られるサブツリーは以下の通りです:
{
"type": "div",
"props": {
"class": "parent"
},
"children": [{
"type": "div",
"props": {
"class": "before"
},
"children": [{
"type": "text",
"props": {
"value": "コンポーネントのレンダリングコンテンツ"
},
"component": null,
"appContext": null
}],
"component": null,
"appContext": null
}],
"component": null,
"appContext": null
}





