什么是混合mixin

首先,谈到混合mixin这个词,并不是只有vue中才有混合的概念。其实在css的预处理器less或者stylus或者scss中也有类似的混合函数mixin的概念。只不过css预处理器中的混合是用来实现样式的复用的。而vue中的混合mixin是用来实现功能的复用的。

less预处理器混合mixin的用法步骤参见我之前的文章: https://segmentfault.com/a/11...

官方是如何定义混合mixin的

文档是这样定义的

混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。

咋一看,说的不太接地气,那我们来用大白话翻译一下吧

大白话翻译

  • 混入 (mixin) 提供了一种非常灵活的方式

    混入功能很叼
  • 来分发 Vue 组件中的可复用功能

    使用混入可以实现在.vue组件中的重复使用的功能。想想有哪些重复使用的功能呢?比如做后台管理系统常常需要使用的分页功能、比如项目中很多的地方都要使用的弹出Message消息提示功能。其实有很多,本文就以分页功能应用场景举例说明
  • 一个混入对象可以包含任意组件选项

    混合是个对象?哇,传说中的面向对象OOP的思想,混合更有点继承的味道吧。混合包含任意组件选项?组件选项不就是data、computed、watch、methods 以及各种生命周期钩子吗,也就是说混合中也可以像组件中那样定义这些组件选项,以供‘混入’使用
  • 当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项

    在vue中使用一个‘东西’,一般的套路大致都是 定义 --> 引入 --> 注册 --> 使用。既然在某个.vue中使用混合,那么引入了以后,就相当于拥有混合中的东西了。

实际使用步骤(分页组件使用混合)

先看一下最终的效果图

假设我们的项目中有两个路由页面都用到了分页组件,分页一般搭配表格,为了方便简洁,这里的话,我们就不放表格了。我们要用mixin实现这样的分页效果

第一步,新建好项目

  • App.vue文件放置对应路由导航和视图结构

    // App.vue文件
    <template>
    <div id="app">
     <div class="top">
       <router-link to="/">路由页面一</router-link>
       <router-link to="/about">路由页面二</router-link>
     </div>
     <div class="bottom">
       <router-view></router-view>
     </div>
    </div>
    </template>
  • 路由中这样定义一下

    import Vue from 'vue'
    import VueRouter from 'vue-router'
    Vue.use(VueRouter)
    
    const router = new VueRouter({
     routes: [
         {
             path: "/",
             component: resolve => require(['../views/home.vue'], resolve),
         },
         {
             path: "/about",
             component: resolve => require(['../views/about.vue'], resolve),
         },
     ]
    })
    export default router
  • home.vue和about.vue使用饿了么UI的分页组件(about.vue文件就不放置了,结构基本上一样的)

    <template>
    <div>
     <div class="block">
       <span class="demonstration">第11111个分页中使用混合</span>
       <el-pagination
         @size-change="handleSizeChange"
         @current-change="handleCurrentChange"
         :page-sizes="[10, 20, 30, 40]"
         :current-page="paging.pageIndex"
         :page-size="paging.pageSize"
         :total="paging.total"
         layout="total, sizes, prev, pager, next, jumper"
         background
       >
       </el-pagination>
     </div>
    </div>
    </template>
    
    <script>
    export default {
    name: "home",
    data() {
     return {
       paging: {
         pageIndex: 1,
         pageSize: 10,
         total: 100,
       },
     };
    },
    methods: {
     handleSizeChange(val) {
       this.paging.pageIndex = 1;
       this.paging.pageSize = val;
     },
     handleCurrentChange(val) {
       this.paging.pageIndex = val;
     },
    },
    };
    </script>

    这样的话,两个路由页面的分页效果都有了。只不过还没用到mixin。这个案例中因为home.vue和about.vue文件中都有分页功能,而使用分页功能就要定义 第几页pageIndex、每页显示几条pageSize、总条数total、翻页改变的方法handleCurrentChange、和条数改变的方法handleSizeChange这些变量和方法。这些变量和方法就属于公共的复用的代码,因为可能好多地方都要用到,我们可以把这些复用的放置在混合文件中,哪里需要使用,哪里就混入进来即可。

第二步(定义一个mixin文件并暴露)

第三步(引入混合注册并使用混合)

  • 首先把原本写好的data中的分页变量和methods中的分页方法删除掉

    当然删掉了会报错,因为分页组件需要这些变量和方法,所以接下来我们使用混合进来的变量和方法
  • 引入混合并注册使用

    <template>
    <div>
     <div class="block">
       <span class="demonstration">第11111个分页中使用混合</span>
       <el-pagination
         @size-change="handleSizeChange"
         @current-change="handleCurrentChange"
         :page-sizes="[10, 20, 30, 40]"
         :current-page="paging.pageIndex"
         :page-size="paging.pageSize"
         :total="paging.total"
         layout="total, sizes, prev, pager, next, jumper"
         background
       >
       </el-pagination>
     </div>
    </div>
    </template>
    <script>
    // 引入混合
    import mixin from '../mixin/index'
    export default {
    name: "home",
    mixins: [mixin] // 注册即使用
    };
    </script>
    另外一个about.vue文件也如法炮制即可,就能实现想要的功能了。篇幅有限不赘述

补充一(查看具体引入的混合)

其实也可以换个角度理解,就是混合是把混合文件中定义的变量方法之类的挂载到某个具体的.vue文件上,也就是挂载到某个具体的vue示例上,所以我们打印这个vue示例,是可以看到挂载进来的mixin代码的,如下:

<script>
import mixin from '../mixin/index' // 引入混合
export default {
  name: "home",
  mixins: [mixin], // 注册即使用
  mounted() {
    console.log('打印vue示例this,查看混合',this);// 看这里、看这里、看这里
  },
};
</script>

打印结果如下:

很显然,混合中的变量和方法已经被挂载到这个vue组件实例上了,既然挂载到这个示例上了,也就意味着,在template中的html代码里面可以使用了,所以使用混合的确可以使得我们写代码变得更加优雅

补充二(mixin代码与组件代码冲突了怎么办)

  • 首先,不要重复
    混合中定义的代码就不要与组件中的代码一样
  • 其次,以组件中的为准
    简而言之,组件中没有的,混合中有,就把混合的拿过来;组件中有的,混合中也有,就不要混 合中的,只保留组件中的

补充三 (全局混入,一般不要去使用)

上述代码案例我们使用的是局部的mixin,其实也挺方便,哪里需要使用,就哪里去引入混合。使用全局混合虽然省去了,引入注册的这一步,但是全局混合中定义的变量和方法,在每个组件上都会挂载上去,这样的话也不太好。毕竟官方也提醒我们,使用全局混入一定要格外小心

总结

mixin VS vuex

使用vuex也可以管理状态,和混合的区别就是vuex中的数据一但改变,所有的相关的依赖vuex中的都会改变,但是使用mixin,不过出现这样的情况。毕竟vuex是公用的,mixin是独立的


水冗水孚
1.1k 声望585 粉丝

每一个不曾起舞的日子,都是对生命的辜负