來源于慕課網(wǎng)慈格,本文章只做總結(jié)怠晴。另:本人水平有限。大神忽略浴捆!
拿到源碼后如何開始閱讀
個人感覺此部分不是很重要蒜田,但還是總結(jié)一下。
這個其實可以通過npm scripts的命令來尋找到选泻。因為vue的代碼最后也會被打包編譯冲粤。打開package.json文件便可看到以下命令,打包的scripts腳本有很多页眯,大多數(shù)都是編譯到不同平臺運行的腳本文件(比如weex或ssr相關(guān))梯捕。這里關(guān)注npm run build
即可
"build": "node scripts/build.js"
我們可以根據(jù)腳本的提示找到scripts/build.js
打開文件后可以看到如下的代碼,以及一些相關(guān)配置窝撵,主要是針對路徑的處理和一些roolup
的配置傀顾。根據(jù)代碼提示可以找到config.js
let builds = require('./config').getAllBuilds()
其實這個config
文件大致只做了三件事情
1.resolve函數(shù),用來獲取不同文件的路徑碌奉,然后做一些處理(大約在28行)
2.builds常量的定義的編譯類型對象短曾,是一個map集合(大約在38行)。執(zhí)行編譯命令的時候會根據(jù)不同的npm scripts
選擇不同的類型赐劣。這里我們可以關(guān)注一下Runtime+compiler
的那個版本嫉拐。代碼如下。
'web-full-esm': {
entry: resolve('web/entry-runtime-with-compiler.js'),
dest: resolve('dist/vue.esm.js'),
format: 'es',
alias: { he: './entity-decoder' },
banner
},
entry
定義的就是代碼的打包入口魁兼。vue的源碼也是正式的從這個文件開始的entry-runtime-with-compiler.js
婉徘。
dist
打包后的代碼,dist/vue.esm.js
這個文件大家要關(guān)注一下璃赡。后期會通過vue-cli生成一個項目判哥,代碼調(diào)試基本都是在這個文件中進行。
-
genConfig
函數(shù)碉考,是rollup的打包配置。沒有關(guān)注太多挺身。
4.平時開發(fā)使用的都是runtime-only
的代碼侯谁。以上的文件是runtime-compiler
的版本,其實二者的區(qū)別在于runtime-only
會借助vue-loader
將template模板章钾,render函數(shù)等渲染好然后瀏覽器直接執(zhí)行js腳本墙贱,但是runtime-compiler
的版本是在執(zhí)行過程中編譯。其實在后期很多地方也是通過相同的函數(shù)實現(xiàn)贱傀,所以沒有必要糾結(jié)到底要分析哪一種版本惨撇。
找到vue的主體代碼
找vue代碼的時候會遇見很多不同的函數(shù),其實不必太在意「現(xiàn)在我們只管一門心思找到vue的主體代碼即可
根據(jù)下面代碼的提示魁衙,應(yīng)該可以很快的定位到這個文件报腔,他的真實路徑是在src/platforms/web/ entry-runtime-with-compiler.js
。至于entry中缺少的那部分剖淀,其實vue內(nèi)部使用別名alias
來做了處理纯蛾。
entry: resolve('web/entry-runtime-with-compiler.js')
在entry-runtime-with-compiler.js
中可以看到如下代碼。大約在8行纵隔。
import Vue from './runtime/index'
然后是runtime/index
翻诉。第一行,此處使用了alias別名處理捌刮。
import Vue from 'core/index'
然后是src/core/index
碰煌。第一行。
import Vue from './instance/index'
然后是./instance/index
绅作。在這個文件中再也沒有import Vue
的字樣了芦圾,那就證明vue的主體函數(shù)就存放在這個文件下!其實代碼很少棚蓄,那就全部貼出來看一下堕扶!
import { initMixin } from './init'
import { stateMixin } from './state'
import { renderMixin } from './render'
import { eventsMixin } from './events'
import { lifecycleMixin } from './lifecycle'
import { warn } from '../util/index'
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)
stateMixin(Vue)
eventsMixin(Vue)
lifecycleMixin(Vue)
renderMixin(Vue)
export default Vue
我大概解釋一下這幾行代碼。上邊那一堆mixin函數(shù)其實就一些狀態(tài)的初始化梭依,比如說data內(nèi)的可觀察數(shù)據(jù)就是在stateMixin
中完成稍算,生命周期就是在lifecycleMixin
,渲染就是在renderMixin
中完成役拴。當我們使用new Vue的時候這些東西最后都會變成一個個方法糊探,被掛載到vm實例上。
下邊解釋一下函數(shù)內(nèi)部的代碼河闰,options就是new Vue({...options})科平。函數(shù)會先檢查一下是否由new來生成,因為vm實例要是一個對象姜性。然后直接執(zhí)行_init方法瞪慧,這個方法其實是在initMixin
中被掛載上去的。
最后總結(jié)一下部念,vue其實就是一個函數(shù)弃酌,然后在初始化的時候在prototype上掛載一堆方法,new vue的時候儡炼,其實生成的是一個實例妓湘,這個實例繼承了一堆方法來輔助我們完成相應(yīng)的開發(fā)。
下一篇就跟著代碼的思路走乌询,直接分析一下initMixin方法榜贴,看一看vue如何完成初始化!