vue原始碼探究---讀vue技術揭祕(1)
阿新 • • 發佈:2018-11-05
需要了解
RollUp
Flow
RollUp
Rollup是一個js的模組打包器,可以將小塊程式碼編譯成大塊複雜程式碼,那為什麼這樣做呢,為了降低開發問題時候的複雜度
Tree-shaking(搖樹優化)
除了使用ES6的模組外,Rollup還能靜態分析程式碼中的import
// 使用 ES6 import 語句匯入(import) ajax 函式 import { ajax } from 'utils'; var query = 'Rollup'; // 呼叫 ajax 函式 ajax( 'https://api.example.com?search=' + query ).then( handleResponse );
Vue 原始碼目錄
├── scripts ------------------------------- 構建相關的檔案,一般情況下我們不需要動 │ ├── git-hooks ------------------------- 存放git鉤子的目錄 │ ├── alias.js -------------------------- 別名配置 │ ├── config.js ------------------------- 生成rollup配置的檔案 │ ├── build.js -------------------------- 對 config.js 中所有的rollup配置進行構建 │ ├── ci.sh ----------------------------- 持續整合執行的指令碼 │ ├── release.sh ------------------------ 用於自動釋出新版本的指令碼 ├── dist ---------------------------------- 構建後文件的輸出目錄 ├── examples ------------------------------ 存放一些使用Vue開發的應用案例 ├── flow ---------------------------------- 型別宣告,使用開源專案 [Flow](https://flowtype.org/) ├── packages ------------------------------ 存放獨立釋出的包的目錄 ├── test ---------------------------------- 包含所有測試檔案 ├── src ----------------------------------- 這個是我們最應該關注的目錄,包含了原始碼 │ ├── compiler -------------------------- 編譯器程式碼的存放目錄,將 template 編譯為 render 函式 │ ├── core ------------------------------ 存放通用的,與平臺無關的程式碼 │ │ ├── observer ---------------------- 響應系統,包含資料觀測的核心程式碼 │ │ ├── vdom -------------------------- 包含虛擬DOM建立(creation)和打補丁(patching)的程式碼 │ │ ├── instance ---------------------- 包含Vue建構函式設計相關的程式碼 │ │ ├── global-api -------------------- 包含給Vue建構函式掛載全域性方法(靜態方法)或屬性的程式碼 │ │ ├── components -------------------- 包含抽象出來的通用元件 │ ├── server ---------------------------- 包含服務端渲染(server-side rendering)的相關程式碼 │ ├── platforms ------------------------- 包含平臺特有的相關程式碼,不同平臺的不同構建的入口檔案也在這裡 │ │ ├── web --------------------------- web平臺 │ │ │ ├── entry-runtime.js ---------- 執行時構建的入口,不包含模板(template)到render函式的編譯器,所以不支援 `template` 選項,我們使用vue預設匯出的就是這個執行時的版本。大家使用的時候要注意 │ │ │ ├── entry-runtime-with-compiler.js -- 獨立構建版本的入口,它在 entry-runtime 的基礎上添加了模板(template)到render函式的編譯器 │ │ │ ├── entry-compiler.js --------- vue-template-compiler 包的入口檔案 │ │ │ ├── entry-server-renderer.js -- vue-server-renderer 包的入口檔案 │ │ │ ├── entry-server-basic-renderer.js -- 輸出 packages/vue-server-renderer/basic.js 檔案 │ │ ├── weex -------------------------- 混合應用 │ ├── sfc ------------------------------- 包含單檔案元件(.vue檔案)的解析邏輯,用於vue-template-compiler包 │ ├── shared ---------------------------- 包含整個程式碼庫通用的程式碼 ├── package.json -------------------------- 不解釋 ├── yarn.lock ----------------------------- yarn 鎖定檔案 ├── .editorconfig ------------------------- 針對編輯器的編碼風格配置檔案 ├── .flowconfig --------------------------- flow 的配置檔案 ├── .babelrc ------------------------------ babel 配置檔案 ├── .eslintrc ----------------------------- eslint 配置檔案 ├── .eslintignore ------------------------- eslint 忽略配置 ├── .gitignore ---------------------------- git 忽略配置
Vue 不同構建輸出
vue使用Rollup構建,有三種輸出方式,UMD,CommonJS,ESModule,三種構建配置入口相同web/entry-runtime.js,但是輸出格式format不同,cjs,es,umd,每種模組形式又分為執行版和完成版
完整版比執行版多一個compiler(觀察者),作用為編譯器程式碼的存放目錄,將template編譯為render,執行版+Compiler = 完整版
Flow
Flow 是Facebook出品的JS靜態型別檢查工具,Vue.js原始碼就是利用Flow做靜態型別檢查。
Flow是動態型別語言,由於js是動態型別語言,很靈活,但是過於靈活容易寫出隱蔽的錯誤程式碼。所以類檢查是當前動態型別語言的發展趨勢。
Flow的工作方式
- 型別推斷:通過變數的使用上下文來推斷出變數的型別,根據推斷來檢查型別
- 型別註釋:事先註釋好我們需要的型別,FLow會基於註釋推斷
型別推斷
不需要任何程式碼修改即可進行型別檢查,會自動推斷變數型別。
function split(str) {
return str.split(' ')
}
split(11)
在Flow檢查後,會報錯,因為split需要的是字串
型別註釋
不需要編寫型別註釋就能過去反饋。
/*@flow*/
function add(x, y){
return x + y
}
add('Hello', 11)
Flow檢查不出錯誤,但是我們可以通過型別註釋來指明期望的型別,型別註釋以冒號:開頭,可以在函式引數,返回值和變數宣告中使用。
/*@flow*/
function add(x: number, y: number): number {
return x + y
}
add('Hello', 11)
這樣就可以檢查到型別。
陣列
/*@flow*/
var arr: Array<number> = [1, 2, 3]
arr.push('Hello')
陣列型別註釋的格式是Array,T表示陣列中每項的資料型別。
類和物件
class Bar {
x: string; // x 是字串
y: string | number; // y 可以是字串或者數字
z: boolean;
constructor(x: string, y: string | number) {
this.x = x
this.y = y
this.z = false
}
}
var bar: Bar = new Bar('hello', 4)
var obj: { a: string, b: number, c: Array<string>, d: Bar } = {
a: 'hello',
b: 11,
c: ['hello', 'world'],
d: new Bar('hello', 3)
}
類的型別註釋格式,可以對類自身的屬性做型別檢查,也可以對建構函式的引數做型別檢查,y中間使用|,表示y的型別既可以用字串也可用數字
Null
若想用型別T可以為null或undefined,可以寫成?T格式:
/*@flow*/
var foo: ?string = null