Vue はテンプレートを再利用することもできます
Vue を使用する多くの学生は、次のような問題に遭遇すると思います。
「コンポーネントには同じテンプレート(html構造)の部分がいくつかあります。再利用したい場合は、サブコンポーネントに抽出するしかありませんが、属性を渡してイベントをリッスンする必要があるため、などなど、いつも面倒くさく感じてしまうので、Reactのようなコンポーネントでテンプレートを直接再利用できればいいのにと今は思っています。」
たとえば、次の例です。
<template>
<dialog v-if="showInDialog">
<!-- 模板内容 -->
</dialog>
<div v-else>
<!-- 与上相同的模板内容 -->
</div>
</template>
再利用する場合は、このテンプレートをサブコンポーネントに抽出する必要があります。これは合理的ですが、いくつかの欠点もあります.子コンポーネントは親コンポーネントのコンテキストにアクセスできません, つまり, 変数とイベントにアクセスできません. プロパティ (props) とイベントバインディング (v- bind) サブコンポーネントにアクセスします。
サブコンポーネントのやり方に問題はありませんが、抽出されたサブコンポーネント (再利用可能な部分) が現在のコンポーネントで複数回しか使用されていない場合、プロパティの転送、イベントのバインド、イベントのトリガーの一連のプロセスがそれほどエレガントではないことがわかります。上。
Reactはこの時笑いました、私は自然にそれをサポートします
現在のコンポーネントでテンプレートを直接再利用する方法はありますか?
**回答は必須です。**
実際、この問題は 2022 年に vuejs/core の問題で提起され、議論されましたが、良い解決策はありませんでした. 2 日前まで、スーパーマスターの antfu は非常に賢い解決策を提案しました—「vue - reuse-テンプレート」、これも今日のトピックです。
Vue-reuse-template はテンプレートの再利用の問題を非常にエレガントで独創的なアイデアで解決します. 偉大なマスターの傑作を見てみましょう.
1. 使い方
1.1 基本的な使い方
使用法は非常に単純で、1 つの定義、1 つの使用、変数を使用するのと同じくらい単純です。
<script setup>
import { createReusableTemplate } from 'vue-reuse-template'
const [DefineTemplate, ReuseTemplate] = createReusableTemplate()
</script>
<template>
<DefineTemplate>
<!-- something complex -->
</DefineTemplate>
<dialog v-if="showInDialog">
<ReuseTemplate />
</dialog>
<div v-else>
<ReuseTemplate />
</div>
</template>
-
DefineTemplate
再利用が必要なテンプレートは内側にラップされ、DefineTemplate
コンテンツはレンダリングされません。これは、変数の定義段階に相当します。 -
ReuseTemplate
DefineTemplate
と組み合わせると、ReuseTemplate
テンプレート コンテンツがレンダリングされます。これは、変数の使用段階に相当します。
1.2 パスパラメータ
スロット機構により、「再利用するテンプレート」のスコープは現在のコンポーネントであるため、コンポーネントの変数とイベントを直接使用できます。これは、追加のパラメーターを渡す方法を示すためのものです。
<template>
<DefineTemplate v-slot="{ data, msg, anything }">
<div>{
{ data }} passed from usage</div>
</DefineTemplate>
<ReuseTemplate :data="data" msg="The first usage" />
<ReuseTemplate :data="anotherData" msg="The second usage" />
<ReuseTemplate v-bind="{ data: something, msg: 'The third' }" />
</template>
より多くの使用法については、ポータルはこちらです。
2. 達成方法
「うわー、これは面白い、どうやって実現するんだ!そんなに複雑じゃないんだ!」というのが最初の感想でした。
実装は型も含めて非常に工夫されており、全体のコードはわずか75行、main関数はわずか30行程度と、そんなに単純なのだろうか。それがどのように達成されるかを見てみましょう!
最初に要約します。
- スロットを使って「再利用するテンプレート」を手に入れる——
define
- クロージャーによって記録されたスロットを使用して、多重化を実現します—
reuse
export function createReusableTemplate<
Bindings extends object,
Slots extends Record<string, Slot | undefined> = Record<string, Slot | undefined>,
>(name?: string) {
// render 用于记录 “待复用模板”
let render: Slot | undefined
// 定义组件:组件作为 “待复用模板” 外层,此时,插槽的内容,即 “待复用模板” 用 render 记录下来
const define = defineComponent((_, {
slots }) => {
return () => {
// 这里没有 return 任何内容,所以不会渲染
render = slots.default
}
})
// 复用组件:直接渲染 render 以达到复用的效果
const reuse = defineComponent({
inheritAttrs: false,
setup(_, {
attrs, slots }) {
return () => {
return render?.({
...attrs, $slots: slots })
}
},
})
// 导出 定义组件 和 复用组件
return makeDestructurable(
{
define, reuse },
[define, reuse] as const,
)
}
詳細は次のとおりです。
-
render
変数render
「再利用するテンプレート」の記録に使用 -
define
関数 (コンポーネント)defineComponent
コンポーネントは、サブコンポーネント(カスタムコンポーネント)として理解できる関数を通じて直接生成され、そのスロットとして「再利用されるテンプレート」が使用されます。コンポーネントがレンダリングされると、内部が実行されるrender = slots.default
ので、「再利用するテンプレート」 が記録されました。「再利用するテンプレート」がスロットとして記録されているということと同じです。
また、
define
関数は何も返さないため、レンダリングされません。 -
reuse
関数 (コンポーネント)また、
defineComponent
関数、内部でレンダリングされるものは何ですか?define
関数に記録することrender
で、再利用を実現します。閉会式はこちら
-
パラメーターの受け渡し
render
記録されるのはスロットなので、引数はスロットとまったく同じように渡されます。 -
スコープ (コンテキスト)
スロットが配置されているスコープは親コンポーネントのスコープであるため、「再利用するテンプレート」はコンポーネントの変数とイベントを直接使用できます。大神がスロットの仕組みをフル活用!
うわー、これはなんておいしいんだろう
全体のアイデアはどれも超一流の知識ではなく、とてもシンプルですがとてもエレガントなので、マスターはマスターのままです! ハハ!
3. 注意事項
-
乱用しないでください
うまく機能しますが、乱用しないでください。
再利用可能な部品が現在のコンポーネントでのみ使用され、保守性が保証されている場合は、それを使用することをお勧めします。また、再利用の観点からも、プロジェクトの維持費の観点からも、サブコンポーネントに分割するタイミングで分割することをお勧めします。
-
パフォーマンスを心配する必要はありません
多重化の処理オーバーヘッドは非常に小さく、パフォーマンスへの影響は基本的に心配する必要がないことが実装からわかります。
4. 今後の展開
実際に遭遇することも珍しくありませんし、コミュニティの多くの学生が反応しているからです。
したがって、将来的には公式が直接サポートする可能性があります。