众所周知,vue 是单向数据流,所以子组件中不能直接修改 props
里的父组件传过来的属性。可有时候我们可能需要对一个 prop 进行“双向绑定”——换言之,要在子组件中更新从父组件中传过来的变量。
这就需要用到 .sync
修饰符 + $emit(update:xxx)
的组合语法。
举个栗子:(该案例中用到了 Vant 第三方 ui 库)
// 父组件中调用子组建
<Child :isShow.sync='isShow'/>
// 子组件中
<template lang="pug">
van-popup.popup-menu(
v-model="currentShow"
round
position="bottom"
:style="{ height: '70%' }"
)
.header 用户选单
.main
//-
</template>
<script>
export default {
props: {
isShow: {
type: Boolean,
default: false
}
},
computed: {
currentShow: {
get () {
return this.isShow
},
set (newValue) {
this.$emit('update:isShow', newValue)
}
}
}
}
上面这种写法,采用 computed 来实现,完全代替了 watch 的方案。若是用 watch 需要像下面这样:
// 父组件中
<Child :isShow='isShow'/>
// 子组件中
export default {
props: {
isShow: {
type: Boolean,
default: false
}
},
data () {
return {
currentShow: false
}
},
watch: {
isShow (newVal) {
if (newVal) {
this.currentShow = true
} else {
this.currentShow = false
}
}
}
}
但是在开发的过程中,要尽量少的使用 watch,所以最佳实现方案是 “.sync
修饰符 + $emit(update:xxx)
的组合语法”。
【注意】
若是直接使用 props 里的属性,回报错:
Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop’s value. Prop being mutated:XXX
如果只使用$emit(update:xxx)
而没有在父组件调用子组件的地方使用.sync
修饰符时,应该也会报错
【参考文档】
vue 的 .sync 修饰符