1. 需要解决的问题
最近在vue项目中,有多个页面
需要用到同一个组件
,至于是什么组件,这里不重要,重要的这个组件需要被多个文件引用,而且有组件有一些
控制逻辑。
1.1代码展示
html
<template>
<div class="app-container">
<div slot="header" class="clearfix">
<div style="float: right;;">
<el-button type="primary" @click="bingdingClick" size="mini">绑定清单</el-button>
</div>
<el-table :data="list" style="width: 100%">
<el-table-column prop="date" label="日期" width="180">
</el-table-column>
<el-table-column prop="name" label="姓名" width="180">
</el-table-column>
<el-table-column prop="address" label="地址">
</el-table-column>
</el-table>
</div>
<el-dialog title="绑定项目清单" width="1200px" :visible.sync="bingdingDialog.dialogVisible" :close-on-click-modal="false">
<bingding ref="bingdingRef" @close="closeDialog" @reload="reloadData"></bingding>
</el-dialog>
</div>
</template>
<script>
const bingding = () => import("./bingding.vue");
export default {
name: "",
components: {
bingding
},
data() {
return {
bingdingDialog: {
dialogVisible: false,
},
list: [],
};
},
created() {
this.getList();
},
methods: {
handleResize() {
this.windowHeight = window.innerHeight;
},
getList() {
this.list = [];
},
//绑定清单
bingdingClick() {
this.bingdingDialog.dialogVisible = true;
this.$nextTick(() => {
this.$refs.bingdingRef.init(ids, 1, proIds[0], workList);
});
},
//关闭绑定弹窗
closeDialog() {
this.bingdingDialog.dialogVisible = false;
},
//绑定弹窗关闭后刷新列表
reloadData() {
this.bingdingDialog.dialogVisible = false;
this.getList();
},
}
};
</script>
1.2代码分析
上面代码里有一个 绑定清单 的组件,此组件是公用
的,有好几个功能页面都需要用上。
使用绑定 组件时 ,需要做处理以下逻辑:
- 弹窗加载
el-dialog
- 引用组件
import("./bingding.vue");
data
里面有bingdingDialog
参数bingdingClick,closeDialog,reloadData
方法的补充
上面的逻辑是每个页面 必须的,那个页面用到组件,就得补充上面的逻辑。并且这些逻辑基本上都是重复代码,复制来复制去的。
问题来了,这些逻辑不好维护 ,只要改就需要每个页面去改。
那有没有办法把这些代码都写到一个文件里面去呢。这样直接引用这个文件不就行了。接着往下看
2. 解决思路
Vue 2里面有一个 Mixin
能解决
2.1 Vue Mixin 详解
Mixin
是 Vue 中一种代码复用的方式,它允许你将组件的选项(如 data、methods、生命周期钩子等)提取到单独的文件中,然后在多个组件中复用。
是不是很契合,接着看结构
js
// myMixin.js
export default {
data() {
return {
mixinData: '来自Mixin的数据'
}
},
methods: {
mixinMethod() {
console.log('来自Mixin的方法')
}
},
created() {
console.log('Mixin的created钩子')
}
}
全局混入
js
// main.js
import Vue from 'vue'
import myMixin from './mixin.js'
Vue.mixin(myMixin) // 全局混入,会影响所有Vue实例
注意:全局混入要谨慎使用
,因为它会影响每一个 Vue 实例。
局部混入
js
import myMixin from '@/mixins/myMixin'
export default {
mixins: [myMixin],
// 组件自己的选项...
}
局部混入,就是单个页面使用
。
2.2 优化代码
将开头的代码优化后,如下
原页面:
html
<template>
<div class="app-container">
<div slot="header" class="clearfix">
<div style="float: right;;">
<el-button type="primary" @click="bingdingClick" size="mini">绑定清单</el-button>
</div>
<el-table :data="list" style="width: 100%">
<el-table-column prop="date" label="日期" width="180">
</el-table-column>
<el-table-column prop="name" label="姓名" width="180">
</el-table-column>
<el-table-column prop="address" label="地址">
</el-table-column>
</el-table>
</div>
<el-dialog title="绑定项目清单" width="1200px" :visible.sync="bingdingDialog.dialogVisible" :close-on-click-modal="false">
<bingding ref="bingdingRef" @close="closeDialog" @reload="reloadData"></bingding>
</el-dialog>
</div>
</template>
<script>
import bingdingWork from '..//bingdingWork.js';
export default {
name: "",
mixins: [bingdingWork],
components: {
bingding
},
data() {
return {
list: [],
};
},
created() {
this.getList();
},
methods: {
handleResize() {
this.windowHeight = window.innerHeight;
},
getList() {
this.list = [];
},
}
};
</script>
代码分析:
- 页面的
el-dialog
弹窗保留 import bingdingWork from '..//bingdingWork.js';
导入公共js,见下面代码mixins: [bingdingWork], Mixin
加载方法- 原有的
data
里面的参数,method
里面的加载,关闭和 方法全部都挪到公用js
里面
Mixin 公共js
js
const bingding = () => import("../bingding.vue");
export default {
components: {
bingding,
},
data() {
return {
bingdingDialog: {
dialogVisible: false,
},
type: 4
}
},
methods: {
//绑定清单
bingdingClick() {
this.bingdingDialog.dialogVisible = true;
this.$nextTick(() => {
this.$refs.bingdingRef.init(ids, this.type, proIds[0], workList);
});
},
//关闭绑定弹窗
closeDialog() {
this.bingdingDialog.dialogVisible = false;
},
//绑定弹窗关闭后刷新列表
reloadData() {
this.bingdingDialog.dialogVisible = false;
this.getList();
},
},
computed: {
mixinComputed() { /* 计算属性 */ }
},
watch: {
mixinData(newVal) { /* 侦听器 */ }
}
}
代码分析:
- 将前面的需要公用的
data,method computed
等等全部挪到js 里面 - 类似的
组件选项,生命周期钩子,计算属性,侦听器,组件
等等都可以写 <template> <style>
这样的不能写入
即到此处,基本上已经完成了 公共 mixin
的开发,哪个页面要用,直接引入,加载即可。
还有一个问题。如果每个页面的参数不一样,需要传参怎么办,继续往下
2.3 Mixin 函数接收参数
改写 Mixin 公共js
将 Mixin 改造成工厂函数
,可以接收参数
并返回定制化的 Mixin 对象
:
js
export default function createBingding(customOptions = {}) {
const bingding = () => import("../bingding.vue");
return {
components: {
bingding,
},
data() {
return {
bingdingDialog: {
dialogVisible: false,
},
type: customOptions.type
}
},
methods: {
//绑定清单
bingdingClick() {
this.bingdingDialog.dialogVisible = true;
this.$nextTick(() => {
this.$refs.bingdingRef.init(ids, this.type, proIds[0], workList);
});
},
//关闭绑定弹窗
closeDialog() {
this.bingdingDialog.dialogVisible = false;
},
//绑定弹窗关闭后刷新列表
reloadData() {
this.bingdingDialog.dialogVisible = false;
this.getList();
},
},
computed: {
mixinComputed() { /* 计算属性 */ }
},
watch: {
mixinData(newVal) { /* 侦听器 */ }
}
}
}
createBingding
为对外开放的函数
customOptions
为初始化的参数
页面优化
js
mixins: [createBingding({type: 4})],
createBingding({type: 4})
,执行方法,并且注入参数
以上即可完成参数的传输。
总结
在vue 2中,可以使用 Mixins 将控制逻辑完全封装在一个文件中,每个页面直接引入使用。减少公共代码的维护问题