Vue 中 使用 Mixins 解决 多页面共用相同组件的相关问题

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 将控制逻辑完全封装在一个文件中,每个页面直接引入使用。减少公共代码的维护问题

相关推荐
前端风云志20 分钟前
TypeScript结构化类型初探
javascript
musk121236 分钟前
electron 打包太大 试试 tauri , tauri 安装打包demo
前端·electron·tauri
翻滚吧键盘1 小时前
js代码09
开发语言·javascript·ecmascript
万少2 小时前
第五款 HarmonyOS 上架作品 奇趣故事匣 来了
前端·harmonyos·客户端
OpenGL2 小时前
Android targetSdkVersion升级至35(Android15)相关问题
前端
rzl022 小时前
java web5(黑马)
java·开发语言·前端
Amy.Wang2 小时前
前端如何实现电子签名
前端·javascript·html5
海天胜景2 小时前
vue3 el-table 行筛选 设置为单选
javascript·vue.js·elementui
今天又在摸鱼2 小时前
Vue3-组件化-Vue核心思想之一
前端·javascript·vue.js
蓝婷儿2 小时前
每天一个前端小知识 Day 21 - 浏览器兼容性与 Polyfill 策略
前端