vue源碼入口文件分析(推薦)
開發(fā)vue項目有段時間了, 之前用angularjs 后來用 reactjs 但是那時候一直沒有時間把自己看源碼的思考記錄下來,現(xiàn)在我不想再浪費(fèi)這 來之不易的思考, 我要堅持??!
看源碼我個人感覺非常開心,每每看上一段,自己就充實許多,不知道你是否和我一樣。
vue 源碼是眾多module(模塊)用 rollup 工具合并而成, 從package.json 中能夠看到。現(xiàn)在讓我們從github上下載vue項目,開始我們今天的“思考”。
我下載的源碼版本是:"version": "2.5.7",
源碼起始位置從這里可以看到
"dev": "rollup -w -c build/config.js --environment TARGET:web-full-dev" // 從build/config.js 中找到 TARGET: web-full-dev 這是運(yùn)行和編譯(支持現(xiàn)在的瀏覽器,由于里面大量應(yīng)用了ES6-7)后的 // Runtime+compiler development build (Browser) 'web-full-dev': { entry: resolve('web/entry-runtime-with-compiler.js'), dest: resolve('dist/vue.js'), format: 'umd', env: 'development', alias: { he: './entity-decoder' }, banner },
找到了開始文件就是 "web/entry-runtime-with-compiler.js", 然后我們一路找 Vue 對象 終于在 “instance/index.js” 中找到了:
// 這是Vue 的開始位置 function Vue (options) { // 判斷如果是不是生產(chǎn)環(huán)境,且不是通過new關(guān)鍵字來創(chuàng)建對象的話,就在控制臺打印一個warning 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) }
看似到這里都結(jié)束了,因為我們目的就是找到開始位置,但是我有個疑問,為什么Vue需要這么多層 ?
entry-runtime-with-compiler.js -> runtime/index.js -> core/index.js -> instance/index.js
當(dāng)我仔細(xì)看了源碼后恍然大悟,我們先看看他們這些文件都做了什么:
(1)instance/index.js
從Vue 模塊命名中能看出一些端倪, instance (實例) 。
這個文件是Vue 對象的開始,同時也是Vue 原型鏈(prototype) 方法的集中文件
// _init initMixin(Vue) // $set、$delete、$watch stateMixin(Vue) // $on、$once、$off、$emit eventsMixin(Vue) // _update、$forceUpdate、$destroy lifecycleMixin(Vue) // $nextTick、_render、以及多個內(nèi)部調(diào)用的方法 renderMixin(Vue)
這些方法只有實例化了才能調(diào)用。
(2)core/index.js
這個文件在Instance/index.js 創(chuàng)建和初步加工后,再次加工。 那他主要做了什么呢? 我們不考慮運(yùn)行環(huán)境
initGlobalAPI(Vue)
對,就調(diào)用了這個方法,很簡單明了吧 --- "初始化全局接口",
讓我們走進(jìn)initGlobalAPI 方法
export function initGlobalAPI (Vue: GlobalAPI) { // config const configDef = {} configDef.get = () => config // 在 非生產(chǎn)環(huán)境,如何修改了配置文件config里面的內(nèi)容會提示警告 if (process.env.NODE_ENV !== 'production') { configDef.set = () => { warn( 'Do not replace the Vue.config object, set individual fields instead.' ) } } // 定義config 屬性, 監(jiān)聽變化 Object.defineProperty(Vue, 'config', configDef) // exposed util methods. // NOTE: these are not considered part of the public API - avoid relying on // them unless you are aware of the risk. Vue.util = { warn, extend, mergeOptions, defineReactive } Vue.set = set Vue.delete = del Vue.nextTick = nextTick Vue.options = Object.create(null) // 給vue 創(chuàng)建 ASSET_TYPES 的 空對象 ASSET_TYPES.forEach(type => { Vue.options[type + 's'] = Object.create(null) }) // this is used to identify the "base" constructor to extend all plain-object // components with in Weex's multi-instance scenarios. Vue.options._base = Vue extend(Vue.options.components, builtInComponents) // Vue.use initUse(Vue) // Vue.mixin initMixin(Vue) // Vue.extend initExtend(Vue) // Vue.component, Vue.directive, Vue.filter initAssetRegisters(Vue) }
這里面基本都是 靜態(tài)方法,即:用 Vue. xxx 的形式調(diào)用。
(3)runtime/index.js
這里就加一些擴(kuò)展和 在 Vue.prototype上添加了__patch__和$mount(掛載元素)。
// Vue.options.directives(model和show)和 Vue.options.components(Transition和TransitionGroup) extend(Vue.options.directives, platformDirectives) extend(Vue.options.components, platformComponents) // install platform patch function Vue.prototype.__patch__ = inBrowser ? patch : noop // public mount method Vue.prototype.$mount = function ( el?: string | Element, hydrating?: boolean ): Component { el = el && inBrowser ? query(el) : undefined return mountComponent(this, el, hydrating) }
(4)entry-runtime-with-compiler.js
就干了一件事就是重寫$mount, Vue根據(jù)不同運(yùn)行環(huán)境,重寫不同$mount
const mount = Vue.prototype.$mount Vue.prototype.$mount = function ( el?: string | Element, hydrating?: boolean ): Component { ... return mount.call(this, el, hydrating) }
總結(jié):
到此我們找到了開始執(zhí)行的文件,和每個文件有什么用,具體怎么做的,做了什么我會下次再寫。不過我們剛開始不要太在乎每個細(xì)節(jié),不要非得弄懂每一行代碼,如果那樣,真的太累了,而且可能沒有勇氣堅持下去。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
vue element項目引入icon圖標(biāo)的方法
這篇文章主要介紹了vue element項目引入icon圖標(biāo)的方法,本文圖文并茂給大家介紹的非常詳細(xì),需要的朋友可以參考下2018-06-06Vue報錯"Failed?to?resolve?loader:less-loader"的解決方
這篇文章主要給大家介紹了關(guān)于Vue報錯"Failed?to?resolve?loader:less-loader"的解決方法,文中通過圖文介紹的非常詳細(xì),對同樣遇到這樣問題的朋友具有一定的需要的朋友可以參考下2023-02-02vue3+element?plus實現(xiàn)側(cè)邊欄過程
這篇文章主要介紹了vue3+element?plus實現(xiàn)側(cè)邊欄過程,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-03-03Vuejs第一篇之入門教程詳解(單向綁定、雙向綁定、列表渲染、響應(yīng)函數(shù))
組件(Component)是 Vue.js 最強(qiáng)大的功能之一。接下來給大家介紹vuejs單向綁定、雙向綁定、列表渲染、響應(yīng)函數(shù)的相關(guān)知識,非常不錯,感興趣的朋友一起看看吧2016-09-09使用vue3-print-nb實現(xiàn)打印pdf分頁代碼示例
這篇文章主要介紹了使用vue3-print-nb實現(xiàn)打印pdf分頁的相關(guān)資料,這種方法不僅適用于Vue3項目,也可以在其他前端框架中實現(xiàn)類似的打印分頁功能,需要的朋友可以參考下2024-10-10Vue實現(xiàn)docx/xlsx/pdf等類型文件預(yù)覽功能
這篇文章主要為大家詳細(xì)介紹了如何溧陽Vue實現(xiàn)docx/xlsx/pdf等類型文件預(yù)覽功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-02-02