两种的实现原理
两种传值都是通过属性和自定义事件来封装的
比如:当我们子组件实现购物车增减,父组件中的总价也随之改变
使用属性和自定义事件来双向绑定
//App.vue父组件中
<template>
<div v-cloak class="App">
<!-- 向子组件传递数据,并给子组件绑定自定义事件,等待子组件触发-->
<box1 @myadd="add" @myreduce="reduce" v-for="(item, i) in goods" :key="item.id" :pro="item" :index="i"></box1>
<p>共计{{goods|fn}}元</p>
</div>
</template>
<script>
import box1 from "./components/box1.vue"
export default {
data() {
return {
goods:[{id:1,title:'鱼香肉丝',price:21,count:1}, { id: 2, title: '回锅肉', price: 28 , count: 2}, { id: 3, title: '酸菜鱼', price: 30, count: 3}],
}
},
methods: {
<!-- 自定义事件处理函数-->
add(index){
this.goods[index].count++
},
reduce(index){
if (this.goods[index].count>0){
this.goods[index].count--
}
},
},
//使用过滤器来计算总价
filters:{
fn(arr){
let count=null
arr.forEach(el => {
count+=el.price*el.count
});
return count
}
},
components:{
box1,
}
}
</script>
//子组件box1.vue中
<template>
<!-- 接受父组件的数据,并给每个商品绑定加减按钮-->
<p><span>{{pro.title}}----{{pro.price}}</span><button @click="reduce">-</button><span>{{pro.count}}</span><button @click="add()">+</button></p>
</template>
<script>
export default {
props:['pro','index'],
methods: {
<!-- 点击按钮触发自定义事件-->
add(){
this.$emit("myadd", this.index)
},
reduce(){
this.$emit("myreduce",this.index)
}
},
}
</script>
sync实现双向绑定
对于 @myadd=“add” @myreduce=“reduce” vue 提供了一个语法糖,将其替换成 :mydata.sysnc=“item.count”;而且也不用再父组件中再去写触发函数了,这样是不是看起来简洁多了。
那么就变成了:
// 父组件
//App.vue父组件中
<div v-cloak class="App">
<box1 :mydata.sync="item.count" v-for="(item, i) in goods" :key="item.id" :pro="item" :index="i"></box1>
<p>共计{{goods|fn}}元</p>
</div>
</template>
<script>
import box1 from "./components/box1.vue"
export default {
data() {
return {
goods:[{id:1,title:'鱼香肉丝',price:21,count:1}, { id: 2, title: '回锅肉', price: 28 , count: 2}, { id: 3, title: '酸菜鱼', price: 30, count: 3}],
}
},
//使用过滤器来计算总价
filters:{
fn(arr){
let count=null
arr.forEach(el => {
count+=el.price*el.count
});
return count
}
},
components:{
box1,
}
}
</script>
//子组件box1.vue中
<template>
<p><span>{{pro.title}}----{{pro.price}}</span><button @click="reduce">-</button><span>{{pro.count}}</span><button @click="add()">+</button></p>
</template>
<script>
export default {
props:['pro','index'],
methods: {
add(){
this.$emit("update:mydata", this.pro.count+1)
},
reduce(){
if (this.pro.count > 0){
this.$emit("update:mydata", this.pro.count-1)
}
}
},
}
</script>
v-model实现双向绑定
通过v-model指令进行双向数据绑定:
1.视图发生改变→对应的数据发生改变:用户在输入框里输入的内容会被message变量接下来,改变了app.message的值。
2.被改变的app.message同时也将动态更新在p标签的内容里。
此时我们只需将上面代码变更两处
//父组件App.vue中
<box1 v-model="item.count" v-for="(item, i) in goods" :key="item.id" :pro="item" :index="i"></box1>
//子组件box1.vue中
methods: {
add(){
this.$emit("input", this.pro.count+1)
},
reduce(){
if (this.pro.count > 0){
this.$emit("input", this.pro.count-1)
} } },