Mixins
Mixins是一種分發Vue組件中可複用功能的非常靈活的一種方式。
什麼時候使用Mixins
1. 頁面的風格不用,但是執行的方法和需要的數據類似,我們是選擇每個都寫呢還是提取出公共部分呢?
基礎實例
我們有一對不同的組件,它們的作用是切換一個狀態布爾值,一個模態框和一個提示框。這些提示框和模態框除了在功能上,沒有其他共同點:它們看起來不一樣,用法不一樣,但是邏輯一樣。
// 模態框 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 } }
解決辦法如下:
const toggle = { data () { isshowing: false }, methods: { toggleShow() { this.isshowing = !this.isshowing } } } // 下面即可使用了 // mixins: [變量名] const Modal = { template: '#modal', mixins: [toggle], components: { appChild: Child } }; const Tooltip = { template: '#tooltip', mixins: [toggle], components: { appChild: Child } };
如果你是以vue-cli創建的項目來寫,可以這樣
// mixin.js export const toggle = { data () { isshowing: false }, methods: { toggleShow() { this.isshowing = !this.isshowing } } }
// modal.vue // 將mixin引入該組件,就可以直接使用 toggleShow() 了 import {mixin} from '../mixin.js' export default { mixins: [mixin], mounted () { } } // tooltip組件同上
合併
當組件和混入對象含有同名選項時,這些選項將以恰當的方式混合。
一、數據對象內
mixin的數據對象和組件的數據發生衝突時以組件數據優先。
var mixin = { data: function () { return { message: 'hello', foo: 'abc' } } } new Vue({ mixins: [mixin], data: function () { return { message: 'goodbye', bar: 'def' } }, created: function () { console.log(this.$data) // => { message: "goodbye", foo: "abc", bar: "def" } } })
二、鉤子函數
同名鉤子函數將會混合爲一個數組,都將被調用到,但是混入對象的鉤子將在組件自身鉤子之前調用。
var mixin = { created: function () { console.log('混入對象的鉤子被調用') } } new Vue({ mixins: [mixin], created: function () { console.log('組件鉤子被調用') } }) // => "混入對象的鉤子被調用" // => "組件鉤子被調用"
三、值爲對象的選項
值爲對象的選項,例如 methods
, components
和 directives
,將被混合爲同一個對象。兩個對象鍵名衝突時,取組件對象的鍵值對。
var mixin = { 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"
全局混入
全局混合被註冊到了每個單一組件上。因此,它們的使用場景極其有限並且要非常的小心。一個我能想到的用途就是它像一個插件,你需要賦予它訪問所有東西的權限。但即使在這種情況下,我也對你正在做的保持警惕,尤其是你在應用中擴展的函數,可能對你來說是不可知的。
Vue.mixin({ mounted() { console.log("我是mixin"); } }) new Vue({ ... })
再次提醒,小心使用它!那個 console.log將會出現在每個組件上。這種情況還不算壞(除了控制檯上有多餘的輸出),但如果它被錯誤的使用,你將能看到它會多麼的有害。
一個使用合理的例子
// 爲自定義的選項 'myOption' 注入一個處理器。 Vue.mixin({ created: function () { var myOption = this.$options.myOption if (myOption) { console.log(myOption) } } }) new Vue({ myOption: 'hello!' }) // => "hello!"
總結
混合對於封裝一小段想要複用的代碼來講是有用的。對你來說它們當然不是唯一可行的。混合很好,它不需要傳遞狀態,但是這種模式當然也可能會被濫用。所以我們還是需要仔細斟酌使用嘍!!
例子
import {mapGetters} from 'vuex' // 目的是想要處理 scroll 的bottom值,在含有playlist列表的情況下 export const playlistMixin = { computed: { ...mapGetters([ 'playList' ]) }, mounted() { this.handlePlaylist(this.playList) }, activated() { this.handlePlaylist(this.playList) }, watch: { playlist(newVal) { this.handlePlaylist(newVal) } }, methods: { // 如果組件中沒有這個方法,那麼就報錯 handlePlaylist() { throw new Error('component must implement handlePlaylist method') } } }