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

相关推荐
Lhuu(重开版几秒前
Vue:Ajax
vue.js·ajax·okhttp
谢尔登14 分钟前
【React】React 18 并发特性
前端·react.js·前端框架
Joker`s smile17 分钟前
使用React+ant Table 实现 表格无限循环滚动播放
前端·javascript·react.js
国家不保护废物22 分钟前
🌟 React 魔法学院入学指南:从零构建你的第一个魔法阵(项目)!
前端·react.js·架构
然我23 分钟前
从原生 JS 到 React:手把手带你开启 React 业务开发之旅
javascript·react.js·前端框架
import_random25 分钟前
[机器学习]svm支持向量机(优势在哪里)
前端
国家不保护废物26 分钟前
从刀耕火种到现代框架:DOM编程 vs Vue/React 进化史
前端·vue.js·react.js
陈随易26 分钟前
Univer v0.8.0 发布,开源免费版 Google Sheets
前端·后端·程序员
wkj00131 分钟前
QuaggaJS 配置参数详解
java·linux·服务器·javascript·quaggajs
不怎么爱学习的dan31 分钟前
实现 ECharts 多国地区可视化方案
前端