注意:vue组件是此组件的根组件,是该组件中所有注册的组件的父组件
现有需求:通过子组件中的输入框来动态绑定父组件中data中的数据。
代码实现
结果
上面功能的实现的确没有问题,但思路有问题,而且在一般情况下,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>
分析:注册了一个cpn组件,使用父传子的方式传了两个值,一个是number1,一个是number2。cpn组件在声明的时候,使用v-bind单方向绑定了父组件data中的num1,和nmu2。在cpn组件内部,在表单中使用v-model动态绑定number1,和number2。这样就可实现在子组件中设置值,父组件中的data也可以跟着修改的需求。
反思:这样虽然可以实现子组件向组件传值,但这种方法在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="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”>
下面的代码等同于上面的代码, 这也就是需求实现的
关键