🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] >[success] # Mixin 混入的基础语法 这章讲解一下 **vue** 中相关的一些 **复用性代码** 该怎么去写,首先介绍一下 **mixin 混入** , **mixin 混入: 就是把某一些内容混入到哪里去** 。 >[success] ## 局部混入 如下代码,定义了一个 **myMixin** 混入,并且 **混入的代码中** 同样有一个名称为 **number** 的 **变量** , **index.html** ~~~ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Mixin 混入的基础语法</title> <!-- 通过cdn方式引入vue --> <script src="https://unpkg.com/vue@next"></script> </head> <body> <div id="root"></div> </body> <script> // 1. 定义mixin 混入 // 组件 data 优先级高于mixin data 优先级 const myMixin = { data(){ return { number: 2, count: 222 } } } const app = Vue.createApp({ data(){ return { number: 1 } }, mixins: [myMixin], // 2. 引入混入 methods: { handleClick(){ console.log('handleClick') } }, template: ` <div> <div>{{number}}</div> <div>{{count}}</div> <button @click="handleClick">增加</button> </div>` }) const vm = app.mount('#root') </script> </html> ~~~ 如果 **混入的变量与文件中的变量名相同** 的情况下, 使用文件自己的 **number** 变量,如果文件中没有 **number** 这个变量,就会使用 **混入的代码中的 number 变量** ,代码如下: ~~~ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Mixin 混入的基础语法</title> <!-- 通过cdn方式引入vue --> <script src="https://unpkg.com/vue@next"></script> </head> <body> <div id="root"></div> </body> <script> // 1. 定义mixin 混入 // 组件 data 优先级高于mixin data 优先级 const myMixin = { data(){ return { number: 2, count: 222 } } } const app = Vue.createApp({ data(){ return { // number: 1 } }, mixins: [myMixin], // 2. 引入混入 methods: { handleClick(){ console.log('handleClick') } }, template: ` <div> <div>{{number}}</div> <div>{{count}}</div> <button @click="handleClick">增加</button> </div>` }) const vm = app.mount('#root') </script> </html> ~~~ **生命周期** 也是可以 **混入** 的,那么如果 **组件代码中与混入代码中** 都有 **created** 会怎么样呢,代码如下: ~~~ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Mixin 混入的基础语法</title> <!-- 通过cdn方式引入vue --> <script src="https://unpkg.com/vue@next"></script> </head> <body> <div id="root"></div> </body> <script> // 1. 定义mixin 混入 // 组件 data, methods 优先级高于mixin data, methods 优先级 // 生命周期函数,先执行 mixin 里面的,再执行组件里面的 const myMixin = { data(){ return { number: 2, count: 222 } }, created(){ console.log('我是混入的created') }, methods: { handleClick(){ console.log('mixin handleClick') } } } const app = Vue.createApp({ data(){ return { number: 1 } }, created(){ console.log('我是自己的created') }, mixins: [myMixin], // 2. 引入混入 methods: { handleClick(){ console.log('handleClick') } }, template: ` <div> <div>{{number}}</div> <div>{{count}}</div> <button @click="handleClick">增加</button> </div>` }) const vm = app.mount('#root') </script> </html> ~~~ **生命周期函数** ,会先执行 **mixin** 里面的,再执行 **组件** 里面的 。 >[success] ## 全局混入 假如有这样一个场景:**A组件** 中引入了 **mixin混入代码** ,并且 **A组件** 中引入了 **B组件** ,在这个时候如果 **B组件** 想使用 **A组件** 引入的 **mixin混入代码** , **可以直接使用吗? 答案是不可以的** 。如果也想使用 **mixin混入的代码**, 必须也要在 **B组件** 内引入 **mixin混入代码** 才能使用,这就跟 **vue** 的 **局部组件** 一个道理,那么 **如何引入一次混入,任何组件都可以使用** 呢,接下来讲解一下 **全局混入** 的使用方法。 **index.html** ~~~ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Mixin 混入的基础语法</title> <!-- 通过cdn方式引入vue --> <script src="https://unpkg.com/vue@next"></script> </head> <body> <div id="root"></div> </body> <script> // 组件 data, methods 优先级高于mixin data, methods 优先级 // 生命周期函数,先执行 mixin 里面的,再执行组件里面的 const app = Vue.createApp({ data(){ return { number: 1 } }, created(){ console.log('我是自己的created') }, methods: { handleClick(){ console.log('handleClick') } }, template: ` <div> <div>{{number}}</div> <child /> <button @click="handleClick">增加</button> </div>` }) // 创建全局mixin app.mixin({ data(){ return { number: 2, count: 222 } }, created(){ console.log('我是混入的created') }, methods: { handleClick(){ console.log('mixin handleClick') } } }) // 创建子组件 app.component('child', { template: "<div>{{count}}</div>" }) const vm = app.mount('#root') </script> </html> ~~~ >[success] ## 自定义属性与mixin 下面代码中的 **number** 属性,这种在 **实例里** 或者 **组件里** 面定义的内容,实际上是一个 **自定义属性** ,既不在 **data** 里,也不在 **methods** 里,又不在 **计算属性** 里,又不在 **各种各样(例如:watch等等...)** 的方法里,直接 **定义在组件的最外层这样的一个属性** ,这种内容,我们把它叫做 **自定义属性** 。 **this.$options** 指的是 当前的 **vue应用** 或 **组件**,所有的内容,在**vue** 做处理之后,都会把它挂到 **this.$options** 里面来,直接 **this.number** 是获取不到的,用 **this.$options.number** 这种方式才可以获取到。 **index.html** ~~~ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Mixin 混入的基础语法</title> <!-- 通过cdn方式引入vue --> <script src="https://unpkg.com/vue@next"></script> </head> <body> <div id="root"></div> </body> <script> // 组件 data, methods 优先级高于mixin data, methods 优先级 // 生命周期函数,先执行 mixin 里面的,再执行组件里面的 const myMixin = { number: 1 } const app = Vue.createApp({ mixins: [myMixin], number: 2, template: ` <div> <div>{{this.$options.number}}</div> </div>` }) const vm = app.mount('#root') </script> </html> ~~~ **组件的 自定义属性 优先级高于 mixin 自定义属性 优先级** >[success] ### 自定义属性优先级修改 虽然上面说到了 **组件的 自定义属性 优先级高于 mixin 自定义属性 优先级** ,但是**vue** 是 **支持修改自定义属性优先级** 的,代码如下: **index.html** ~~~ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Mixin 混入的基础语法</title> <!-- 通过cdn方式引入vue --> <script src="https://unpkg.com/vue@next"></script> </head> <body> <div id="root"></div> </body> <script> // 组件 data, methods 优先级高于mixin data, methods 优先级 // 生命周期函数,先执行 mixin 里面的,再执行组件里面的 const myMixin = { number: 1 } const app = Vue.createApp({ mixins: [myMixin], number: 2, template: ` <div> <div>{{this.$options.number}}</div> </div>` }) // 对自定义属性number的合并策略做修改, app.config.optionMergeStrategies.number = (mixinVal, appVal) => { return mixinVal || appVal // mixinVal 有就用 mixinVal,否则用appVal } const vm = app.mount('#root') </script> </html> ~~~ >[success] ## 总结 1. **组件 的 data, methods 优先级高于mixin data, methods 优先级** 2. **生命周期函数,先执行 mixin 里面的,再执行组件里面的** 3. **组件的 自定义属性 优先级高于 mixin 自定义属性 优先级**