Привет всем, яКагуя такая милая. В этой статье будет описано, как реализовать его на пользовательском общедоступном компоненте.
v-model
, Это очень помогает в разработке общедоступных компонентов в реальных проектах!
цель обучения
При самостоятельной инкапсуляции компонентов, особенно при взаимодействии таких компонентов, как поля ввода, раскрывающиеся поля выбора и т. д., как правило, при привязке значений вы используетеv-model
,использоватьv-model
Главное преимущество в том, что нет необходимости запоминать конкретныеprop
Имя поля может быть привязано к значению в компоненте, что снижает стоимость использования компонента.
Ведь хорошая общественная составляющая, прежде всегоAPI
Дизайн должен быть понятным и простым в использовании.
Во-вторых, мы должны постаратьсяПовторная логическая обработкаПоместите его в подкомпонент, что сделает инкапсуляцию компонента более значимой.
Конечно, через изучение этой статьи, даже если это не интерактивный компонент,Подойдет любой компонентдостичь таким образомv-model
.
Давайте узнаем, как инкапсулировать общие компонентыv-model
.
Основные понятия v-модели
v-model
фактически$emit('input')
так же какprops:value
Комбинированный синтаксический сахар, если в компоненте выполняются эти два условия, его можно использовать в компоненте.v-model
.
Хотя есть некоторые отличия в некоторых интерактивных компонентах,Например:
checkbox
а такжеradio
использоватьprops:checked
свойства и$emit('change')
мероприятие.
select
использоватьprops:value
свойства и$emit('change')
мероприятие.
Однако, помимо перечисленных выше, другие$emit('input')
так же какprops:value
.
Внедрение цифрового шагомера
Теперь, когда вы знаетеv-model
Конкретный принцип реализации, давайте попробуем самостоятельно инкапсулировать цифровой шагомер, который в основном состоит из двух кнопок увеличения и уменьшения и поля ввода.
Новый компонент
Создать новыйNumberInput
компоненты
<template>
<div>
<button>-1</button>
<input type="text" />
<button>+1</button>
</div>
</template>
<script>
export default {
name: "NumberInput"
}
</script>
props:value
Сначала напишите первое условие,props:value
, Так как это цифровой шагомер, поэтомуvalue
Тип должен быть числовым и должен быть параметром, который необходимо передать.
<input type="number" :value="value" />
props:{
value:{
type: Number,
default: 0,
require: true
}
}
Конечно, написать сюда, будет проблема, т.к.props
Есть одна характеристика, т.Однонаправленный поток данных, для понимания потока данных.
вы также можете назвать этоОдносторонняя привязка нисходящего канала, что эквивалентно значению родительского компонента, проходящего черезprops
При передаче дочернему компоненту изменение значения в родительском компоненте будет передано дочернему компоненту, а изменение этого значения в дочернем компоненте не может быть передано родительскому компоненту.(Хотя возможно, консоль выдаст предупреждение, а это официально не рекомендуется)
Вы можете представить себе водопад сверху вниз. Родительский компонент находится сверху, а дочерний компонент снизу. Этот поток воды может течь только сверху вниз, но не снизу вверх. Это неправильно, и брат Ньютон не не согласен.
Конечно, появление этого одностороннего потока данных в основном связано с предотвращением случайного обновления состояния родительского компонента дочерним компонентом, что затрудняет понимание потока данных вашего приложения.
$emit('input')
упомянутый вышеОднонаправленный поток данныхЕсть точка вне следуетизменить внутри дочернего компонентаprops
.
Значит, нам нужно переписать его по-другому, определив переменнуюcurrentValue
, чтобы избежать для подкомпонентовprops
Прямая модификация , все для<input>
Модификация поля ввода выполняется с помощью этогоcurrentValue
записать.
<input type="number" :value="currentValue" />
props:{
value:{
type: Number,
default: 0
require: true
}
},
data(){
return{
currentValue: this.value
}
}
В это время мы сначала модифицируемcurrentValue
значение, затем передать$emit('input')
чтобы уведомить родительский компонент, что нашvalue
Измените значение родительского элементаprops
Значение изменяется, а затем значение в дочернем компоненте обновляется через односторонний поток данных родительского компонента. чтобы избежать подкомпонентов вprops
прямая модификация.
<input type="number" :value="currentValue" @input="changeValue" />
methods:{
changeValue(e){
this.currentValue = parseInt(e.target.value);
this.$emit('input', this.currentValue);
}
}
Теперь этого прекрасно избегаютОднонаправленный поток данныхПроблема, поставленнаяcurrent
переменные для записи значений и избегайтеprops
прямая модификация. потом$emit('input')
Пусть значение, связанная в родительском компоненте, будет измененаОдносторонняя привязка нисходящего канала, измененный родительским компонентомprops
Потом точно так же аккумуляторы слева и справа тоже очень просто, и это тоже правильноcurrentValue
изменение значения плюс$emit('input')
коробка передач.
<button @click="increase(-1)">-1</button>
<button @click="increase(1)">+1</button>
methods:{
increase(value){
this.currentValue+= value;
this.$emit('input', this.currentValue);
}
}
На данный момент остается еще один важный шаг, которыйwatch
монитор
watch
монитор
Когда компонент инициализируется изvalue
Получите значение один раз и измените его непосредственно, когда родительский компонентv-model
При привязке значения дляvalue
Особенно важен своевременный мониторинг.
Итак, наконец, мы должны добавить еще один шагwatch
монитор.
watch:{
value(newVal){
this.currentValue = newVal;
}
},
До сих порv-model
Компоненты упакованы.
Итак, полный код выглядит следующим образом
<template>
<div>
<button @click="increase(-1)">-1</button>
<input type="number" :value="currentValue" @input="changeValue" />
<button @click="increase(1)">+1</button>
</div>
</template>
<script>
export default {
name: "NumberInput",
props:{
value:{
type: Number,
default: 0,
require: true
}
},
data(){
return{
currentValue: this.value
}
},
watch: {
value(newVal){
this.currentValue = newVal;
}
},
methods:{
changeValue(e){
this.currentValue = parseInt(e.target.value);
this.$emit('input', this.currentValue);
},
increase(value){
this.currentValue+= value;
this.$emit('input', this.currentValue);
}
}
}
</script>
<style lang="stylus" scoped>
</style>
Использование компонентов
<NumberInput v-model="number"></NumberInput>
import NumberInput from "./NumberInput";
export default {
components:{NumberInput},
data(){
return{
number: 10
}
}
}
Вывод в конце статьи
Любой компонент может быть реализованv-model
.
реализоватьv-model
Основные пункты следующие:
-
props:value
используется для контроля
v-model
Связанное значение. -
currentValue
из-за
单向数据流
причина, нужно использоватьcurrentValue
Избегайте подкомпонентов дляprops
прямая операция. -
$emit('input')
используется для контроля
v-model
операции изменения значения, все дляprops
Когда значение изменяется, родительский компонент должен быть уведомлен. -
watch
мониторКогда компонент инициализируется из
value
Получите значение один раз и измените его непосредственно, когда родительский компонентv-model
При привязке значения дляvalue
своевременный мониторинг.
Пасхалки в конце статьиmodel
Например, некоторые люди говорят, что я просто не хочу использоватьprops:value
так же как$emit('input')
, я хочу изменить имя, то в это время,model
может помочь вам сделать это.
Потому что эти два имени имеют другое использование в некоторых собственных элементах формы.
export default {
model: {
prop: 'number',
event: 'change'
},
}
В данном случае это использованиеprops:number
так же как$emit('change')
.