vueJs源碼解讀0-1

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命令顯式的指定輸出的代碼,輸入的時候也採用靜態命令的形式。模塊之間的依賴關係在編譯的時候就確定了

  1. 一個模塊也即是一個獨立的文件
  2. 使用export規定模塊對外的接口
  3. 使用import輸入其他模塊提供的功能
  4. 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到現在的情況

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章