Vue--双向绑定
原文网址:Vue—双向绑定_IT利刃出鞘的博客-CSDN博客
其他网址
父子组件prop值的双向绑定
简介
说明
在有些情况下,我们可能需要对一个 prop 进行“双向绑定”。不幸的是,真正的双向绑定会带来维护上的问题,因为子组件可以变更父组件,且在父组件和子组件都没有明显的变更来源。
众所周知,vue组件间的传值都是单向数据流。按官网的 单向数据流 解释:所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解。
最常见的就是在公共组件中(如计数器、单选按钮)中,子组件(计数器)把父组件传来的数字展示出来。在点击子组件的添加按钮时,因为单向数据流的原因,不能直接在子组件中给数字+1。
本文以计数器为例,说明子组件给父组件传递数据的方案。
公共代码
import Vue from 'vue'
import Router from 'vue-router'
import CompA from "@/components/CompA";
export default new Router({
routes: [
{
path: '/compA',
name: 'compA',
component: CompA
}
]
})
方案1:prop + $emit
components/CompA(父组件)
<template>
<div class="compA">
<p>CompA</p>
<p>count: {
{ count }}</p>
<hr>
<comp-b v-bind:count="count" v-on:update:count="count = $event"></comp-b>
</div>
</template>
<script>
import CompB from "@/components/CompB";
export default {
components: {CompB},
data() {
return {
count: 0,
}
},
}
</script>
<style scoped>
</style>
components/CompB(子组件)
<template>
<div class="compB">
<p>CompB</p>
<button @click="updateCount">You click me {
{count}} times</button>
</div>
</template>
<script>
export default {
props: ['count'],
methods: {
updateCount() {
this.$emit('update:count', +this.count + 1);
},
}
}
</script>
<style scoped>
</style>
测试
访问:http://localhost:8080/#/compA
未点击按钮前
每点击按钮一次,数目加1(父组件和子组件会同步显示)
方案2:v-model
其他网址
官方网址:自定义组件的-v-model
简介
自定义组件的v-model其实就是父子组件通信的语法糖而已,它等价于:value=”value(固定格式)” @input=”emitEvent(组件emit带的第一个参数)”。即:
<comp-b v-model="value"></comp-b>
<!-- 等价于下边这样写 -->
<!-- <comp-b :value="value" v-on:input="value = $event"></comp-b>-->
也就是说,此时。子组件中emit的自定义事件名需要为input。父子组件中传的值键名需要是value。
实例
components/CompA(父组件)
<template>
<div class="compA">
<p>CompA</p>
<p>count: {
{ value }}</p>
<hr>
<comp-b v-model="value"></comp-b>
<!-- 等价于下边这样写 -->
<!-- <comp-b :value="value" v-on:input="value = $event"></comp-b>-->
</div>
</template>
<script>
import CompB from "@/components/CompB";
export default {
components: {CompB},
data() {
return {
value: 0,
}
},
}
</script>
<style scoped>
</style>
components/CompB(子组件)
<template>
<div class="compB">
<p>CompB</p>
<button @click="changeCount">You click me {
{value}} times</button>
</div>
</template>
<script>
export default {
props: ['value'],
methods: {
changeCount() {
this.$emit('input', +this.value + 1);
},
}
}
</script>
<style scoped>
</style>
测试
访问:http://localhost:8080/#/compA
未点击按钮时:
每点击按钮一次,数目加1(父组件和子组件会同步显示)
注意
components/CompA中,必须用
,它生成的html如下:如果将CompA和CompB的value都替换为count,则是不成功的。如下 未点击按钮时:
点击按钮之后
方案3:v-model + model
其他网址
官方网址:model
简介
允许一个自定义组件在使用 v-model 时定制 prop 和 event。默认情况下,一个组件上的 v-model 会把 value 用作 prop 且把 input 用作 event,但是一些输入类型比如单选框和复选框按钮可能想使用 value prop 来达到不同的目的。使用 model 选项可以回避这些情况产生的冲突。
实例
components/CompA(父组件)
<template>
<div class="compA">
<p>CompA</p>
<p>count: {
{ count }}</p>
<hr>
<comp-b v-model="count"></comp-b>
</div>
</template>
<script>
import CompB from "@/components/CompB";
export default {
components: {CompB},
data() {
return {
count: 0,
}
},
}
</script>
<style scoped>
</style>
components/CompB(子组件)
<template>
<div class="compB">
<p>CompB</p>
<button @click="changeCount">You click me {
{count}} times</button>
</div>
</template>
<script>
export default {
props: ['count'],
model:{
prop: "count",
event: 'change-count'
},
methods: {
changeCount() {
this.$emit('change-count', +this.count + 1);
},
}
}
</script>
<style scoped>
</style>
测试
访问:http://localhost:8080/#/compA
未点击按钮时:
每点击按钮一次,数目加1(父组件和子组件会同步显示)
方案4:.sync 修饰符
其他网址
官方网址:.sync 修饰符
简介
同样是语法糖,具体用法直接戳进官网查看。
<comp-b v-bind:count.sync="myCount"></comp-b>
<!-- 等价于-->
<!--<comp-b
v-bind:count="myCount"
v-on:update:count="myCount=$event">
</comp-b>-->
实例
components/CompA(父组件)
<template>
<div class="compA">
<p>CompA</p>
<p>count: {
{ myCount }}</p>
<hr>
<comp-b v-bind:count.sync="myCount"></comp-b>
<!-- 等价于-->
<!--<comp-b
v-bind:count="myCount"
v-on:update:count="myCount=$event">
</comp-b>-->
</div>
</template>
<script>
import CompB from "@/components/CompB";
export default {
components: {CompB},
data() {
return {
myCount: 0,
}
},
}
</script>
<style scoped>
</style>
可以看到:此时变量名不对应子组件的props的prop名。
components/CompB(子组件)
<template>
<div class="compB">
<p>CompB</p>
<button @click="changeCount">You click me {
{count}} times</button>
</div>
</template>
<script>
export default {
props: ['count'],
methods: {
changeCount() {
this.$emit('update:count', +this.count + 1);
},
}
}
</script>
<style scoped>
</style>
测试
访问:http://localhost:8080/#/compA
未点击按钮时:
每点击按钮一次,数目加1(父组件和子组件会同步显示)
方案5:多个 prop的双向绑定
其他网址
官方网址:.sync 修饰符
简介
跟方案4相同,依然使用.sync。把 countGroup 对象中的每一个 property (如 count) 都作为一个独立的 prop 传进去,然后各自添加用于更新的 v-on 监听器。
实例
components/CompA.vue(父组件)
<template>
<div class="compA">
<p>CompA</p>
<p>count1: {
{ countGroup.count1 }}</p>
<p>count2: {
{ countGroup.count2 }}</p>
<hr>
<comp-b v-bind.sync="countGroup"></comp-b>
</div>
</template>
<script>
import CompB from "@/components/CompB";
export default {
components: {CompB},
data() {
return {
countGroup:{
count1: 0,
count2: 0
}
}
},
}
</script>
<style scoped>
</style>
components/CompB.vue(子组件)
<template>
<div class="compB">
<p>CompB</p>
<button @click="changeCount1">You click count1 {
{count1}} times</button>
<button @click="changeCount2">You click count2 {
{count2}} times</button>
</div>
</template>
<script>
export default {
props: ['count1', 'count2'],
methods: {
changeCount1() {
this.$emit('update:count1', +this.count1 + 1);
},
changeCount2() {
this.$emit('update:count2', +this.count2 + 1);
},
}
}
</script>
<style scoped>
</style>
测试
访问:http://localhost:8080/#/compA
未点击按钮时:
每点击按钮一次,数目加1(父组件和子组件会同步显示)
还没有评论,来说两句吧...