data-binding: intro
https://ubugeeei.github.io/chibivue/10-minimum-example/080-template-binding.html#テンプレートにバインドしたい
今の状態だと、直接DOM操作をしているだけ
Reactivity System や Virtual Dom の恩恵を得ることができてない
code: main.ts
import { createApp, reactive } from 'chibivue'
const app = createApp({
setup() {
const state = reactive({ message: 'Hello, chibivue!' })
const changeMessage = () => {
state.message += '!'
}
return { state, changeMessage }
},
template: `
<div class="container" style="text-align: center">
<h2>message: {{ state.message }}</h2>
<button @click="changeMessage"> click me! </button>
</div>
`,
})
app.mount('#app')
↑ 今回目指す開発者インターフェース
setup内で定義したステートをtemplate内で使いたい
setup内で定義した関数をtemplate内で使いたい
-> テンプレートバインティング
setup から return した値を使いたいので、setup の戻り値にステートを追加
code: packages/runtime-core/componentOptions.ts
export type ComponentOptions = {
setup?: (
props: Record<string, any>,
ctx: { emit: (event: string, ...args: any[]) => void }
) => Function | Record<string, unknown> | void;
// 省略
};
setupの戻り値をコンポーネントのデータとして保持できるようにする
code: packages/runtime-core/component.ts
export interface ComponentInternalInstance {
// 省略
setupState: Data // setup の結果がオブジェクトの場合はここに格納することにする
}
コンパイラを実装する前に、setupState をどのようにしてテンプレートにバインティングするのか?
テンプレートを実装する前
render関数がクロージャを形成し、変数 (state) を参照しているだけ
code: main.ts
const app = createApp({
setup() {
const state = reactive({ message: 'hello' })
return () => h('div', {}, state.message)
},
})
テンプレート実装後
code: main.ts
const app = createApp({
setup() {
const state = reactive({ message: 'hello' })
return { state }
},
// これはrender関数に compile される
template: '<div>{{ state.message }}</div>',
// イメージ
// render() {
// return h('div', {}, state.message)
// }
})
render関数内では state という変数が定義されてない
どのようにして state を参照できるようにすれば良いか?