Vue中子组件通过v-model动态修改父组件中的值
父子通信中的子传父-使用v-model实现双向数据绑定
-
现有需求:通过子组件中的输入框来动态绑定父组件中data中的数据。
-
代码实现
-
- 父组件使用porps来向子组件传值
- 子组件通过自己定义的两个属性(number1,number2)来接受父组件的值(num1,num2)
- 通过v-model属性将输入框与子组件的number1和number2来进行绑定
-
-
结果
-
上面功能的实现的确没有问题,但思路有问题,而且在一般情况下,vue是不建议通过这种方式来直接修改父组件中的值的。
-
代码如下:
-
-
<body>
<div id="app">
<cpn :number1="num1" :number2="num2"></cpn>
</div>
<template id="cpm">
<div>
<h2>props:{{number1}}</h2>
<h2>data:{{dnumber1}}</h2>
<input type="text" v-model="number1">
<h2>props:{{number2}}</h2>
<h2>data:{{dnumber2}}</h2>
<input type="text" v-model="number2">
</div>
</template>
<script>
const app = new Vue({
el: '#app',
data: {
num1: 1,
num2: 0
},
components: {
cpn: {
template: '#cpm',
props: {
number1: Number,
number2: Number
},
},
},
})
</script>
</body>
- 运行截图
反思:这样虽然可以实现子组件向组件传值,但这种方法在vue看来是极为不推荐的。
- 代码改进
- 代码实现
- 在上面的基础上,我在子组件中定义两个data属性(dnumber1,dnumber2),用来保存父组件传过来的值
- 将input绑定的属性从number1改为dnumber1,number2同理
- 代码实现
<body>
<div id="app">
<cpn :number1="num1" :number2="num2"></cpn>
</div>
<template id="cpm">
<div>
<!-- 用来查看父子组件中,值的变化情况 -->
<h2>props:{{number1}}</h2>
<h2>data:{{dnumber1}}</h2>
<input type="text" v-model="dnumber1">
<!-- 用来查看父子组件中,值的变化情况 -->
<h2>props:{{number2}}</h2>
<h2>data:{{dnumber2}}</h2>
<input type="text" v-model="dnumber2">
</div>
</template>
<script>
const app = new Vue({
el: '#app',
data: {
num1: 1,
num2: 0
},
components: {
cpn: {
template: '#cpm',
props: {
number1: Number,
number2: Number
},
data() {
return {
dnumber1: this.number1,
dnumber2: this.number2
}
}
},
},
})
</script>
</body>
- 运行截图
反思:这样是不报错了,但是父组件中的值没有被修改呀,看来得使用
自定义事件
来向父组件传值了!
-
代码改进
-
自组件使用
$emit
自定义事件创建一个自定义事件dnumber1change
,dnumber2change
,并将dnumber1,和dnumber2传递过去。- 父组件定义监听函数
number1chage
,number2change
,在这个函数中,将取得的值value
传递给父组件data
中的值,从而将num1
,和num2
的值进行修改。
- 父组件定义监听函数
-
<body>
<div id="app">
<cpn :number1="num1" :number2="num2" @dnumber1change="number1chage" @dnumber2change="number2change"></cpn>
</div>
<template id="cpm">
<div>
<!-- 用来查看父子组件中,值的变化情况 -->
<h2>props:{{number1}}</h2>
<h2>data:{{dnumber1}}</h2>
<input type="text" :value="dnumber1" @input="num1Input">
<!-- 用来查看父子组件中,值的变化情况 -->
<h2>props:{{number2}}</h2>
<h2>data:{{dnumber2}}</h2>
<input type="text" :value="dnumber2" @input="num2Input">
</div>
</template>
<script>
const app = new Vue({
el: '#app',
data: {
num1: 1,
num2: 0
},
methods: {
number1chage(value) {
this.num1 = parseInt(value)
},
number2change(value) {
this.num2 = parseInt(value)
}
},
components: {
cpn: {
template: '#cpm',
props: {
number1: Number,
number2: Number
},
data() {
return {
dnumber1: this.number1,
dnumber2: this.number2
}
},
methods: {
num1Input(event) {
this.dnumber1 = event.target.value;
// 为了父组件可以修改值,发出一个事件
this.$emit('dnumber1change', this.dnumber1);
},
num2Input(event) {
this.dnumber2 = event.target.value;
// 为了父组件可以修改值,发出一个事件
this.$emit('dnumber2change', this.dnumber2);
}
}
},
}
})
</script>
</body>
-
运行截图
总结:v-model的本质
- < input type="text" v-model="dnumber1">
- < input type="text" v-bind:value="dnumber1" @input="dnumber1=$event.target.value">
下面的代码等同于上面的代码, 这也就是需求实现的
关键