Vueカスタム入力
私たちのほとんどは、カスタム入力コンポーネントを構築します.その背後には複数の理由がありますが、一般的に、カスタムスタイルを持ち、再利用することができます.
それは簡単に聞こえるかもしれませんが、いくつかのgotchasを持っていると我々はいくつかの詳細を確認するために、ドキュメントを介して行くまで時間が経つ.あなたがいくつかのVue概念に精通していないなら、それは少し複雑になります.
先月、2021年2月、再び起こった.可能なとき、私はVueスラックグループの人々を助けようとします、そして、この質問は再び現れました.この質問ではなく、カスタム入力コンポーネントの構築に問題がありました.その問題はいくつかの概念に関連していた.
自分自身のためにこの知識を統合し、他の人のためのドキュメントとしてそれを使用するために、私はカスタム入力を書くプロセスをラップすることを決めた.
目次 v-model and The wrong custom input component
The happy custom input component Adding validation (or operation on data change) Combining computed and Extra: the So what?
Vモデル
公式ドキュメントは、どのように動作するかを説明する素晴らしい仕事です.https://vuejs.org/v2/guide/forms.html
手短に言えば、以下のテンプレートがあります.
上記のコンポーネントの問題は、再利用できないことです.私たちがユーザ名と電子メールを必要とするページを持っていると想像してください.上記のコンポーネントは、データがコンポーネント自体の中にあるので、電子メールケースを処理しません.それはカスタム入力コンポーネントが輝き、またその課題の一つです
間違ったカスタム入力コンポーネント
さて、なぜ私はこの例を示していますか?答えはです:これは私たちのほとんどは、しようとする最初のアプローチです.
カスタム入力コンポーネントの使い方を見てみましょう.
上記のコードを試してみると、予想通りに動作しますが、なぜ間違っていますか?コンソールを開くと、次のようになります.
この問題を見るもう一つの方法は
次のステップは上記の例を再加工し、期待通りに動作するようにすることです.
幸せなカスタム入力コンポーネント
幸せなカスタム入力コンポーネントは、そのプロップを変異せず、親コンポーネントへの変更を発行します.
The docs この正確な例がありますが、もう少しここに行きます.我々が医者に続くならば
検証の追加
データが変化したとき、何かをする必要がある場合には、例えば、空で、エラーメッセージを表示するかどうかを確認してください.以下のコンポーネントを変更します.
私たちがより多くのものを加えるならば、我々は最も多分この構成要素を拡大していて、ものはすべての上に広げられます
計算と
そのようなコンポーネントを書き直しましょう.
我々がそれを達成することができる1つの涼しいことは修飾子の使用です
これは、簡単な入力コンポーネントの良いアプローチです.物事は、より複雑になることができますし、このアプローチでは、すべてのユースケースを満たすことはありません.良い例は、あなたが
エキストラ
The
この場合は、
何?
私のテイクは、カスタム入力がどの程度複雑になるかによるものです. それは1つのコンポーネントのスタイルを集中化するためにつくられました、そして、APIはかなりVueのAPIの上にあります:
他のすべて(これはあなたが必要なものをサポートするために多くの前のセットアップを微調整する必要があることを意味します):リスナー、ウォッチャーと他の必要があります.複数の状態を持っているかもしれません(ロード状態が役に立つかもしれないasync検証を考えます)、あるいは、あなたは支持したいかもしれません
それは簡単に聞こえるかもしれませんが、いくつかのgotchasを持っていると我々はいくつかの詳細を確認するために、ドキュメントを介して行くまで時間が経つ.あなたがいくつかのVue概念に精通していないなら、それは少し複雑になります.
先月、2021年2月、再び起こった.可能なとき、私はVueスラックグループの人々を助けようとします、そして、この質問は再び現れました.この質問ではなく、カスタム入力コンポーネントの構築に問題がありました.その問題はいくつかの概念に関連していた.
自分自身のためにこの知識を統合し、他の人のためのドキュメントとしてそれを使用するために、私はカスタム入力を書くプロセスをラップすることを決めた.
目次
<input>
The happy custom input component
v-model
model
property Vモデル
<input>
一旦我々がVueでフォームを構築し始めるならば、我々は指令を学びますv-model
. それは私たちのための多くのハードワークを行います:それは入力に値をバインドします.これは、入力の値を変更するたびに、変数も更新されることを意味します.公式ドキュメントは、どのように動作するかを説明する素晴らしい仕事です.https://vuejs.org/v2/guide/forms.html
手短に言えば、以下のテンプレートがあります.
<!-- UsernameInput.vue -->
<template>
<label>
Username
<input type="text" name="username" v-model="username">
</label>
</template>
<script>
export default {
name: 'UsernameInput',
data() {
return {
username: 'Initial value',
};
},
}
</script>
私たちには、ある入力がありますInitial value
初期値とユーザー名のデータが自動的に入力された値を変更すると自動的に更新されます.上記のコンポーネントの問題は、再利用できないことです.私たちがユーザ名と電子メールを必要とするページを持っていると想像してください.上記のコンポーネントは、データがコンポーネント自体の中にあるので、電子メールケースを処理しません.それはカスタム入力コンポーネントが輝き、またその課題の一つです
v-model
一貫性のある行動間違ったカスタム入力コンポーネント
さて、なぜ私はこの例を示していますか?答えはです:これは私たちのほとんどは、しようとする最初のアプローチです.
カスタム入力コンポーネントの使い方を見てみましょう.
<!-- App.vue -->
<template>
<custom-input :label="label" v-model="model" />
</template>
<script>
import CustomInput from './components/CustomInput.ue';
export default {
name: 'App',
components: { CustomInput },
data() {
return {
label: 'Username',
model: '',
};
},
}
</script>
カスタム入力はlabel
とv-model
この場合、以下のコンポーネントのようになります.<!-- CustomInput.vue -->
<template>
<label>
{{ label }}
<input type="text" :name="name" v-model="value" />
</label>
</template>
<script>
export default {
name: 'CustomInput',
props: {
label: {
type: String,
required: true,
},
value: {
type: String,
required: true,
},
},
computed: {
name() {
return this.label.toLowerCase();
},
},
}
</script>
まず、それはlabel
プロパティとしてname
その上に(また、プロパティである可能性があります).第二に、それはvalue
プロパティを<input>
通しv-model
. その理由はわかるin the docs しかし、短いとき、我々が使うときv-model
カスタムコンポーネントでvalue
からの値であるプロパティとしてv-model
変数.この例では、model
で定義App.vue
.上記のコードを試してみると、予想通りに動作しますが、なぜ間違っていますか?コンソールを開くと、次のようになります.
[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "value"
我々は財産を変異していると文句を言う.Vueが機能する方法:子コンポーネントは親コンポーネントから派生した子要素を持ち、子コンポーネントは親コンポーネントへの変更を表します.使用v-model
とvalue
親コンポーネントから得たpropはそれに違反します.この問題を見るもう一つの方法は
App.vue
このように:<!-- App.vue -->
<template>
<custom-input :label="label" :value="model" />
</template>
...
主な違いは:value
の代わりにv-model
. この場合、我々はちょうど合格しているmodel
にvalue
プロパティ.この例はまだ動作し、コンソールで同じメッセージを取得します.次のステップは上記の例を再加工し、期待通りに動作するようにすることです.
幸せなカスタム入力コンポーネント
幸せなカスタム入力コンポーネントは、そのプロップを変異せず、親コンポーネントへの変更を発行します.
The docs この正確な例がありますが、もう少しここに行きます.我々が医者に続くならば
CustomInput
以下のようになります.<!-- CustomInput.vue -->
<template>
<label>
{{ label }}
<input type="text" :name="name" :value="value" @input="$emit('input', $event.target.value)" />
</label>
</template>
<script>
export default {
name: 'CustomInput',
props: {
label: {
type: String,
required: true,
},
value: {
type: String,
required: true,
},
},
computed: {
name() {
return this.label.toLowerCase();
},
},
}
</script>
これで作業ができる.両方に対してもApp.vue
, 使用するものv-model
, すべてが期待通りに動作し、使用するもの:value
私たちがプロパティを突然変異するのを止めたので、それがもう働きません.検証の追加
データが変化したとき、何かをする必要がある場合には、例えば、空で、エラーメッセージを表示するかどうかを確認してください.以下のコンポーネントを変更します.
<!-- CustomInput.vue -->
<template>
...
<input type="text" :name="name" :value="value" @input="onInput" />
...
</template>
<script>
...
methods: {
onInput(event) {
this.$emit('input', event.target.value);
}
}
...
</script>
次に空のチェックを追加します.<!-- CustomInput.vue -->
<template>
...
<p v-if="error">{{ error }}</p>
...
</template>
<script>
...
data() {
return {
error: '',
};
},
...
onInput(event) {
const value = event.target.value;
if (!value) {
this.error = 'Value should not be empty';
}
this.$emit('input', event.target.value)
}
...
</script>
これは、作品の種類は、最初のエラーが表示されませんし、入力すると、エラーメッセージが表示されます削除します.問題は、エラーメッセージが消えないことです.これを修正するには、値プロパティにWatcherを追加し、更新されるたびにエラーメッセージを消去する必要があります.<!-- CustomInput.vue -->
...
<script>
...
watch: {
value: {
handler(value) {
if (value) {
this.error = '';
}
},
},
},
...
</script>
我々は、類似した結果をelse
内部onInput
. Watcherを使用すると、ユーザーが入力値を更新する前に有効にすることができます.私たちがより多くのものを加えるならば、我々は最も多分この構成要素を拡大していて、ものはすべての上に広げられます
<script>
ブロック.物事をグループ化するために、我々は異なるアプローチを試みることができますv-model
.計算と
v-model
その代わりにinput
イベントとして再び放出すると、我々は力を活用することができますv-model
and computed
. それは我々が間違ったアプローチを得ることができる最も近いが、まだそれを右にする😅そのようなコンポーネントを書き直しましょう.
<!-- CustomInput.vue -->
<template>
...
<input type="text" :name="name" v-model="model" />
...
</template>
<script>
...
computed: {
...
model: {
get() {
return this.value;
},
set(value) {
this.$emit('input', value);
},
},
},
...
</script>
我々は、取り除くことができますonInput
メソッドとウォッチャーから我々はすべての内のすべてを扱うことができますget/set
計算されたプロパティからの関数.我々がそれを達成することができる1つの涼しいことは修飾子の使用です
.trim/number
これは手動で書かなければなりません.これは、簡単な入力コンポーネントの良いアプローチです.物事は、より複雑になることができますし、このアプローチでは、すべてのユースケースを満たすことはありません.良い例は、あなたが
.lazy
親コンポーネントの修飾子を手動で聞く必要がありますinput
and change
.エキストラ
model
プロパティThe
model
property ビットをカスタマイズできますv-model
動作.どのプロパティをマップするかを指定することができますvalue
, そして、どのイベントが放出されるか、デフォルトはそうですinput
or change
時.lazy
を使用する.この場合は、
value
何か他のもののために、それが特定の前後関係のためにより多くの感覚を作るかもしれないか、ちょうどより明白なものを作りたいです、そして、名前を変えてくださいvalue
to model
, 例えば.ほとんどの場合、入力をオブジェクトとして取得するときにチェックボックス/ラジオをカスタマイズするのに使うかもしれません.何?
私のテイクは、カスタム入力がどの程度複雑になるかによるものです.
computed
+ v-model
. それは我々の例でかなり落ちます、それは単純な小道具と複雑な合法化を持ちません.<!-- CustomInput.vue -->
<template>
<label>
{{ label }}
<input type="text" :name="name" v-model="model" />
</label>
</template>
<script>
export default {
name: 'CustomInput',
props: {
label: {
type: String,
required: true,
},
value: {
type: String,
required: true,
},
},
computed: {
name() {
return this.label.toLowerCase();
},
model: {
get() {
return this.value;
},
set(value) {
this.$emit('input', value);
},
},
},
}
</script>
.lazy
親コンポーネントからの修飾子は、最初のアプローチを避ける良い例です.<!-- CustomInput.vue -->
<template>
<label>
{{ label }}
<input type="text" :name="name" :value="value" @input="onInput" @change="onChange" />
</label>
</template>
<script>
export default {
name: 'CustomInput',
props: {
label: {
type: String,
required: true,
},
value: {
type: String,
required: true,
},
},
/* Can add validation here
watch: {
value: {
handler(newValue, oldValue) {
},
},
}, */
computed: {
name() {
return this.label.toLowerCase();
},
},
methods: {
onInput(event) {
// Can add validation here
this.$emit('input', event.target.value);
},
onChange(event) { // Supports .lazy
// Can add validation here
this.$emit('change', event.target.value);
},
},
}
</script>
それを見直してくれてありがとうReference
この問題について(Vueカスタム入力), 我々は、より多くの情報をここで見つけました https://dev.to/viniciuskneves/vue-custom-input-bk8テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol