vue源碼解讀-1
在github上下載到源碼的後在src的目錄下也即是該所有分塊的源文件的地址所在的地方,使用webstrom在file–>Settings–>languages&Frameworks中選擇javascript使用ECMAScript6
1. index.js
import Vue from ‘./instance/vue’
import installGlobalAPI from ‘./global-api’
import { inBrowser, devtools } from ‘./util/index’
import config from ‘./config’
import export
使用了四個import,導入了所需要的模塊。ES6的模塊通過export命令顯式的指定輸出的代碼,輸入的時候也採用靜態命令的形式。模塊之間的依賴關係在編譯的時候就確定了
- 一個模塊也即是一個獨立的文件
- 使用export規定模塊對外的接口
- 使用import輸入其他模塊提供的功能
- export可以輸出變量函數或類;export輸出語句爲動態綁定的(如下面的例子);基本寫法在所定義的變量函數或類的前面加入export(如:export function a(){ …….}; export var s=’RankBill’) 或者在末尾使用export{a,s ,..}統一的輸出;
export var foo='test'
setTimeout(()=>foo='TEST',500)//test TEST
5.import表示導入輸出的變量函數或類。import {……} from ‘dst’: dst表示從哪個模塊中導入也即是文件名 可以寫爲 ‘./dst.js’或 ‘./dst’(./表示當前目錄下); 整體加載模塊的寫法爲:import * as rank from ‘./dst’ 表示加載dst中所有輸出的 整體重命名爲rank 或使用module:module rank from ‘./dst’
使用import的時候,變量名或函數名稱一定要與export中的對應,用戶則必須瞭解輸出的那些屬性或方法
6.export default可以指定模塊的默認輸出(默認的也即是隻有一個)使用export default …..相對應的是 import everyName from ”此時不需要使用{ }; export default functionName 會以匿名函數的形式導出,意味着import可以用任何名稱 (export default爲匿名函數的時候顯然符合規定 )
export default function a(){.....}
//function a(){...} export default a
import a from '**'
export function a(){...}
import {a} from '***'
export default function(){.....} //匿名
import name from '....'
ES6輸出的是值的只讀的引用,區別於commonJs輸出的值的拷貝;commonJs是加載時執行,es6只生成一個指向該模塊的動態引用
—> import Vue from ‘./instance/vue’(instance/vue.js)
此時進入instance/下的vue 可以看到 export default Vue
‘instance/vue’
function Vue (options) {
this._init(options)
}
1.這個Vue是一個正規正矩的函數的聲明的寫法(此時涉及函數聲明的提升,也即是在代碼執行前會先讀取函數的聲明 ;同理變量的提升)
function fa() {
console.info(“whahaha”)
}
(function () {
if (false) {
function fa() {
console.info(“shuangwaiwai”)
}
}
fa();
}()); //shuangwaiwai
函數的聲明會在當前的作用域內提升,相當於預先在該作用域頂部聲明瞭該函數變量的提升:
var tmp=”Beijing”
fucntion rk(){
console.info(tmp)
if(){
var tmp=”yeh”
}
}
rk()// undefined
此時相當於 在rk(rk.name)會在頂部聲明var tmp;
2.可以看出this指向調用Vue的作用上下文
在進入其他模塊前我們翻譯下這段註釋:
/**
* The exposed Vue constructor.
*
* API conventions: (API 慣例)
* - public API methods/properties are prefixed with$
* (公共API或屬性前加 ‘$’)
* - internal methods/properties are prefixed with_
* (內部調用方法或屬性前加‘_’)
* - non-prefixed properties are assumed to be proxied user
* data.(沒有任何標示前綴的屬性,看作爲被代理的用戶數據)
*
* @constructor
* @param {Object} [options]
* @public
*/
部分註釋不明白的地方在後續會逐步的明朗開來,接下來進入的仍然是instance/vue.js中的其他的部分
// install internals
initMixin(Vue)
stateMixin(Vue)
eventsMixin(Vue)
lifecycleMixin(Vue)
miscMixin(Vue)// install instance APIs
dataAPI(Vue)
domAPI(Vue)
eventsAPI(Vue)
lifecycleAPI(Vue)
—>initMixin(Vue) (instance/internal/init.js)
1.顯然使用到了匿名函數的export default參數也即是Vue
2.導入了util/index中的mergeOptions函數(下文中會有介紹)
3.let的使用
let
let的使用最爲塊級作用域的福音,ES6引入了let用來聲明變量,其作用範圍只在let所在的代碼塊中有效;不存在變量的提升在塊級的範圍內使用到了let命令 則其聲明的變量綁定在該區域之內,任何在未聲明之前進行的賦值都會報錯
任何在let變量之前,改變量均不可用,語法上暫時性死區(TDZ)z
{
tmp=”df”
let tmp
} //error
一個例子說明let用法的好處
一種爲錯誤寫法後兩種爲IIFE與用let的寫法
對當前出入的Vue添加原型方法_init,c傳入參數爲options
options = options || {} //options爲空則爲{} 否則爲options
this.$el = null
this.$parent = options.parent
this.$root = this.$parent? this.$parent.$root : this
this.$children = []
this.$refs = {} // child vm references
this.$els = {} // element references
this._watchers = [] // all watchers as an array
this._directives = [] // all directives
$的表示public-api ; _ 開頭的表示internal-api,初始化後此時的this也即是指向Vue,爲初始化爲undefined;options也即是在初始化的時候進行new Vue({…}) 中,下面以具體的實例子講解大家會更加明白些
在控制檯中輸出options 與this
隨後在Vue上掛在了很多的屬性
八大實例屬性
屬性名 | 說明 |
---|---|
this.$el | |
this.$parent | |
this.$root | |
this.$children | |
this.$options | |
this.$refs={} | child vm references |
this.$els={} | element references |
與後面的$state共同構成了八大實例屬性 |
屬性名 | 說明 |
---|---|
this._watchers = [] | child vm references |
this._directives = [] | all directives |
this._isVue = true | a flag to avoid this being observed |
this._isVue = true | a flag to avoid this being observed |
event
屬性名 | – |
---|---|
this._events = {} | registered callbacks |
this._eventsCount = {} | for $broadcast optimization |
fragment
屬性名 | – |
---|---|
this._isFragment = false | registered callbacks |
this._fragment = | @type {DocumentFragment} |
this._fragment = | {DocumentFragment} |
this._fragmentStart = | @type {Text|Comment} |
this._fragmentEnd = null | @type {Text|Comment} |
lifecycle state
屬性名 | – |
---|---|
this._isCompiled = | |
this._isDestroyed = | |
this._isReady = | |
this._isAttached = | |
this._isBeingDestroyed = | |
this._vForRemoving = false | |
this._unlinkFn = null |
緊接着爲Vue install internals與 install instance APIs
initMixin(Vue)
stateMixin(Vue)
eventsMixin(Vue)
lifecycleMixin(Vue)
miscMixin(Vue)dataAPI(Vue)
domAPI(Vue)
eventsAPI(Vue)
lifecycleAPI(Vue)
(下表_爲internal ,$爲public)
initMixin(Vue) | Vue.prototype._init |
stateMixin(Vue) | 1. $data |
2.Vue.prototype._initState | |
3.Vue.prototype._initProps | |
4.Vue.prototype._initData | |
5. Vue.prototype._setData | |
6.Vue.prototype._proxy | |
7.Vue.prototype._digest | |
8.Vue.prototype._initComputed | |
9.Vue.prototype._initMethods | |
10.Vue.prototype._initMeta | |
eventsMin(Vue) | 1. Vue.prototype._initEvents |
2.Vue.prototype._initDOMHooks | |
3.Vue.prototype._callHook | |
lifecycleMixin(Vue) | 1.Vue.prototype._updateRef |
2.Vue.prototype._compile | |
3.Vue.prototype._initElement | |
4.Vue.prototype._bindDir | |
5.Vue.prototype._destroy | |
6.Vue.prototype._cleanup | |
miscMixin(Vue) | 1.Vue.prototype._applyFilters |
2.Vue.prototype._resolveComponent |
instance api:
7個數據類實例api
– | |
---|---|
dataAPI(Vue) | Vue.prototype.$get |
7個數據類api | Vue.prototype.$set |
Vue.prototype.$delete | |
Vue.prototype.$watch | |
Vue.prototype.$eval | |
Vue.prototype.$interpolate | |
Vue.prototype.$log | |
6個DOM操作api
– | |
---|---|
domAPI(Vue) | Vue.prototype.$nextTick |
DOM操作 | Vue.prototype.$appendTo |
Vue.prototype.$prependTo | |
Vue.prototype.$before | |
Vue.prototype.$after | |
Vue.prototype.$remove | |
6個事件類操作的api
– | |
---|---|
eventsAPI(Vue) | Vue.prototype.$on |
事件類 | Vue.prototype.$once |
Vue.prototype.$off | |
Vue.prototype.$emit | |
Vue.prototype.$broadcast | |
Vue.prototype.$dispatch | |
3個生命週期類api
– | |
---|---|
lifecycleAPI(vue) | Vue.prototype.$mount |
生命週期類 | Vue.prototype.$destroy |
Vue.prototype.$compile |
我們在通過類似的圖來準確的說明從index.js到現在的情況