Vue — 详解mixins混入使用,应用场景

混入是vue官方文档提出的 关于vue复用性的一种方式,看了文档似懂,查找了下网上的讲解,整理下好好缕一缕这个东西

前言

当我们的项目越来越大,我们会发现组件之间可能存在很多相似的功能,你在一遍又一遍的复制粘贴相同的代码段(data,method,watch、mounted等),如果我们在每个组件中去重复定义这些属性和方法会使得项目出现代码冗余并提高了维护难度,针对这种情况官方提供了Mixins特性

一、什么是Mixins? mixins是一个js对象

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

mixins(混入),官方的描述是一种分发 Vue 组件中可复用功能的非常灵活的方式,mixins是一个js对象,它可以包含我们组件中script项中的任意功能选项,如data、components、methods 、created、computed等等。

我们只要将共用的功能以对象的方式传入 mixins选项中,当组件引用 mixins对象时所有mixins对象的选项都将被混入该组件本身的选项中来,这样就可以提高代码的重用性,使你的代码保持干净和易于维护。

image.png

放大看这张图:右边就是一个混入对象; 左边引用了混入对象

二、什么时候使用Mixins?

当我们存在多个组件中的数据或者功能很相近时,我们就可以利用mixins将公共部分提取出来,通过 mixins封装的函数,组件调用他们是不会改变函数作用域外部的。
作用: 减少data、methods、钩子的重复
🤭🤭🤭🤭
文章最后会举例应用场景~

三、如何创建Mixins?

在src目录下创建一个mixins文件夹,文件夹下新建一个myMixins.js文件。前面我们说了mixins是一个js对象,所以应该以对象的形式来定义myMixins,在对象中我们可以和vue组件一样来定义我们的data、components、methods 、created、computed等属性,并通过export导出该对象


image.png

四、如何使用Mixins?

前面在myMixins.js中输出一个混入对象,然后在需要调用的组件中引入myMixins.js文件即可


image.png

五、Mixins的特点

特点1:方法和参数在各组件中不共享,虽然组件调用了mixins并将其属性合并到自身组件中来了,但是其属性只会被当前组件所识别并不会被共享。

🤭也就是当前组件对mixins的属性的修改,其他也引用了这个mixins的组件并不会受影响。🤭

① 首先我们在混合对象myMixins.js中定义一个age字段和getAge方法

export const myMixins = {
  components:{},
  data() {
    return {
      age: 18,
    }
  },
  mounted() {
    this.getAge()
  },
  methods: {
    getAge() {
      console.log(this.age)
    }
  }
}

② 此时组件1引用了这个mixins,组件1中对num进行+1操作

// 这是组件1
import { myMixins } from "@/mixins/myMixins.js";
export default {
  mixins: [myMixins],
  data() {
    return {}
  },
  created() {
    this.age++   // 组件1的age变成了19啦
  },
}

③ 组件2不进行操作

export default {
  mixins: [myMixins],
  data() {
    return {}
  },
}

④ 我们分别切换到两个页面,查看控制台输出。会发现组件1改变了age里面的值,组件2中age值还是混合对象的初始值,并没有随着组件1的增加而改变


image.png

特点2:引入mixins后,组件会对其进行合并,将mixins中的数据和方法拓展到当前组件中来,如果当前组件也有同名称的属性或者方法,在合并的过程中会出现冲突,接下来我们详细了解Mixins合并冲突

六、Mixins合并冲突

【6.1】混入对象里的(components、methods 、computed、data)这些选项,混入组件时选项会被合并,重名冲突时优先采用组件的 🤭,组件中的键会覆盖混入对象的

① 我们在混入对象增加age属性、getAge1方法和getAge2方法

// myMixins.js
export const myMixins = {
  components:{},
  data() {
    return {
      age: 18,
    }
  },
  methods: {
    getAge1() {
      console.log("age1 from mixins =", this.age )
    },
    getAge2() {
      console.log("age2 from mixins =", this.age )
    },
  }
}

② 我们在引入了myMixins文件的组件中,增加age属性、getAge1方法和getAge3方法

// template.vue
import { myMixins } from "@/mixins/myMixins.js";
export default {
  mixins: [myMixins],
  data() {
    return {
      age: 20,
    }
  },
  mounted() {
    this.getAge1();
    this.getAge2();
    this.getAge3();
  },
  methods: {
    getAge1() {
      console.log('age1 from template =', this.age)
    },
    getAge3() {
      console.log('age3 from template =', this.age)
    },
  }
}

③ 我们会发现:
组件中的age覆盖了混合对象的age,
组件的getAge1方法覆盖了混合对象的getAge1方法


image.png

【6.2】值为函数(created、mounted)的选项,混入组件时选项会被合并调用,
🤭 混合对象里的钩子函数在组件里的钩子函数之前调用

// myMixins.js
export const myMixins = {
  components:{},
  data() {
    return {}
  },
  created() {
    console.log('xxx from mixins')
  }
}

再看看引用了mixins的组件

import { myMixins } from "@/mixins/myMixins.js";
export default {
  mixins: [myMixins],
  data() {
    return {}
  },
  created() {
    console.log('xxx from template')
  }
}

结果 mixins自己的created 比 引用了mixins的组件里的created先执行


image.png

七、全局混入

严重警告:一旦使用全局混入,它将影响每一个之后创建的 Vue 实例。
使用恰当时,这可以用来为自定义选项注入处理逻辑。

// 为自定义的选项 'myOption' 注入一个处理器。
Vue.mixin({
  created: function () {
    var myOption = this.$options.myOption
    if (myOption) {
      console.log(myOption)
    }
  }
})

new Vue({
  myOption: 'hello!'
})
// => "hello!"

不建议使用全局混入,全局注册之后会对所有组件都生效,影响比较大,项目大的情况下,建议使用局部注册

八、同时引入多个mixin对象

同时引入多个 mixins: [mixinsTest2,mixinsTest]

在使用局部注册的时候,可同时引入多个混入对象,执行顺序和引入顺序一致,此处便不再赘述了。

结论: 引入多个以后,,我们先引入的先被使用,先引用,先使用!

九、与vuex的区别

vuex:用来做状态管理的,里面定义的变量在每个组件中均可以使用和修改,在任一组件中修改此变量的值之后,其他组件中此变量的值也会随之修改。

Mixins:可以定义共用的变量,在每个组件中使用,引入组件中之后,各个变量是相互独立的,值的修改在组件中不会相互影响。

十、与公共组件的区别

组件:在父组件中引入组件,相当于在父组件中给出一片独立的空间供子组件使用,然后根据props来传值,但本质上两者是相对独立的。

Mixins:则是在引入Mixins之后,Mixins与组件中的属性和方法进行合并,相当于扩展了父组件的对象与方法,可以理解为形成了一个新的组件。

😄😄

另外,vue不建议,子组件直接修改props接收到的父组件的数据,但是,混入可以做到组件的属性或者方法覆盖混入对象的


混入的应用场景

假设我们需要在每个组件上添加name和time。在created、destroyed时,打出提示,并给出存活时间。

一共有五个组件,请问怎么做?
做法1:给每个组件添加data和created, destroyed钩子,重复5次
做法2:使用mixin减少重复。

做法1:

<template>
    <div>child1</div>
</template>
<script>
    export default{
        data(){
            return {
                name:'child1',
                time_birth:undefined,
                time_dead:undefined
            }
        },
        created(){
            this.time_birth=new Date();
            console.log(this.name+'出生了');
        },
        beforeDestroy(){
            this.time_dead=new Date();
            console.log(`${this.name}死了,共存活了${this.time_dead-this.time_birth}ms`);
        }
    }
</script>

// 依次对组件2 3 4 5 分别执行这些操作。。。

做法1小结: 代码重复太多,基本上每个组件都在复刻第一个组件的样式,这样下来,代码的维护性是十分低的。万一有一天要改需求了怎么办?又倒回去重新修改5次吗?5次并不是真正的5次,万一是10次,100次呢?很显然,这种做法并不可取。接下来来看另外一种做法。

做法2:
创建混入对象:

const myMixin = {
    data(){
            return {
                /* 每个组件的名字不同,用另外的方法赋值。即每个组件自己带上自己的名字即可。 */
                name:undefined,
                time_birth:undefined,
                time_dead:undefined
            }
        },
        created(){
            if(!this.name){
                throw new Error('need name');  // 名字是用的组件里data的name
            }
            this.time_birth=new Date();
            console.log(this.name+'出生了');
        },
        beforeDestroy(){
            this.time_dead=new Date();
            console.log(`${this.name}死了,共存活了${this.time_dead-this.time_birth}ms`);
        }
}
export default myMixin;

组件里

<template>
    <div>child1</div>
</template>
<script>
    /* 首先导入公共部分的js内容 */
    import myMixin from './Mixins/public.js';
    export default{
        data(){
            return {
                /* 其他组件就写自己组件的名字即可 */
                name:'child1',
            }
        },
        /* 使用导入的public模块 */
        mixins:[myMixin],
    }
</script>

用了混入后,组件只需要引用混入对象,然后在data里填写组件的名字,再挂载一下混入对象,就好了。

今天就聊到这里,后续有想到栗子再补充吧 🤭
🤭

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容