目次
まえがき
テンプレートを定義するコンポーネントを取得し、createReusableTemplate を通じてテンプレートを再利用します
Vue3 では、スクリプトのセットアップに加えて、
はい、とても簡単です。Define の場合、コア コードはこれらの 2 ~ 3 行です
同様に、テンプレートで Reuse を使用する場合、セットアップに入り、レンダリングするすべてのパラメータを渡し、レンダリングの結果を返します。
添加类型支持
小结一下
加个彩蛋吧
如何魔改
ホームページ ウェブフロントエンド Vue.js Vue3 の再利用可能なコンポーネントの使用方法

Vue3 の再利用可能なコンポーネントの使用方法

May 20, 2023 pm 07:25 PM
vue3

    まえがき

    vue であれ、react であれ、複数の重複コードに遭遇した場合、ファイルを埋め尽くすのではなく、これらのコードを再利用する方法を考えます。冗長コード付き。

    実際、vue と React はどちらもコンポーネントを抽出することで再利用を実現できますが、小さなコードの断片に遭遇し、別のファイルを抽出したくない場合は、React は対応するコンポーネントを宣言できます。

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    const Demo: FC<{ msg: string}> = ({ msg }) => {

      return <div>demo msg is { msg } </div>

    }

    const App: FC = () => {

      return (

      <>

        <Demo msg="msg1"/>

        <Demo msg="msg2"/>

      </>

      )

    }

    ログイン後にコピー

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    /** render function的形式 */

    const App: FC = () => {

      const renderDemo = (msg : string) => {

        return <div>demo msg is { msg } </div>

      }

      return (

      <>

        {renderDemo(&#39;msg1&#39;)}

        {renderDemo(&#39;msg2&#39;)}

      </>

      )

    }

    ログイン後にコピー

    ただし、.vue テンプレートの場合は、react のように使用できません。単一のファイルで他のコンポーネントを宣言します。コードを再利用したい場合は、コンポーネントを抽出するだけです。 ######しかし、しかし!上のDemoコンポーネントのように、ところどころにコードが2~3行しかないのですが、1つのコンポーネントに抽出して必要がないと思ったら、CVメソッドしかないのでしょうか? (もちろん、リストのようなものであれば、v-for コードを使用できますが、これはここで紹介するシナリオではありません)

    急いでいるのはわかりますが、まだ心配する必要はありません。 。コンポーネントのスコープ内で再利用するテンプレートを丸で囲むことができる場合は、Vue に「このコードを丸で囲んだのは、いくつかの場所で使用する必要があるためです。ただし、現時点ではこの機能はサポートしていないようです。しかし、 、大丈夫、達成できなかったら実装します

    大まかな実装計画はこんな感じです:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    <template>

      <DefineFoo v-slot="{ msg }">

        <div>Foo: {{ msg }}</div>

      </DefineFoo>

      ...

      <ReuseFoo msg="msg1" />

      <div>xxx</div>

      <ReuseFoo msg="msg2" />

      <div>yyy</div>

      <ReuseFoo msg="msg3" />

    </template>

    ログイン後にコピー

    Vue3 の再利用可能なコンポーネントの使用方法でも、何がこの計画はどうですか?実装はどうですか?結局のところ、あなたはすでに天に誇っているので、それを達成できない場合は、まだ困難に耐えなければなりません。 OK、渡さないでください。antfu のボスが実際に実装したもので、

    createReusableTemplate

    と呼ばれ、VueUse に配置されています。ドキュメントをクリックすると詳細が表示されます。 使用方法

    テンプレートを定義するコンポーネントを取得し、createReusableTemplate を通じてテンプレートを再利用します

    1

    2

    3

    4

    <script setup>

    import { createReusableTemplate } from &#39;@vueuse/core&#39;

    const [DefineTemplate, ReuseTemplate] = createReusableTemplate()

    </script>

    ログイン後にコピー

    次に、コードを再利用する場所で

    DefineTemplate# を使用します ##これをまとめます。その後、

    ReuseTemplate を通じて単一ファイル テンプレートのどこでも使用できます:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    <template>

      <DefineTemplate>

        <!-- 这里定义你要复用的代码 -->

      </DefineTemplate>

        <!-- 在你要复用的地方使用ReuseTemplate, -->

        <ReuseTemplate />

        ...

        <ReuseTemplate />

    </template>

    ログイン後にコピー
    ⚠️ DefineTemplate は ReuseTemplate

    #の前に使用する必要があります。 createReusableTemplate は、Tuple、つまり定義と再利用のコンポーネントのペアを返すため、上記の例により、単一のファイル内で複数のコードを再利用できます。

    また、実際に定義を返し、オブジェクトの構造化によって再利用することもできます (これは素晴らしいことですが、この記事では詳しく説明しません。興味があれば、次回共有します)。使用法は同じです。例は次のとおりです。

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    <script setup lang="ts">

    const [DefineFoo, ReuseFoo] = createReusableTemplate<{ msg: string }>()

    const TemplateBar = createReusableTemplate<{ msg: string }>()

    const [DefineBiz, ReuseBiz] = createReusableTemplate<{ msg: string }>()

    </script>

    <template>

      <DefineFoo v-slot="{ msg }">

        <div>Foo: {{ msg }}</div>

      </DefineFoo>

      <ReuseFoo msg="world" />

      <!-- 看这里 -->

      <TemplateBar.define v-slot="{ msg }">

        <div>Bar: {{ msg }}</div>

      </TemplateBar.define>

      <TemplateBar.reuse msg="world" />

      <!-- Slots -->

      <DefineBiz v-slot="{ msg, $slots }">

        <div>Biz: {{ msg }}</div>

        <component :is="$slots.default" />

      </DefineBiz>

      <ReuseBiz msg="reuse 1">

        <div>This is a slot from Reuse</div>

      </ReuseBiz>

      <ReuseBiz msg="reuse 2">

        <div>This is another one</div>

      </ReuseBiz>

    </template>

    ログイン後にコピー

    これは本当に魔法です。実装方法

    Vue3 の再利用可能なコンポーネントの使用方法上記の使用法を紹介しましたが、誰もできないと思います。それを理解してください。開始コストは確かに 0 です。次に、これがどのように達成されるかを見てみましょう。

    Vue3 では、スクリプトのセットアップに加えて、

    defineComponent

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    const Demo = defineComponent({

      props: {

        ...,

      },

      setup(props, { attrs, slots }) {

        return () => {

          ...

        }

      }

    })

    ログイン後にコピー

    を通じてコン​​ポーネントを定義できることがわかっています。次に、テンプレートを定義する方法を見てみましょう<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>&lt;DefineFoo v-slot=&quot;{ msg }&quot;&gt; &lt;div&gt;Foo: {{ msg }}&lt;/div&gt; &lt;/DefineFoo&gt;</pre><div class="contentsignin">ログイン後にコピー</div></div>デジャブのように見えますか? v-slot?、えっ、くそー、これはスロットじゃないですか!また、テンプレートコードはデフォルトのスロットに配置されるようです。

    さて、Define 関数の実装方法を見てみましょう。

    Define の実装

    テンプレートがデフォルト スロットで定義されていると述べました。その後、ローカル変数 render を定義できます。その後、テンプレートで Define を使用すると、セットアップに入ります。 . この時slot.defaultを取得してレンダーに置くと良いのではないでしょうか? , コードは次のとおりです

    1

    2

    3

    4

    5

    6

    7

    8

    9

    let render: Slot | undefined

    const Define = defineComponent({

      setup(props, { slots, }) {

        return () => {

          /** 这里拿到默认插槽的渲染函数 */

          render = slots.default

        }

      }

    })

    ログイン後にコピー

    はい、とても簡単です。Define の場合、コア コードはこれらの 2 ~ 3 行です

    再利用の実装

    上記の render 関数を使用して、Reuse を使用する場合、取得した v-slot や attrs などを render に渡すのは良いことではないでしょうか。

    同様に、テンプレートで Reuse を使用する場合、セットアップに入り、レンダリングするすべてのパラメータを渡し、レンダリングの結果を返します。

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    const reuse = defineComponent({

      setup(_, { attrs, slots }) {

        return () => {

          /**

           * 没有render,有两种可能

           * 1. 你没Define

           * 2. Define写在Reuse后面

           **/

          if (!render && process.env.NODE_ENV !== &#39;production&#39;)

            throw new Error(`[vue-reuse-template] Failed to find the definition of template${name ? ` "${name}"` : &#39;&#39;}`)

          return render?.({ ...attrs, $slots: slots })

        }

      },

    })

    ログイン後にコピー

    上記の属性もプロパティです。 Reuse

    1

    <ReuseFoo msg="msg1" />

    ログイン後にコピー

    にアップロードしました。なぜ $slots を渡す必要があるのですか?

    実際には上記の例があります。テンプレートでは、動的コンポーネント

    # を通じてスロットの実際の値を取得することもできます。 ## コンテンツ

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    <DefineBiz v-slot="{ msg, $slots }">

        <div>Biz: {{ msg }}</div>

        <component :is="$slots.default" />

    </DefineBiz>

    <ReuseBiz msg="reuse 1">

        <div>This is a slot from Reuse</div>

      </ReuseBiz>

    <ReuseBiz msg="reuse 2">

      <div>This is another one</div>

    </ReuseBiz>

    ログイン後にコピー

    #もちろん、デフォルトのスロットだけでなく、他の名前付きスロットも利用可能です

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    <DefineBiz v-slot="{ msg, $slots }">

        <component :is="$slots.header" />

        <div>Biz: {{ msg }}</div>

        <component :is="$slots.default" />

      </DefineBiz>

      <ReuseBiz msg="reuse 1">

        <template #header>

          <div>我是 reuse1的header</div>

        </template>

        <div>This is a slot from Reuse</div>

      </ReuseBiz>

      <ReuseBiz msg="reuse 2">

        <template #header>

          <div>我是 reuse1的header</div>

        </template>

        <div>This is another one</div>

      </ReuseBiz>

    ログイン後にコピー

    Vue3 の再利用可能なコンポーネントの使用方法

    Chuhua のプレイ方法はあなたが決めます~

    型サポート、開発エクスペリエンスを向上

    Vue3 の再利用可能なコンポーネントの使用方法テンプレートを定義しましたが、テンプレートがどのパラメータを受け取り、どのパラメータが渡されるのかを伝える必要があります。それが正しければ、ヒントの種類が間違っていれば、開発エクスペリエンスは非常に悪くなりますが、心配しないでください。上司はこれらのことをすでに検討しています。

    createReusableTemplate 支持泛型参数,也就是说你要复用的模板需要什么参数,只需要通过传入对应类型即可,比如你有个 msg,是 string 类型,那么用法如下

    1

    const [DefineFoo, ReuseFoo] = createReusableTemplate<{ msg: string }>()

    ログイン後にコピー

    然后你就会发现,DefineFoo, ReuseFoo 都会对应的类型提示了

    添加类型支持

    我们上面说是用 defineComponent 得到 Define 和 Reuse,而 defineComponent 返回的类型就是 DefineComponent 呀

    1

    type DefineComponent<PropsOrPropOptions = {}, RawBindings = {}, ...>

    ログイン後にコピー

    假设模板参数类型为 Bindings 的话,那么对于 Reuse 来说,其既支持传参,也支持添加插槽内容,所以类型如下

    1

    2

    3

    4

    5

    6

    7

    8

    type ReuseTemplateComponent<

      Bindings extends object,

      Slots extends Record<string, Slot | undefined>,

      /** Bindings使之有类型提示 */

    > = DefineComponent<Bindings> & {

     /** 插槽相关 */

      new(): { $slots: Slots }

    }

    ログイン後にコピー

    而对于 Define 类型来说,我们知道其 v-slot 也有对应的类型,且能通过$slots 拿到插槽内容,所以类型如下

    1

    2

    3

    4

    5

    6

    7

    type DefineTemplateComponent<

     Bindings extends object,

     Slots extends Record<string, Slot | undefined>,

     Props = {},

    > = DefineComponent<Props> & {

      new(): { $slots: { default(_: Bindings & { $slots: Slots }): any } }

    }

    ログイン後にコピー

    小结一下

    ok,相信我开头说的看懂只需要 1 分钟不到应该不是吹的,确实实现很简单,但功能又很好用,解决了无法在单文件复用代码的问题。

    我们来小结一下:

    • 通过 Define 来将你所需要复用的代码包起来,通过 v-slot 拿到传过来的参数,同时支持渲染其他插槽内容

    • 通过 Reuse 来复用代码,通过传参渲染出不同的内容

    • 为了提升开发体验,加入泛型参数,所以 Define 和 Reuse 都有对应的参数类型提示

    • 要记住使用条件,Define 在上,Reuse 在下,且不允许只使用 Reuse,因为拿不到 render function,所以会报错

    加个彩蛋吧

    实际上多次调用 createReusableTemplate 得到相应的 DefineXXX、ReuseXXX 具有更好的语义化Vue3 の再利用可能なコンポーネントの使用方法

    Vue3 の再利用可能なコンポーネントの使用方法

    也就是说,我不想多次调用 createReusableTemplate 了,直接让 define 和 reuse 支持 name 参数(作为唯一的 template key),只要两者都有相同的 name,那就意味着它们是同一对

    如何魔改

    实际上也很简单,既然要支持 prop name来作为唯一的 template key,那 define 和 reuse 都添加 prop name 不就好?

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    const define = defineComponent({

      props {

        name: String

      }

    })

    const reuse = defineComponent({

      props {

        name: String

      }

    })

    ログイン後にコピー

    然后之前不是有个 render 局部变量吗?因为现在要让一个 Define 支持通过 name 来区分不同的模板,那么我们判断到传入了 name,就映射对应的的 render 不就好?

    这里我们通过 Map 的方式存储不同 name 对应的 render,然后 define setup 的时候存入对应 name 的 render,reuse setup 的时候通过 name 拿到对应的 render,当然如果没传入 name,默认值是 default,也就是跟没有魔改之前是一样的

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    const renderMap = new Map<string, Slot | undefined>()

    const define = defineComponent({

        props: {

          /** template name */

          name: String,

        },

        setup(props, { slots }) {

          return () => {

            const templateName: string = props.name || &#39;default&#39;

            if (!renderMap.has(templateName)) {

              // render = slots.default

              renderMap.set(templateName, slots.default)

            }

          }

        },

      })

      const reuse = defineComponent({

        inheritAttrs: false,

        props: {

          name: String,

        },

        setup(props, { attrs, slots }) {

          return () => {

            const templateName: string = props.name || &#39;default&#39;

            const render = renderMap.get(templateName)

            if (!render && process.env.NODE_ENV !== &#39;production&#39;)

              throw new Error(`[vue-reuse-template] Failed to find the definition of template${templateName}`)

            return render?.({ ...attrs, $slots: slots })

          }

        },

      })

    ログイン後にコピー

    以上がVue3 の再利用可能なコンポーネントの使用方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

    このウェブサイトの声明
    この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

    ホットAIツール

    Undresser.AI Undress

    Undresser.AI Undress

    リアルなヌード写真を作成する AI 搭載アプリ

    AI Clothes Remover

    AI Clothes Remover

    写真から衣服を削除するオンライン AI ツール。

    Undress AI Tool

    Undress AI Tool

    脱衣画像を無料で

    Clothoff.io

    Clothoff.io

    AI衣類リムーバー

    AI Hentai Generator

    AI Hentai Generator

    AIヘンタイを無料で生成します。

    ホットツール

    メモ帳++7.3.1

    メモ帳++7.3.1

    使いやすく無料のコードエディター

    SublimeText3 中国語版

    SublimeText3 中国語版

    中国語版、とても使いやすい

    ゼンドスタジオ 13.0.1

    ゼンドスタジオ 13.0.1

    強力な PHP 統合開発環境

    ドリームウィーバー CS6

    ドリームウィーバー CS6

    ビジュアル Web 開発ツール

    SublimeText3 Mac版

    SublimeText3 Mac版

    神レベルのコード編集ソフト(SublimeText3)

    vue3+vite: src に画像を動的にインポートするために require を使用するときのエラーを解決する方法 vue3+vite: src に画像を動的にインポートするために require を使用するときのエラーを解決する方法 May 21, 2023 pm 03:16 PM

    vue3+vite:src は、イメージとエラー レポートと解決策を動的にインポートするために require を使用します。vue3+vite は複数のイメージを動的にインポートします。vue3。TypeScript 開発を使用している場合、イメージを導入するために require のエラー メッセージが表示されます。requireisnotdefined は使用できません。 vue2 のような imgUrl:require(' .../assets/test.png') は、typescript が require をサポートしていないため、インポートされます。そのため、import が使用されます。解決方法は次のとおりです: awaitimport を使用します

    vue3 プロジェクトで tinymce を使用する方法 vue3 プロジェクトで tinymce を使用する方法 May 19, 2023 pm 08:40 PM

    tinymce はフル機能のリッチ テキスト エディター プラグインですが、tinymce を vue に導入するのは他の Vue リッチ テキスト プラグインほどスムーズではありません。tinymce 自体は Vue には適しておらず、@tinymce/tinymce-vue を導入する必要があります。外国のリッチテキストプラグインであり、中国語版を通過していないため、公式 Web サイトから翻訳パッケージをダウンロードする必要があります (ファイアウォールをバイパスする必要がある場合があります)。 1. 関連する依存関係をインストールします npminstalltinymce-Snpminstall@tinymce/tinymce-vue-S2. 中国語パッケージをダウンロードします 3. スキンと中国語パッケージを導入します. プロジェクトのパブリック フォルダーに新しい tinymce フォルダーを作成し、

    Vue3 でページの部分的なコンテンツを更新する方法 Vue3 でページの部分的なコンテンツを更新する方法 May 26, 2023 pm 05:31 PM

    ページの部分的な更新を実現するには、ローカル コンポーネント (dom) の再レンダリングを実装するだけで済みます。 Vue でこの効果を実現する最も簡単な方法は、v-if ディレクティブを使用することです。 Vue2 では、v-if 命令を使用してローカル dom を再レンダリングすることに加えて、新しい空のコンポーネントを作成することもできます。ローカル ページを更新する必要がある場合は、この空のコンポーネント ページにジャンプしてから、再びジャンプします。 beforeRouteEnter ガードを空白のコンポーネントに配置します。元のページ。以下の図に示すように、Vue3.X の更新ボタンをクリックして赤枠内の DOM を再読み込みし、対応する読み込みステータスを表示する方法を示します。 Vue3.X の scriptsetup 構文のコンポーネントのガードには o しかないので、

    Vue3 がマークダウンを解析し、コードのハイライトを実装する方法 Vue3 がマークダウンを解析し、コードのハイライトを実装する方法 May 20, 2023 pm 04:16 PM

    Vue はブログ フロントエンドを実装しており、マークダウン解析を実装する必要があり、コードがある場合はコードのハイライトを実装する必要があります。 Vue には、markdown-it、vue-markdown-loader、marked、vue-markdown など、マークダウン解析ライブラリが多数あります。これらのライブラリはすべて非常に似ています。ここではMarkedが使用され、コード強調表示ライブラリとしてhighlight.jsが使用されます。 1. 依存ライブラリをインストールする vue プロジェクトの下でコマンド ウィンドウを開き、次のコマンド npminstallmarked-save//marked を入力して、マークダウンを htmlnpmins に変換します。

    vue3 プロジェクトをパッケージ化してサーバーに公開した後、アクセス ページが空白で表示される問題の解決方法 vue3 プロジェクトをパッケージ化してサーバーに公開した後、アクセス ページが空白で表示される問題の解決方法 May 17, 2023 am 08:19 AM

    vue3 プロジェクトがパッケージ化され、サーバーに公開されると、アクセス ページに空白の 1 が表示されます。vue.config.js ファイル内の publicPath は次のように処理されます: const{defineConfig}=require('@vue/cli-service') module.exports=defineConfig({publicPath :process.env.NODE_ENV==='production'?'./':'/&

    Vue3 でアバターを選択してトリミングする方法 Vue3 でアバターを選択してトリミングする方法 May 29, 2023 am 10:22 AM

    最終的な効果は、VueCropper コンポーネントのyarnaddvue-cropper@next をインストールすることです。上記のインストール値は Vue3 用です。Vue2 の場合、または他の方法を参照したい場合は、公式 npm アドレス: 公式チュートリアルにアクセスしてください。また、コンポーネント内で参照して使用するのも非常に簡単です。必要なのは、対応するコンポーネントとそのスタイル ファイルを導入することだけです。ここではグローバルに参照しませんが、import{userInfoByRequest}from'../js/api を導入するだけです。 ' コンポーネント ファイルにインポートします。import{VueCropper}from'vue-cropper&

    vue3+ts+axios+pinia を使用して無意味なリフレッシュを実現する方法 vue3+ts+axios+pinia を使用して無意味なリフレッシュを実現する方法 May 25, 2023 pm 03:37 PM

    vue3+ts+axios+pinia で無意味なリフレッシュを実現 1. まず、プロジェクト内の aiXos と pinianpmipinia をダウンロードします--savenpminstallaxios--save2. axios リクエストをカプセル化-----ダウンロード js-cookienpmiJS-cookie-s// aixosimporttype{AxiosRequestConfig , AxiosResponse}from"axios";importaxiosfrom'axios';import{ElMess

    Vue3 の再利用可能なコンポーネントの使用方法 Vue3 の再利用可能なコンポーネントの使用方法 May 20, 2023 pm 07:25 PM

    はじめに vue であれ、react であれ、複数の繰り返しコードに遭遇した場合、ファイルを冗長なコードの束で埋めるのではなく、これらのコードを再利用する方法を考えます。実際、vue と React はどちらもコンポーネントを抽出することで再利用を実現できますが、小さなコードの断片に遭遇し、別のファイルを抽出したくない場合は、それに比べて、React は同じファイル内で対応するウィジェットを宣言して使用できます。または、次のような renderfunction を通じて実装します。 constDemo:FC=({msg})=>{returndemomsgis{msg}}constApp:FC=()=>{return(

    See all articles