深入淺析Vue中mixin和extend的區(qū)別和使用場景
Vue中有兩個較為高級的靜態(tài)方法mixin和extend,接下來我們來討論下關于他們各自的原理和使用場景。
Mixin:
原理:
先來看看官網(wǎng)的介紹:
參數(shù):{Object} mixin
用法:
混入也可以進行全局注冊。使用時格外小心!一旦使用全局混入,它將影響每一個之后創(chuàng)建的 Vue 實例。使用恰當時,這可以用來為自定義選項注入處理邏輯。
// 為自定義的選項 'myOption' 注入一個處理器。 Vue.mixin({ created: function () { var myOption = this.$options.myOption if (myOption) { console.log(myOption) } } }) new Vue({ myOption: 'hello!' }) // => "hello!"
我們知道,Vue.mixin傳遞的這個參數(shù)對象,在初始化Vue實例的時候會merge到options上,下面是Vue源碼中對mixin的操作。
// src\core\global-api\mixin.js export function initMixin (Vue: GlobalAPI) { Vue.mixin = function (mixin: Object) { this.options = mergeOptions(this.options, mixin) return this } } // src\core\instance\index.js function Vue (options) { if (process.env.NODE_ENV !== 'production' && !(this instanceof Vue) ) { warn('Vue is a constructor and should be called with the `new` keyword') } this._init(options) } initMixin(Vue) ... export default Vue
也就是說,mixin只是對我們在初始化Vue實例時傳遞的配置對象的一個擴展。
就像上面官網(wǎng)實例寫的例子,我們在執(zhí)行Vue.mixin方法時傳遞一個配置對象進去,對象里面有個created勾子函數(shù),通過源碼我們可以看到這個傳遞進來的對象最終會和我們在初始化實例也就是new Vue(options)
時的這個options合并(通過上面源碼中的mergeOptions方法),保存在option上。
使用場景:
當我們需要全局去注入一些methods,filter或者hooks時我們就可以使用mixin來做。 比如我們希望每一個Vue實例都有一個print方法,我們就可以這么做:
Vue.mixin({ methods: { print() { console.log(`我是一個通過mixin注入的方法!`) } } })
或者我們想要去監(jiān)聽在什么階段時什么組件被加載了,被卸載了等等,我們可以這么做:
Vue.mixin({ mounted() { console.log(`${this.$route.name} component mounted!`) }, destroyed() { console.log(`${this.$route.name} component destroyed!`) } })
如果我們并不想給每一個組件實例都混入這些配置options,而只是個別的組件,最好不要使用mixin,它可能會影響到我們組件的性能。
Extend:
原理:
先來看看官網(wǎng)的介紹:
參數(shù):{Object} options
用法:
使用基礎 Vue 構造器,創(chuàng)建一個“子類”。參數(shù)是一個包含組件選項的對象。
data 選項是特例,需要注意 - 在 Vue.extend()
中它必須是函數(shù)。
data必須是函數(shù)是為了防止各個實例的數(shù)據(jù)混亂,閉包的應用。
<div id="mount-point"></div> // 創(chuàng)建構造器 var Profile = Vue.extend({ template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>', data: function () { return { firstName: 'Walter', lastName: 'White', alias: 'Heisenberg' } } }) // 創(chuàng)建 Profile 實例,并掛載到一個元素上。 new Profile().$mount('#mount-point')
再來看看源碼里面關于Vue.extend的實現(xiàn):
Vue.extend = function (extendOptions: Object): Function { extendOptions = extendOptions || {} const Super = this const SuperId = Super.cid const cachedCtors = extendOptions._Ctor || (extendOptions._Ctor = {}) if (cachedCtors[SuperId]) { return cachedCtors[SuperId] } const name = extendOptions.name || Super.options.name if (process.env.NODE_ENV !== 'production' && name) { validateComponentName(name) } const Sub = function VueComponent (options) { this._init(options) } Sub.prototype = Object.create(Super.prototype) Sub.prototype.constructor = Sub Sub.cid = cid++ Sub.options = mergeOptions( Super.options, extendOptions ) Sub['super'] = Super // For props and computed properties, we define the proxy getters on // the Vue instances at extension time, on the extended prototype. This // avoids Object.defineProperty calls for each instance created. if (Sub.options.props) { initProps(Sub) } if (Sub.options.computed) { initComputed(Sub) } // allow further extension/mixin/plugin usage Sub.extend = Super.extend Sub.mixin = Super.mixin Sub.use = Super.use // create asset registers, so extended classes // can have their private assets too. ASSET_TYPES.forEach(function (type) { Sub[type] = Super[type] }) // enable recursive self-lookup if (name) { Sub.options.components[name] = Sub } // keep a reference to the super options at extension time. // later at instantiation we can check if Super's options have // been updated. Sub.superOptions = Super.options Sub.extendOptions = extendOptions Sub.sealedOptions = extend({}, Sub.options) // cache constructor cachedCtors[SuperId] = Sub return Sub } }
首先我們可以看到,extend方法返回的Sub其實是一個構造函數(shù),而且繼承自Vue,也就是說extend方法返回的是Vue的一個子類。
Sub.prototype = Object.create(Super.prototype) Sub.prototype.constructor = Sub
這兩行代碼其實就是實現(xiàn)Sub對Vue的繼承,源碼中有一行是
const Super = this
所以這里的Super指的就是Vue。
Sub.options = mergeOptions( Super.options, extendOptions )
我們注意到在extend中也會對傳進來的配置option和Vue原來的options做一個合并。
使用場景:
當我們不需要全局去混入一些配置,比如,我們想要獲得一個component。我們可以使用Vue.component(),
也可以使用Vue.extend()。
const ChildVue = Vue.extend({ ...options }) new ChildVue({ ...options })
注意extend得到的是一個Vue的子類,也就是構造函數(shù)。
區(qū)別:
mixin是對Vue類的options進行混入。所有Vue的實例對象都會具備混入進來的配置行為。
extend是產(chǎn)生一個繼承自Vue類的子類,只會影響這個子類的實例對象,不會對Vue類本身以及Vue類的實例對象產(chǎn)生影響。
總結
以上所述是小編給大家介紹的Vue中mixin和extend的區(qū)別和使用場景,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
如果你覺得本文對你有幫助,歡迎轉載,煩請注明出處,謝謝!
相關文章
vue路由事件beforeRouteLeave及組件內定時器的清除方法
今天小編就為大家分享一篇vue路由事件beforeRouteLeave及組件內定時器的清除方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-09-09一文詳細聊聊vue3的defineProps、defineEmits和defineExpose
vue3官方文檔defineProps和defineEmits都是只能在scriptsetup中使用的編譯器宏,下面這篇文章主要給大家介紹了關于vue3的defineProps、defineEmits和defineExpose的相關資料,需要的朋友可以參考下2023-02-02對vue v-if v-else-if v-else 的簡單使用詳解
今天小編就為大家分享一篇對vue v-if v-else-if v-else 的簡單使用詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-09-09詳解Vue基于 Nuxt.js 實現(xiàn)服務端渲染(SSR)
直接使用 Vue 構建前端單頁面應用,頁面源碼時只有簡單的幾行 html,這并不利于網(wǎng)站的 SEO,這時候就需要服務端渲染,本篇文章主要介紹了詳解Vue基于 Nuxt.js 實現(xiàn)服務端渲染(SSR),具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-04-04element組件中自定義組件的樣式不生效問題(vue scoped scss無效)
這篇文章主要介紹了解決element組件中自定義組件的樣式不生效問題(vue scoped scss無效),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09