vue中使用mixins/extends傳入參數的方式

使用mixins/extends傳入參數

最近做報表頁面,基本都是列表頁面,所以想用mixins。

但是接口的url不同,於是考慮怎麼才能傳入參數去適配各個頁面。

後來發現mixin文件可以寫個函數,接受傳遞過來的參數,然後return一個對象。

大概如下:

mixin.js

export default function(config) {
    let {
        listUrl="",
        exportUrl=""
    } = config;
    return {
        created() {
            console.log(listUrl);
            console.log(exportUrl);
        }
    }
}

xxx.vue

import Mixin from './mixin';
let mixin = new Mixin({
    listUrl: "www.baidu.com",
    exportUrl: "www.yahu.com"
})
 
export default{
    mixins:[mixin],
}

extends也是差不多。 

vue mixins的原理

以前一直以為mixins在vue裡面應該不是很重要,隻是提供瞭一個混入的api,慢慢的才知道mixin在vue裡面非常重要。生命周期、vuex等都有mixin的影子,在內部算是很重要的一個api。

先上精簡過後的源碼:

export const LIFECYCLE_HOOKS = [
    'beforeCreate',
    'created',
    'beforeMount',
    'mounted',
    'beforeUpdate',
    'updated',
    'beforeDestroy',
    'destroyed',
]
const strats = {};
function mergeHook(parentVal, childValue) {
    if (childValue) {
        if (parentVal) {
            return parentVal.concat(childValue);
        } else {
            return [childValue]
        }
    } else {
        return parentVal;
    }
}
LIFECYCLE_HOOKS.forEach(hook => {
    strats[hook] = mergeHook
})

上面這部分很好理解,是生命周期的合並,下面判斷有這些生命周期的key的時候,直接調用strats[key](parent[key], child[key]),我們都知道生命周期的mixins是先執行mixins的再執行當前組件的,所以直接concat,後面執行循環調用的時候就是這個順序。

export function mergeOptions(parent, child) {
    const options = {}
    if (child.mixins) {
        for (var i = 0, l = child.mixins.length; i < l; i++) {
            var mixin = child.mixins[i];
            parent = mergeOptions(parent, mixin);
        }
    }
    for (let key in parent) {
        mergeField(key)
    }
    for (let key in child) {
        if (!parent.hasOwnProperty(key)) {
            mergeField(key);
        }
    }
    function mergeField(key) {
        if (strats[key]) {
            options[key] = strats[key](parent[key], child[key]);
        } else {
            if (typeof parent[key] == 'object' && typeof child[key] == 'object') {
                options[key] = {
                    ...parent[key],
                    ...child[key]
                }
            }else{
                options[key] = child[key];
            }
        }
    }
    return options
}

這邊生命周期是單獨判斷,其他熟悉方法則是一起的,比如方法methods,如果父和子都有,就結構合並在一起。因為mixins用法可以傳入一個數組,這邊還需要優先判斷是否有mixins字段,有就要遞歸合並。

核心有瞭其他都是調用瞭,比如把mixin方法掛載到vue上可以直接調用:

Vue.mixin = function (mixin) {
    // 將屬性合並到Vue.options上
    this.options = mergeOptions(this.options,mixin);
    return this;
}

初始化的時候先合並一次,生命周期也是,在狀態初始化之前先調用beforeCreate,初始化之後調用created,源碼搜索Vue.prototype._init這個方法裡面就能看見,包括其他生命周期,可以搜索callhook去看看:

vm.$options = mergeOptions(vm.constructor.options,options);
callHook(vm,'beforeCreate');

// 初始化狀態

initState(vm);
callHook(vm,'created');

callHook就是循環調用生命周期:

export function callHook(vm, hook) {
    const handlers = vm.$options[hook];
    if (handlers) {
        for (let i = 0; i < handlers.length; i++) {
            handlers[i].call(vm);
        }
    }
}

mixin方法核心就是合並實例的屬性,watch、methods、data等,也可以新增一開始沒有的屬性,比如vuex的$store。 

以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。

推薦閱讀: