这是我参与11月更文挑战的第29天,活动详情查看:2021最后一次更文挑战
问题
由于业务需求,今天把饿了么的弹窗封装成组件,供别的页面调用,三下五除二就封装好了,文档写的很详细,功能也正常,点击取消按钮可以正常关闭弹框。但是点击弹框空白的地方关闭弹框时突然看到控制台报错:
经常写vue的同学,就应该知道这个问题。这个是因为vue的单向数据流,数据从父组件传向子组件,子组件不能修改从父组件传的数据,只能通过父组件去修改。 如果你在子组件修改,就会报这个错。
下面我通过代码模拟一下
父组件
<template>
<div>
<el-button @click="showFn">show</el-button>
<Dialog v-model="dialogVisible"></Dialog>
</div>
</template>
<script>
import Dialog from './components/Dialog.vue'
export default {
name: "App",
components: {
Dialog
},
data () {
return {
dialogVisible: false
}
},
methods: {
showFn () {
this.dialogVisible = true
}
}
};
</script>
Dialog组件:
<template>
<el-dialog
title="我是dialog头部"
:visible.sync="value"
>
<div>我是dialog内容</div>
<span slot="footer">
<el-button @click="close()">取消</el-button>
</span>
</el-dialog>
</template>
<script>
export default {
name: 'Dialog',
props: {
value: {
type: Boolean,
required: true
}
},
methods: {
close () {
this.$emit('input', false)
}
}
}
</script>
v-model
我是通过v-model来控制Dialog的显示的。
这个v-model是结合prop为value和input事件的语法糖,传入prop为value的值,如果value需要改变的时候,触发input事件,同时把改变的值当作参数传回。
sync修饰符
在Dialog组件里面,我把prop传入的value又传给el-dialog组件,这里使用了.sync修饰符。
我讲讲.sync修饰符,其实它跟v-model类似,它是 绑定值 和 @update:绑定值的语法糖。
绑定值加上sync修饰符,传入子组件,然后在子组件中需要改变绑定值时,通过触发@update:绑定值事件,然后把改变的值传给父组件,这样子达到单向数据流的目的。
问题分析
说说我遇到的这个报错问题,点击取消按钮可以正常关闭弹框。但是点击弹框空白的地方关闭弹框时控制台却报错。
这个是因为在el-dialog组件上使用了.sync修饰符,弹框关闭的时候同时把value的值改变了,而这个是在字组件里改变,所以导致了报错。
那为什么点击取消按钮可以正常关闭弹框? 因为它是通过事件触发通知父组件来修改,所以不会报错。
解决问题
那该怎么解决呢?
我们也参照取消按钮通过事件触发的方式,前面我们说了,sync修饰符也是有事件触发的,我这里不用语法糖,而是使用事件触发,使用是@update:visible
elemnetUI的dialog组件部分源码:
修改后的代码:
<el-dialog
title="我是dialog头部"
:visible="value"
@update:visible="close"
>
<div>我是dialog内容</div>
<span slot="footer">
<el-button @click="close()">取消</el-button>
</span>
</el-dialog>
运行,没有报错了。