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

相关推荐
徐同保14 分钟前
通过AzureOpenAI请求gpt-4.1-mini
前端
红尘散仙25 分钟前
四、WebGPU 基础入门——Uniform 缓冲区与内存对齐
前端·rust·gpu
进取星辰36 分钟前
13、性能优化:魔法的流畅之道——React 19 memo/lazy
前端·react.js·前端框架
zwjapple42 分钟前
React中createPortal 的详细用法
前端·javascript·react.js
小矮马43 分钟前
React-组件通信
前端·javascript·react.js
codingandsleeping1 小时前
pnpm + monorepo:高效的项目管理方式
前端
程序员三千_1 小时前
最近爆火的MCP到底是什么?
前端
古时的风筝1 小时前
暴论:2025年,程序员必学技能就是MCP
前端·后端·mcp
古时的风筝1 小时前
这编程圈子变化太快了,谁能告诉我 MCP 是什么
前端·后端·mcp
王月lydia1 小时前
环境变量篇-vue3的H5项目从0到1工程化落地经验篇2
前端