vue之mixin理解和使用

vue之mixin理解和使用

Posted by SkioFox on February 10, 2018

vue之mixin理解与使用=>共享组件之间共同的js逻辑

使用Mixin。Vue 中的Mixin对编写函数式风格的代码很有用,因为函数式编程就是通过减少移动的部分让代码更好理解(引自 Michael Feathers )。Mixin允许你封装一块在应用的其他组件中都可以使用的函数。

  1. 我们有一对不同的组件,它们的作用是通过切换状态(Boolean类型)来展示或者隐藏模态框或提示框。这些提示框和模态框除了功能相似以外,没有其他共同点:它们看起来不一样,用法不一样,但是逻辑一样。
    // 模态框
       const Modal = {
         template: '#modal',
         data() {
           return {
             isShowing: false
           }
         },
         methods: {
           toggleShow() {
             this.isShowing = !this.isShowing;
           }
         },
         components: {
           appChild: Child
         }
       }
    
       // 提示框
       const Tooltip = {
         template: '#tooltip',
         data() {
           return {
             isShowing: false
           }
         },
         methods: {
           toggleShow() {
             this.isShowing = !this.isShowing;
           }
         },
         components: {
           appChild: Child
         }
       }
    
  2. 我们可以在这里提取逻辑并创建可以被重用的项
  • 抽取逻辑
const toggle = {
      data() {
        return {
          isShowing: false
        }
      },
      methods: {
        toggleShow() {
          this.isShowing = !this.isShowing;
        }
      }
    }

    const Modal = {
      template: '#modal',
      mixins: [toggle],
      components: {
        appChild: Child
      }
    };

    const Tooltip = {
      template: '#tooltip',
      mixins: [toggle],
      components: {
        appChild: Child
      }
    };
  • 使用
// 建立mixin
// mixin/toggle.js
export default toggle={
    data(){
        return {
            isShowing:false
        }
    },
    methods: {
        toggleShow() {
            this.isShowing = ! this.isShowing
        }
    }
}

// 组件中引用
import Child from './Child'
import { toggle } from './mixins/toggle'

export default {
    name: 'modal',
    mixins: [toggle],
    components: {
        appChild: Child
    }
}
// 即便我们使用的是一个对象而不是一个组件,生命周期函数对我们来说仍然是可用的,理解这点很重要。我们也可以这里使用mounted()钩子函数,它将被应用于组件的生命周期上。
  1. 在下面的这个例子,我们可以看到,我们不仅仅是实现了自己想要的功能,并且Mixin中的生命周期的钩子也同样是可用的。
  • 当我们在组件上应用Mixin的时候,有可能组件与Mixin中都定义了相同的生命周期钩子,这时候钩子的执行顺序的问题凸显了出来。默认Mixin上会首先被注册,组件上的接着注册,这样我们就可以在组件中按需要重写Mixin中的语句。组件拥有最终发言权。
//mixin
  const hi = {
    mounted() {
      console.log('hello from mixin!')
    }
  }

  //vue instance or component
  new Vue({
    el: '#app',
    mixins: [hi],
    mounted() {
      console.log('hello from Vue instance!')
    }
  });

  //Output in console
  > hello from mixin!
  > hello from Vue instance!
  • 如果这两个冲突了,我们看看 Vue实例或组件是如何决定输赢的:
    //mixin
       const hi = {
         methods: {
           sayHello: function() {
             console.log('hello from mixin!')
           }
         },
         mounted() {
           this.sayHello()
         }
       }
    
       //vue instance or component
       new Vue({
         el: '#app',
         mixins: [hi],
         methods: {
           sayHello: function() {
             console.log('hello from Vue instance!')
           }
         },
         mounted() {
           this.sayHello()
         }
       })
    
       // Output in console
       > hello from Vue instance!
       > hello from Vue instance!
    
  • 混入methods, components 和 directives(自定义指令)时,将被混合为同一个对象。两个对象键名冲突时,取组件对象的键值对。

      methods: {
          foo: function () {
            console.log('foo')
          },
          conflicting: function () {
            console.log('from mixin')
          }
        }
      }
    
      var vm = new Vue({
        mixins: [mixin],
        methods: {
          bar: function () {
            console.log('bar')
          },
          conflicting: function () {
            console.log('from self')
          }
        }
      })
    
      vm.foo() // => "foo"
      vm.bar() // => "bar"
      vm.conflicting() // => "from self"