來源于慕課網(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)試基本都是在這個文件中進(jìn)行。
-
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ù),其實不必太在意?,F(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中完成。當(dāng)我們使用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如何完成初始化!