最近在使用element-ui的dialog组件二次封装成独立组件使用时,子组件须要将关闭dialog状态返回给父组件,简单的说就是要实现父子组件之间的数据双向绑定问题。html
大体代码以下:vue
1,父组件vuex
<template> <button @click="openDialog">打开弹窗</button> <dialogCompenent :show="result" :result="result" @dialogData="closeDialog"></dialogCompenent> </template> <script type="text/babel"> import dialogCompenent from '/dialogCompenent' export default { data () { return { result: false } }, components: { dialogCompenent }, methods: { openDialog () { this.result = true }, closeDialog (data) { this.result = data } } } </script>
2,子组件 childCompenentelement-ui
<template> <el-dialog title="弹框组件" :visible.sync="result" @open="doOpen" @close="doClose" :show="result" size="tiny"> <div class="content-wrapper"> 具体业务代码... </div> </el-dialog> </div> </template> <script type="text/babel"> import videoApi from '../../api/videoApi/videoApi' export default { name: 'dialogCompenent', props: { result: Boolean }, methods: { doOpen () { ... }, doClose () { this.$emit('dialogData', false) ... } } } </script>
程序在浏览器上虽然可以正常运行,可是在vue2.0却会报错:api
[Vue warn]: 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: "result" (found in component )
组件内不能修改props的值,同时修改的值也不会同步到组件外层,即调用组件方不知道组件内部当前的状态是什么浏览器
这是什么缘由形成的呢?缓存
在vue1.x版本中利用props的twoWay和.sync绑定修饰符就能够实现props的双向数据绑定。babel
在vue2.0中移除了组件的props的双向数据绑定功能,若是须要双向绑定须要本身来实现。
在vue2.0中组件的props的数据流动改成了只能单向流动,即只能由(父组件)经过组件的v-bind:attributes传递给(子组件),子组件只能被动接收父组件传递过来的数据,并在子组件内不能修改由父组件传递过来的props数据。app
官方文档解释:ide
prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,可是不会反过来。这是为了防止子组件无心修改了父组件的状态——这会让应用的数据流难以理解。
虽然废弃了props的双向绑定对于整个项目总体而言是有利且正确的,可是在某些时候咱们确实须要从组件内部修改props的需求
在Vue2.0中,实现组件属性的双向绑定方式
子组件修改:
<template> <el-dialog title="弹框组件" :visible.sync="openStatus" @open="doOpen" @close="doClose" :show="openStatus" size="tiny"> <div class="content-wrapper"> 具体业务代码... </div> </el-dialog> </div> </template> <script type="text/babel"> import videoApi from '../../api/videoApi/videoApi' export default { name: 'dialogCompenent', props: { result: Boolean }, /*建立一个openStatus变量缓存result数据 *在子组件须要调用result的地方调用data对象openStatus */ data () { return { openStatus: this.result } }, //新增result的watch,监听变动同步到openStatus //监听父组件对props属性result的修改,并同步到组件内的data属性 watch: { result (val) { this.openStatus = val } }, methods: { doOpen () { ... }, doClose () { this.$emit('dialogData', false)//子组件对openStatus修改后向父组件发送事件通知 ... } } } </script>
父组件修改:
<template> <button @click="openDialog">打开弹窗</button> <dialogCompenent :show="result" :result="result" @dialogData="closeDialog"></dialogCompenent> </template> <script type="text/babel"> import dialogCompenent from '/dialogCompenent' export default { data () { return { result: false } }, components: { dialogCompenent }, methods: { openDialog () { this.result = true }, closeDialog (data) { this.result = data//子组件触发父组件事件,进行数据变动,同步result数据 } } } </script>
至此,实现了子组件内数据与父组件的数据的双向绑定,组件内外数据的同步。最后归结为一句话就是:组件内部本身变了告诉外部,外部决定要不要变。
结语
那么为何vue1.0还有的数据双向绑定在vue2.0版本中反而抛弃了呢,经过上述案例咱们也能够发现双向绑定的props代码多,不利于组件间的数据状态管理,尤为是在复杂的业务中更是如此,因此尽可能不使用这种方式的双向绑定,过于复杂的数据处理使用vuex来进行数据管理。(https://vuex.vuejs.org/zh-cn/...)