在vue项目中,一个vue单文件里往往有多个弹框(以elementUI为了,那就是el-dialog
组件),杂乱而繁多,在这里尝试以一种简化的方式来处理。
-
为了方便说明,以一个简单例子进行说明,要实现下图效果,点击“打开弹窗”,在弹窗中点击“Add”,可以增加selectNumber,点击“关闭”按钮,可以关闭按钮:
- 原有代码如下:
// vue单文件页面
<template>
<div>
<el-button @click="visible=true">打开弹窗</el-button>
selectNumber:{{selectNumber}}
<el-dialog
:visible.sync="visible"
:show-close="false"
title="我是题目"
width="400px"
@close="closeDialog('hehe')">
{{selectNumber}}
<el-button @click="handleClick">Add</el-button>
<el-button @click="handleClose">关闭</el-button>
</el-dialog>
</div>
</template>
<script>
export default {
data() {
return {
selectNumber: 0,
visible: false
}
}
methods: {
handleClick() {
this.selectNumber +=1
},
closeDialog() {
this.visible = false
this.$message({ type: 'success', message: '关闭' })
}
}
}
</script>
- 当一个功能页面(假如对应一个vue但未见)中交互复杂,存在多个
el-dialog
组件,然后每一个里面有或多或少的逻辑的话,那么代码行数会明显增加,我们往往采取下面几种方式来优化代码结构:
通过MessageBox方式来处理逻辑较简单的弹窗效果,见官方示例MessageBox 弹框
通过mixin的方式组织代码使结构更清晰简洁,但是这种无法使
template
部分更为简洁将弹框封装成组件,将弹框中的业务逻辑封装进组件,接着前例,改造如下:
// vue单文件页面
<template>
<div>
<el-button @click="visible=true">打开弹窗</el-button>
selectNumber:{{selectNumber}}
<test-dialog
:visible.sync="visible"
:show-close="false"
title="我是题目"
width="400px"
:selectNumber.sync="selectNumber"
@close="closeDialog('hehe')">
</test-dialog>
</div>
</template>
<script>
import testDialog from './testDialog.js'
export default {
data() {
return {
selectNumber: 0,
visible: false
}
},
components: {
testDialog
},
methods: {
closeDialog() {
this.visible = false
this.$message({ type: 'success', message: '关闭' })
}
}
}
</script>
// test-dialog组件:
export default {
name: 'testDialog',
template: `
<el-dialog v-bind="$attrs" :visible.sync="visible" v-on="$listeners">
{{selectNumber}}
{{this.$attrs}}
<el-button @click="handleClick">Add</el-button>
<el-button @click="handleClose">关闭</el-button>
</el-dialog>
`,
props: {
visible: false
},
data() {
return {
...this.$attrs
}
},
watch: {
visible: {
handler() {
Object.keys(this.$attrs).forEach(attr => {
this[attr] = this.$attrs[attr]
})
},
deep: true,
immediate: true,
}
},
methods: {
handleClick() {
this.selectNumber += 1
this.tableData.push(this.selectNumber)
},
handleClose() {
this.$emit('update:visible', false)
this.$emit('update:selectNumber', this.selectNumber)
this.$emit('update:tableData', this.tableData)
}
},
created() {
// console.log('this.$attrs ', this, this.$attrs, new Date().valueOf())
}
}
test-dialog
组件主要用到了$attrs
和$listeners
来达到透传的效果,通过.sync
使得数据能更新到父组件中。从效果上来看,既达到了js的拆分,又实现了模板的拆分,同时部分变量(sync修饰的)达到了父子组件共享的效果。