vue中的混合mixin的使用细致讲解(以分页功能为例)__Vue.js
发布于 3 年前 作者 banyungong 1174 次浏览 来自 分享
粉丝福利 : 关注VUE中文社区公众号,回复视频领取粉丝福利

highlight: a11y-dark

什么是混合mixin

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

less预处理器混合mixin的用法步骤参见我之前的文章: https://juejin.cn/post/6956826951541587982/

官方是如何定义混合mixin的

文档是这样定义的

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

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

大白话翻译

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

    混入功能很叼

  • 来分发 Vue 组件中的可复用功能。

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

  • 一个混入对象可以包含任意组件选项。

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

  • 当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项

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

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

先看一下最终的效果图

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

第一步,新建好项目

  • 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文件并暴露)

snipaste_20210505_213709.png

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

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

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

  • 引入混合并注册使用
    <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>

打印结果如下:

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

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

  • 首先,不要重复

    混合中定义的代码就不要与组件中的代码一样

  • 其次,以组件中的为准

    简而言之,组件中没有的,混合中有,就把混合的拿过来;组件中有的,混合中也有,就不要混合中的,只保留组件中的

补充三 (全局混入,慎用)

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

总结

mixin VS vuex

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

版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 作者: 水冗水孚 原文链接:https://juejin.im/post/6958813201207148580

回到顶部