Vuetifyでカスタムコンポーネントを作成する
25961 ワード
こんにちは!
最近、私はVuetifyコンポーネントをカスタマイズして、デフォルトのコンポーネントのルック/フィールを持っています.この記事では、親コンポーネントからプロシージャ、イベント、スロットを継承する方法を示します.私はここで例としてVuetifyを取りました、しかし、プラクティス/出来事/スロットを提供するどんな他のUIフレームワークででも、実行は適用されることができました.それはいくつかの点で誰かの役に立つでしょう.
基本的に主な理由は、時々カバーするユースケースを持っており、Vuetifyコンポーネント(または他のUIフレームワーク)コンポーネントに基づいて再利用可能/カスタマイズ可能なコンポーネントを作成する必要があることです.さてここでなぜですかカスタムコンポーネントを作成すると、既定で提供するUIフレームワークを失うことはありません.
私は私の例をベースに2つの異なるユースケースを定義するつもりです. 最初のユースケースは、例えば定義済み小道具を使用してVuetifyコンポーネントを使用することです 番目のユースケースは、Vuetifyコンポーネントに基づいてカスタムコンポーネントを構築しています.の組み合わせであるコンポーネントを構築するつもりです Vuetify(v 3.0タイタン)の次のバージョンでは、このケースは簡単にカバーされます.以下に例を示します.
しかし、我々はまだこれらのものへの任意のアクセスを持っていない限り、我々はまだ現在のアプローチで立ち往生している.だからここでどのように最小限の努力でそれを行うことができます.
今Vuetifyを使用しているときは、すべてのコンポーネントは、事前定義された小道具/イベント/スロットのいくつかの並べ替えがあります.上記の両方のユースケースをカバーするために、最も重要なことは、親コンポーネントからこれらの小道具/イベント/スロットを継承することです.では、どうやってそれを行うのですか?
定義済み小道具を使用してカスタムテキストフィールドを作成する
したがって、現在これらの小道具を以下のようにカスタムコンポーネントに追加すると、現在動作しません
親から小道具を受け継ぐために、我々は我々を助ける小さいトリックを使うことができます.VUEでは、各親コンポーネントは、それ自身を追加する属性を送信します.それらにアクセスするには
道 Vue 2で.X Vue 3で.X 詳細についてはVue 3 docs.
我々が我々が使っているように我々が我々のカスタムテキストフィールドを使うことができるように、我々は現在親から小道具を継承しています
解決策はここでも簡単です.
リスナーはVue 3で削除されます.xと$ attrsの内部に含まれます.Vue 3を使用している場合.x、コンポーネントをバインドする
スロットは小道具やイベントより少し異なっています.これを行うには確かに異なる方法がありますが、ここで私は親から子に送られたすべてのスロットを転送するために何をしている.
計算された中で親から送られたスロット名をすべて選びます.
すごい!だから今ではフォワーディングv-text-field slots 親から子供へのスロットを使用することを意味
我々は現在、継承で行われます.しかし、あなたのいくつかを使用する必要がある場合
例:
イン イン 両方
要約すると、Vueは私たちが行う必要がある達成するために多くの異なるオプションを提供しています.フレームワークが既に提供しているものを失うことなく、UIフレームワークに基づいたカスタムコンポーネントを作成することは非常に簡単です.確かにいくつかのエッジケースがあるかもしれないが、私は上記の説明しようとしたアプローチでは、それらのほとんどを解決することができますと思う.うまくいけば、このポストは、コンセプトを理解するのに役立ちました!
読んでくれてありがとう!
最近、私はVuetifyコンポーネントをカスタマイズして、デフォルトのコンポーネントのルック/フィールを持っています.この記事では、親コンポーネントからプロシージャ、イベント、スロットを継承する方法を示します.私はここで例としてVuetifyを取りました、しかし、プラクティス/出来事/スロットを提供するどんな他のUIフレームワークででも、実行は適用されることができました.それはいくつかの点で誰かの役に立つでしょう.
なぜ
基本的に主な理由は、時々カバーするユースケースを持っており、Vuetifyコンポーネント(または他のUIフレームワーク)コンポーネントに基づいて再利用可能/カスタマイズ可能なコンポーネントを作成する必要があることです.さてここでなぜですかカスタムコンポーネントを作成すると、既定で提供するUIフレームワークを失うことはありません.
私は私の例をベースに2つの異なるユースケースを定義するつもりです.
v-text-field
デフォルトでは、標準の色などでは、まだオーバーライドできるようにしたいoutlined
or color
デフォルトで定義されていてもプロパティは外側にあります.v-text-field
and v-card
. しかし、あなたはまだデフォルトの小道具/イベント/スロットを使用することができますv-text-field
カスタムコンポーネントを手動で定義しないでください.しかし、我々はまだこれらのものへの任意のアクセスを持っていない限り、我々はまだ現在のアプローチで立ち往生している.だからここでどのように最小限の努力でそれを行うことができます.
ハウ
今Vuetifyを使用しているときは、すべてのコンポーネントは、事前定義された小道具/イベント/スロットのいくつかの並べ替えがあります.上記の両方のユースケースをカバーするために、最も重要なことは、親コンポーネントからこれらの小道具/イベント/スロットを継承することです.では、どうやってそれを行うのですか?
定義済み小道具を使用してカスタムテキストフィールドを作成する
// CustomTextField.vue
<template>
<v-text-field
:value="value"
outlined
color="primary"
@input="v => $emit('input', v)" />
</template>
大丈夫、今では次のように使えます.// Parent.vue
<custom-text-field v-model="value" />
注意:v-model
砂糖構文:value="value" @input="v => $emit('input', v)"
我々は、CustomTextFieldを作成してデフォルトでは、概説され、主要な色をしています.今、我々が使用したいならばflat
or dense
または他の支柱v-text-field
オンcustom-text-field
? または何をオーバーライドする必要がある場合outlined
and color
プロパティはいくつかの点で、どのように我々はそれを行うつもりですか?基本的に我々はできないoutlined
and color
が静的に定義され、何も変更されません.したがって、現在これらの小道具を以下のようにカスタムコンポーネントに追加すると、現在動作しません
<custom-text-field v-model="value" dense :outlined="false" />
これは、親から送信されたすべての小道具を継承していないためです.小道具の継承
親から小道具を受け継ぐために、我々は我々を助ける小さいトリックを使うことができます.VUEでは、各親コンポーネントは、それ自身を追加する属性を送信します.それらにアクセスするには
$attrs
このように親から送信された全てをバインドするためのテンプレートでは// CustomTextField.vue
<template>
<v-text-field
v-bind="$attrs"
:value="value"
outlined
color="primary"
@input="v => $emit('input', v)" />
</template>
<script>
export default {
inheritAttrs: false
}
</script>
とVoila!現在我々<v-text-field>
CustomTextFieldコンポーネントは、<custom-text-field>
. だから今すぐ簡単にすべての支柱を使用することができますv-text-field
提供する<custom-text-field>
そして、このような内部の定義済みの小道具をオーバーライドします.// Parent.vue
<custom-text-field v-model="value" dense :outlined="false" />
重要
道
$attrs
Vue 2の間で振る舞う.Xと3.X!いくつかの違いがあります.$attrs
含まれませんstyles
and classes
それは親から送られた$attrs
含むstyles
and classes
それは親から送られた.Also $listeners
現在、内部に含まれます$attrs
あとで話しましょうイベントの継承
我々が我々が使っているように我々が我々のカスタムテキストフィールドを使うことができるように、我々は現在親から小道具を継承しています
v-text-field
小道具で.それで、イベントについてどうですか?どのように我々は進行中のすべてのイベントを転送することができます<v-text-field>
to <custom-text-field>
?解決策はここでも簡単です.
// CustomTextField.vue
<template>
<v-text-field
v-bind="$attrs"
:value="value"
outlined
color="primary"
v-on="$listeners"
@input="v => $emit('input', v)" />
</template>
<script>
export default {
inheritAttrs: false
}
</script>
我々はバインド$listeners
with v-on
そして、thats!だから今では簡単に任意のイベントを追加することができます<v-text-field>
提供する<custom-text-field>
このように:// Parent.vue
<custom-text-field
v-model="value"
dense
:outlined="false"
@blur="onFocus"
@keypress="onKeypress" />
重要
リスナーはVue 3で削除されます.xと$ attrsの内部に含まれます.Vue 3を使用している場合.x、コンポーネントをバインドする
$attrs
バインドするのに十分でしょう$listeners
, このように:// bind props, attrs, class, style in Vue 3.x
<v-text-field v-bind="$attrs" />
詳細についてはVue 3 docs. スロットの継承
スロットは小道具やイベントより少し異なっています.これを行うには確かに異なる方法がありますが、ここで私は親から子に送られたすべてのスロットを転送するために何をしている.
計算された中で親から送られたスロット名をすべて選びます.
// CustomTextField.vue
export default {
setup(props, ctx) {
const parentSlots = computed(() => Object.keys(ctx.slots))
return { parentSlots }
}
}
その後<template>
パートIスロットを通してループして、すべてのスロットを動的に宣言します.// CustomTextField.vue
// Vue 2.x way, binding $listeners with v-on not needed in Vue 3.x
<template>
<v-text-field
v-bind="$attrs"
:value="value"
outlined
color="primary"
v-on="$listeners"
@input="v => $emit('input', v)"
>
<!-- Dynamically inherit slots from parent -->
<template v-for="slot in parentSlots" #[slot]>
<slot :name="slot" />
</template>
</v-text-field>
</template>
<script>
export default {
setup(props, ctx) {
const parentSlots = computed(() => Object.keys(ctx.slots))
return { parentSlots }
}
}
</script>
なお、△は速記であるv-slot
. ここでは、<template v-for="slot in parentSlots" #[slot]="props">
<slot :name="slot" :props="props" />
</template>
スロットプロップを転送する.でもv-text-field
コンポーネントは、任意の小道具を持っていないスロットをレンダリングしません.私は、これがVuetifyのバグであると思います.Issue here すごい!だから今ではフォワーディングv-text-field slots 親から子供へのスロットを使用することを意味
<v-text-field>
このように:// Parent.vue
<custom-text-field
v-model="value"
dense
:outlined="false"
@blur="onFocus"
@keypress="onKeypress"
>
<template #label>Custom Label</template>
<template #message>Custom Message</template>
</custom-text-field>
ボーナス:小道具/イベント/スロットのカスタムメイドの使用
我々は現在、継承で行われます.しかし、あなたのいくつかを使用する必要がある場合
$attrs
別の要素に?たとえば、カスタムコンポーネントの中に<v-text-field>
and <v-card>
そして、あなたはcolor
両方のプロパティ.この時点で行くには別の方法があります.しかし、私が物事を組織し続けるのが好きである限り、私は1ポイントから組織/コントロールに計算を使います.例:
// CustomTextField.vue
// Vue 2.x way, binding $listeners with v-on not needed in Vue 3.x
<template>
<div>
<v-text-field
v-bind="[textFieldDefaults, $attrs]"
:value="value"
v-on="$listeners"
@input="v => $emit('input', v)"
>
<template v-for="slot in parentSlots" #[slot]>
<slot :name="slot" />
</template>
</v-text-field>
<v-card v-bind="cardDefaults">
<v-card-text>I am a card</v-card-text>
</v-card>
</div>
</template>
<script>
export default {
setup(props, ctx) {
const parentSlots = computed(() => Object.keys(ctx.slots))
const textFieldDefaults = computed(() => ({
outlined: true,
dense: true,
color: 'primary'
}))
const cardDefaults = computed(() => ({
color: ctx.attrs.color || 'primary'
}))
return { parentSlots, textFieldDefaults, cardDefaults }
}
}
</script>
ではここで何が起きているのか.我々は2つの計算変数を作成しているv-text-field
デフォルトとv-card
. textFieldDefaults
デフォルトのテキストフィールドの小道具を定義し、v-bind=[textFieldDefaults, $attrs]
. デフォルト値のいずれかが上位から送信された場合、値$attrs
デフォルトの小道具を上書きする.cardDefaults
私たちだけを取るcolor
プロパティ.あなたが望むならば、あなたは簡単にここから親から送られた他の支柱または聞き手を加えることができました.textFieldDefaults
and cardDefaults
それらを反応させて、親で起こっている変化を聞くことができるように、計算されて、宣言されなければなりません.結論
要約すると、Vueは私たちが行う必要がある達成するために多くの異なるオプションを提供しています.フレームワークが既に提供しているものを失うことなく、UIフレームワークに基づいたカスタムコンポーネントを作成することは非常に簡単です.確かにいくつかのエッジケースがあるかもしれないが、私は上記の説明しようとしたアプローチでは、それらのほとんどを解決することができますと思う.うまくいけば、このポストは、コンセプトを理解するのに役立ちました!
読んでくれてありがとう!
Reference
この問題について(Vuetifyでカスタムコンポーネントを作成する), 我々は、より多くの情報をここで見つけました https://dev.to/onurelibol/creating-custom-components-with-vuetify-inheriting-props-events-slots-in-composition-api-56efテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol