因为业务需要,最近不写 iOS,也不写 Ruby 了,开始写钱端。然后…做为一个钱端 P0,表示用了 Electron 和饿了么大钱端的 Element 库之后,好像一直都很顺利,直到…我碰到了组件间值同步的问题😫。
需求是这样的,我需要点击一个按钮,然后打开一个对话框用来新建一些东西。 对话框的话我当然是用 el-dialog
来做啊,Element!So easy!!!el-dialog
有个叫 :visible.sync
的属性,用来控制它的显示和隐藏。
如果我不封装这个对话框,直接放在当前页面,像下面这样设置就 OK 了:
<template>
<el-dialog :visible.sync="visible"></el-dialog>
</template>
<script>
export default {
data () {
return {
visible: false
}
}
}
</script>
这样一来我只需要设置 visible
的值就可以控制 el-dialog
节点 的显示和隐藏了:
<el-button @click="visible = true"></el-button>
不过本人是个封装控😂,el-dialog
里面还有一堆东西呢,直接放在这不能忍,所以我很干脆的把这个 el-dialog
和它的数据放到另外一个组件(PS:子组件)去了,然后,问题就来了:我的按钮还在当前组件里(PS:父组件),上面这行代码我控制不了这个 visible
属性了。What the Fuck!!!我需要学习,然后各种查,问,试,期间曲折的过程我就不说了,直接放最终我个人觉得比较能接受的版本吧:
首先我们先定义子组件:
<template>
<el-dialog :visible.sync="visible"></el-dialog>
</template>
<script>
export default {
props: {
pvisible: Boolean
},
computed: {
visible: {
// getter
get: function () {
return this.pvisible
},
// setter
set: function (newValue) {
this.$emit('update:pvisible', newValue)
}
}
}
}
</script>
这里有几个关键点:
- 父组件会有一个值和子组件的
pvisible
绑定,然后通过props
传递过来,而且需要指定类型,不指定的话默认是字符串类型。 - 需要一个
computed
的属性visible
来控制el-dialog
的显示和隐藏,为什么是computed
?原因有两个:-
get
方法可以直接获取pvisible
的值并控制el-dialog
的显示和隐藏。 -
要避免直接操作
props
里面pvisible
的值,如果直接操作,就会报下面的 warning: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: "pvisible"
这是时候
set
方法就可以通过emit
方法修改父组件里的那个值,然后因为父组件里的那个值和子组件的pvisible
是绑定的,从而pvisible
也会发生变化,这样就避免了上面的问题。
-
emit
方法第一个参数中的update:
是固定的,不能瞎写,这个和 vue 2.3.x 以后的新增特性有关。另外pvisible
是父组件中那个值的名字。
然后是父组件:
<template>
<child-components v-bind:pvisible.sync="pvisible"></child-components>
</template>
<script>
import ChildComponents from './ChildComponents'
export default {
data () {
return {
pvisible: false
}
},
components: { ChildComponents }
}
</script>
这里同样有几个关键点:
- 需要一个
pvisible
属性来绑定子组件里props
中pvisible
。 v-bind:pvisible.sync="pvisible"
就是刚才说的 vue 2.3.x 以后的新特性,绑定属性的同时,接收子组件emit
消息更新。
现在我们就可以在父组件通过设置 pvisible
为 true
来显示对话框,然后在子组件中通过设置 visible
为 false
来隐藏对话框了。而且他们的状态只存储在父组件的 pvisible
中,两边改变的也都是 pvisible
的值,这样就达到了数据统一,并通过数据的改变驱动页面变化的效果。
Emmm,这也是为什么我的文章标题是伪双向绑定了,因为其实改的值都是一个,绑定是单向的,不过因为一些语法糖,然后看起来像是双向绑定了 pvisible
和 visible
这两个值。
最后,我的理解很有可能是错的,所以还请各位钱端大佬多多指正!!!感谢🙏