我们专注成都网站设计 成都网站制作 成都网站建设
成都网站建设公司服务热线:028-86922220

网站建设知识

十年网站开发经验 + 多家企业客户 + 靠谱的建站团队

量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决

在Vue.js中使用Mixin

有一种很常见的情况:有两个非常相似的组件,他们的基本功能是一样的,但他们之间又存在着足够的差异性,此时的你就像是来到了一个分岔路口:我是把它拆分成两个不同的组件呢?还是保留为一个组件,然后通过props传值来创造差异性从而进行区分呢?

创新互联专注于康马企业网站建设,响应式网站,成都商城网站开发。康马网站建设公司,为康马等地区提供建站服务。全流程按需策划设计,专业设计,全程项目跟踪,创新互联专业和态度为您提供的服务

两种解决方案都不够***:如果拆分成两个组件,你就不得不冒着一旦功能变动就要在两个文件中更新代码的风险,这违背了 DRY 原则。反之,太多的props传值会很快变得混乱不堪,从而迫使维护者(即便这个人是你)在使用组件的时候必须理解一大段的上下文,拖慢写码速度。

使用Mixin。Vue 中的Mixin对编写函数式风格的代码很有用,因为函数式编程就是通过减少移动的部分让代码更好理解(引自 Michael Feathers )。Mixin允许你封装一块在应用的其他组件中都可以使用的函数。如果使用姿势得当,他们不会改变函数作用域外部的任何东西,因此哪怕执行多次,只要是同样的输入你总是能得到一样的值,真的很强大!

基础实例

我们有一对不同的组件,它们的作用是通过切换状态(Boolean类型)来展示或者隐藏模态框或提示框。这些提示框和模态框除了功能相似以外,没有其他共同点:它们看起来不一样,用法不一样,但是逻辑一样。

 
 
 
 
  1. // 模态框 
  2.  
  3. const Modal = { 
  4.  
  5.   template: '#modal', 
  6.  
  7.   data() { 
  8.  
  9.     return { 
  10.  
  11.       isShowing: false 
  12.  
  13.     } 
  14.  
  15.   }, 
  16.  
  17.   methods: { 
  18.  
  19.     toggleShow() { 
  20.  
  21.       this.isShowing = !this.isShowing; 
  22.  
  23.     } 
  24.  
  25.   }, 
  26.  
  27.   components: { 
  28.  
  29.     appChild: Child 
  30.  
  31.   } 
  32.  
  33. } 
  34.  
  35.   
  36.  
  37. // 提示框 
  38.  
  39. const Tooltip = { 
  40.  
  41.   template: '#tooltip', 
  42.  
  43.   data() { 
  44.  
  45.     return { 
  46.  
  47.       isShowing: false 
  48.  
  49.     } 
  50.  
  51.   }, 
  52.  
  53.   methods: { 
  54.  
  55.     toggleShow() { 
  56.  
  57.       this.isShowing = !this.isShowing; 
  58.  
  59.     } 
  60.  
  61.   }, 
  62.  
  63.   components: { 
  64.  
  65.     appChild: Child 
  66.  
  67.   } 
  68.  
  69. }  

我们可以在这里提取逻辑并创建可以被重用的项:

 
 
 
 
  1. const toggle = { 
  2.  
  3.   data() { 
  4.  
  5.     return { 
  6.  
  7.       isShowing: false 
  8.  
  9.     } 
  10.  
  11.   }, 
  12.  
  13.   methods: { 
  14.  
  15.     toggleShow() { 
  16.  
  17.       this.isShowing = !this.isShowing; 
  18.  
  19.     } 
  20.  
  21.   } 
  22.  
  23. } 
  24.  
  25.   
  26.  
  27. const Modal = { 
  28.  
  29.   template: '#modal', 
  30.  
  31.   mixins: [toggle], 
  32.  
  33.   components: { 
  34.  
  35.     appChild: Child 
  36.  
  37.   } 
  38.  
  39. }; 
  40.  
  41.   
  42.  
  43. const Tooltip = { 
  44.  
  45.   template: '#tooltip', 
  46.  
  47.   mixins: [toggle], 
  48.  
  49.   components: { 
  50.  
  51.     appChild: Child 
  52.  
  53.   } 
  54.  
  55. };  

你可以点击这里,查看 Sarah Drasner(@sdras) 在CodePen上编写 Mixin 的例子

为了更容易理解Mixin,这个例子故意编写得简单一些。真实应用中Mixin有如下的应用,但是它的作用也不仅限于此:获取视窗和组件的尺寸,采集特定的鼠标事件和图表的基本元素。Paul Pflugradt 有一个关于 Vue Mixins 的优秀项目,值得一提的是它是用 coffeescript 编写的。

用法

上面这个codepen的例子并没有告诉我们在一个真实的应用中如何使用Mixin,所以我们看看下面的这个。

你可以按照你喜欢的任意方式设置你的目录结构,但为了结构规整我喜欢新建一个mixin目录。我们创建的这个文件含有.js扩展名(跟.vue相对,就像我们的其他文件),为了使用Mixin我们需要输出一个对象。

接着我们可以在Modal.vue使用这样的写法,来引入这个Mixin:

 
 
 
 
  1. import Child from './Child' 
  2.  
  3. import { toggle } from './mixins/toggle' 
  4.  
  5.   
  6.  
  7. export default { 
  8.  
  9.   name: 'modal', 
  10.  
  11.   mixins: [toggle], 
  12.  
  13.   components: { 
  14.  
  15.     appChild: Child 
  16.  
  17.   } 
  18.  
  19. }  

即便我们使用的是一个对象而不是一个组件,生命周期函数对我们来说仍然是可用的,理解这点很重要。我们也可以这里使用mounted()钩子函数,它将被应用于组件的生命周期上。这种工作方式真的很灵活也很强大。

合并

在下面的这个例子,我们可以看到,我们不仅仅是实现了自己想要的功能,并且Mixin中的生命周期的钩子也同样是可用的。因此,当我们在组件上应用Mixin的时候,有可能组件与Mixin中都定义了相同的生命周期钩子,这时候钩子的执行顺序的问题凸显了出来。默认Mixin上会首先被注册,组件上的接着注册,这样我们就可以在组件中按需要重写Mixin中的语句。组件拥有最终发言权。当发生冲突并且这个组件就不得不“决定”哪个胜出的时候,这一点就显得特别重要,否则,所有的东西都被放在一个数组当中执行,Mixin将要被先推入数组,其次才是组件。

 
 
 
 
  1. //mixin 
  2.  
  3. const hi = { 
  4.  
  5.   mounted() { 
  6.  
  7.     console.log('hello from mixin!') 
  8.  
  9.   } 
  10.  
  11. } 
  12.  
  13.   
  14.  
  15. //vue instance or component 
  16.  
  17. new Vue({ 
  18.  
  19.   el: '#app', 
  20.  
  21.   mixins: [hi], 
  22.  
  23.   mounted() { 
  24.  
  25.     console.log('hello from Vue instance!') 
  26.  
  27.   } 
  28.  
  29. }); 
  30.  
  31.   
  32.  
  33. //Output in console 
  34.  
  35. > hello from mixin! 
  36.  
  37. > hello from Vue instance!  

如果这两个冲突了,我们看看 Vue实例或组件是如何决定输赢的:

 
 
 
 
  1. //mixin 
  2.  
  3. const hi = { 
  4.  
  5.   methods: { 
  6.  
  7.     sayHello: function() { 
  8.  
  9.       console.log('hello from mixin!') 
  10.  
  11.     } 
  12.  
  13.   }, 
  14.  
  15.   mounted() { 
  16.  
  17.     this.sayHello() 
  18.  
  19.   } 
  20.  
  21. } 
  22.  
  23.   
  24.  
  25. //vue instance or component 
  26.  
  27. new Vue({ 
  28.  
  29.   el: '#app', 
  30.  
  31.   mixins: [hi], 
  32.  
  33.   methods: { 
  34.  
  35.     sayHello: function() { 
  36.  
  37.       console.log('hello from Vue instance!') 
  38.  
  39.     } 
  40.  
  41.   }, 
  42.  
  43.   mounted() { 
  44.  
  45.     this.sayHello() 
  46.  
  47.   } 
  48.  
  49. }) 
  50.  
  51.   
  52.  
  53. // Output in console 
  54.  
  55. > hello from Vue instance! 
  56.  
  57. > hello from Vue instance!  

你可能已经注意到这有两个console.log而不是一个——这是因为***个函数被调用时,没有被销毁,它只是被重写了。我们在这里调用了两次sayHello()函数。

全局Mixin

当我们使用“全局”来描述Mixin的时候,我们并不是说Mixin能够像filter,在每个组件都能被访问到。只是我们能够在组件通过mixins:[toggle]访问组件上的Mixin对象。

全局Mixin被注册到了每个单一组件上。因此,它们的使用场景极其有限并且在使用的时候我们需要非常小心。一个我能想到的用途就是类似于插件,你需要赋予它访问所有东西的权限。但即使在这种情况下,我也对你正在做事情的充满警惕,尤其当你打算为应用增加通能的时候,这样做可能对你来说是个潘多拉的盒子。

为了创建一个全局实例,我们可以把它放在Vue实例之上。在一个典型的 Vue-cli 初始化的项目中,它可能在你的main.js文件中。

 
 
 
 
  1. Vue.mixin({ 
  2.  
  3.   mounted() { 
  4.  
  5.     console.log('hello from mixin!') 
  6.  
  7.   } 
  8.  
  9. }) 
  10.  
  11.   
  12.  
  13. new Vue({ 
  14.  
  15.   ... 
  16.  
  17. })  

再次提醒,小心使用它!那个console.log将会出现在每个组件上,在这个案例里还不算坏(除了控制台上有多余的输出)。但如果全局Mixin被错误的使用,你将能看到它有多可怕。

结论

Mixin对于封装一小段想要复用的代码来讲是有用的。对你来说Mixin当然不是唯一可行的选择:比如说高阶组件就允许你组合相似函数,Mixin只是的一种实现方式。我喜欢Mixin,因为我不需要传递状态,但是这种模式当然也可能会被滥用,所以,仔细思考下哪种选择对你的应用最有意义吧! 


文章名称:在Vue.js中使用Mixin
转载源于:http://www.swkodf.com/article/djjgcss.html

其他资讯