v-модель и дочерние компоненты?
У меня есть форма и привязка ввода с использованием v-модели:
<input type="text" name="name" v-model="form.name">
Теперь я хочу извлечь вход и сделать его собственным компонентом, как вы привязываете значения дочернего компонента к объекту form.name
?
Ответы
Ответ 1
Как указано в документации,
v-model
- это просто синтаксический сахар для:
<input
v-bind:value="something"
v-on:input="something = $event.target.value">
Чтобы реализовать директиву v-model
для настраиваемого компонента:
- указать
value
для компонента - установите свойство данных в значение
value
prop в методе data
(так как вы не должны изменять значение prop изнутри компонента). - испускать
input
событие со значением свойства данных всякий раз, когда он изменяется
Вот простой пример:
Vue.component('my-input', {
template: '
<div>
My Input:
<input v-model="inputVal">
</div>
',
props: ['value'],
data() {
return { inputVal: this.value }
},
watch: {
inputVal(val) {
this.$emit('input', val);
}
}
})
new Vue({
el: '#app',
data() {
return { foo: 'a', bar: 'b' }
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.3/vue.min.js"></script>
<div id="app">
<!-- using v-model... -->
<my-input v-model="foo"></my-input>
<!-- is the same as this... -->
<my-input :value="bar" @input="bar = $event"></my-input>
{{ foo }}<br>
{{ bar }}
</div>
Ответ 2
используйте sync
в своем основном экземпляре, и если вы используете vue> 2.2, вам нужно использовать emit
в компоненте.
Проверьте этот документ: https://alligator.io/vuejs/upgrading-vue-2.3/#propsync
Простой пример (с vue 2.5):
Vue.component('my-input', {
template: '<input v-on:keyup="onChange($event)" :value="field"></div>',
props: ["field"],
methods: {
onChange: function (event) {
this.$emit('update:field', event.target.value);
}
}
});
var vm = new Vue({
el: '#app',
data:{val: ''},
});
h1 span { color: red }
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<div id='app'>
<h1>
value
<span>{{ val }}</span>
</h1>
<my-input :field.sync="val">
</my-input>
</div>
Ответ 3
Вы также можете указать события :value
и @input
для дочернего компонента и использовать события вместо создания часов.
MyInput.vue
<template>
<input
:value="value"
@input="$emit('input', $event.target.value)" />
</template>
<script>
export default {
props: ['value']
};
</script>
Screen.vue
<template>
<my-input v-model="name" />
</template>
<script>
import MyInput from './MyInput.vue';
export default {
components: { MyInput },
data() {
return {
name: ''
}
}
};
</script>
Ответ 4
В приведенном ниже примере показано, как установить модель из родительского в дочерний компонент и синхронизировать данные между ними. Это очень полезно, когда вы разделяете формы приложения на разные компоненты и используете их в разных контекстах. Таким образом, вы можете использовать, например, фрагменты (компоненты) формы в разных местах, не повторяя себя.
РОДИТЕЛЬСКИЙ КОМПОНЕНТ
<template lang="pug">
.parent
Child(:model="model")
br
label(for="c") Set "c" from parent
input(id="c", v-model="model.c")
.result.
<br>
<span> View from parent :</span>
<br>
a = {{ model.a }}
<br>
b = {{ model.b }}
<br>
c = {{ model.c }}
</template>
<script>
import Child from './components/child.vue'
export default {
name: "App",
components: {
Child
},
data() {
return {
// This model is set as a property for the child
model: {
a: 0,
b: 0,
c: 0
}
}
},
};
</script>
ДЕТСКИЙ КОМПОНЕНТ
<template lang="pug">
.child
label(for="a") Set "a" from child
input(id="a", v-model="internalModel.a", @input="emitModel")
br
br
label(for="b") Set "b" from child
input(id="b", v-model="internalModel.b", @input="emitModel")
.result
br
span View from child
br
| a = {{ internalModel.a }}
br
| b = {{ internalModel.b }}
br
| c = {{ internalModel.c }}
</template>
<script>
export default {
name: 'Child',
props: {
model: {
type: Object
}
},
data() {
return {
internalModel: {
a:0,
b:0,
c:0
}
}
},
methods: {
emitModel() {
this.$emit('input', this.internalModel)
}
},
mounted() {
this.internalModel = this.model;
}
}
</script>