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

相关推荐
三十_A1 分钟前
零基础通过 Vue 3 实现前端视频录制 —— 从原理到实战
前端·vue.js·音视频
前端小菜袅1 分钟前
PC端原样显示移动端页面方案
开发语言·前端·javascript·postcss·px-to-viewport·移动端适配pc端
Highcharts.js3 分钟前
如何使用Highcharts SVG渲染器?
开发语言·javascript·python·svg·highcharts·渲染器
We་ct3 分钟前
LeetCode 228. 汇总区间:解题思路+代码详解
前端·算法·leetcode·typescript
爱问问题的小李18 分钟前
ue 动态 Key 导致组件无限重置与 API 重复提交
前端·javascript·vue.js
码云数智-大飞22 分钟前
从回调地狱到Promise:JavaScript异步编程的演进之路
开发语言·javascript·ecmascript
m0_7482299924 分钟前
PHP+Vue打造实时聊天室
开发语言·vue.js·php
子兮曰26 分钟前
深入Vue 3响应式系统:为什么嵌套对象修改后界面不更新?
前端·javascript·vue.js
CHU72903529 分钟前
直播商城APP前端功能全景解析:打造沉浸式互动购物新体验
java·前端·小程序
枫叶丹430 分钟前
【Qt开发】Qt界面优化(一)-> Qt样式表(QSS) 背景介绍
开发语言·前端·qt·系统架构