知識儲備
-
: 将僞數組轉換為真數組[].slice.call(lis)
-
: 得到節點類型node.nodeType
-
Object.defineProperty(obj, propertyName, {})
: 給對象添加/修改屬性(指定描述符)
configurable: true/false 是否可以重新
enumerable: true/false 是否可以枚舉define
(for..in / keys())
value: 指定初始值
writable: true/false
value
是否可以修改存取(通路)描述符
get: 函數, 用來得到目前屬性值
set: 函數, 用來監視目前屬性值的變化
-
: 得到對象自身可枚舉的屬性名的數組Object.keys(obj)
-
: 文檔碎片(高效批量更新多個節點)DocumentFragment
-
: 判斷obj.hasOwnProperty(prop)
是否是prop
自身的屬性obj
資料代理(MVVM.js)
- 通過一個對象代理對另一個對象中屬性的操作(讀/寫)
- 通過
對象來代理vm
對象中所有屬性的操作data
- 好處: 更友善的操作data中的資料
-
基本實作流程
1). 通過
給Object.defineProperty()
添加與vm
data
對象的屬性對應的屬性描述符
2). 所有添加的屬性都包含
3). 在getter/setter
内部去操作getter/setter
中對應的屬性資料data
模闆解析(compile.js)
- 模闆解析的關鍵對象:
對象compile
-
模闆解析的基本流程:
1). 将el的所有子節點取出, 添加到一個建立的文檔fragment對象中
2). 對
fragment
中的所有層次子節點遞歸進行編譯解析處理
* 對表達式文本節點進行解析
* 對元素節點的指令屬性進行解析
* 事件指令解析
* 一般指令解析
3). 将解析後的
添加到fragment
中顯示el
- 解析表達式文本節點:
1). 根據正則對象得到比對出的表達式字元串: 子比對textNode.textContent = value
/RegExp.$1
2). 從data中取出表達式對應的屬性值
3). 将屬性值設定為文本節點的textContent
- 事件指令解析:
elementNode.addEventListener(事件名, 回調函數.bind(vm))
v-on:click="test"
1). 從指令名中取出事件名
2). 根據指令的值(表達式)從methods中得到對應的事件處理函數對象
3). 給目前元素節點綁定指定事件名和回調函數的dom事件監聽
4). 指令解析完後, 移除此指令屬性
- 一般指令解析:
elementNode.xxx = value
1). 得到指令名和指令值(表達式)
2). 從data中根據表達式得到對應的值
3). 根據指令名确定需要操作元素節點的什麼屬性
*
v-text---textContent
屬性
*
v-html---innerHTML
屬性
*
v-class--className
屬性
4). 将得到的表達式的值設定到對應的屬性上
5). 移除元素的指令屬性
資料劫持–>資料綁定
資料綁定(model==>View):
- 一旦更新了data中的某個屬性資料, 所有界面上直接使用或間接使用了此屬性的節點都會更新(更新)
資料劫持
四個重要對象
Observer
- 用來對
所有屬性資料進行劫持的構造函數data
- 給
中所有屬性重新定義屬性描述data
(get/set)
- 為
中的每個屬性建立對應的data
對象dep
Dep(Depend)
-
中的每個屬性(所有層次)都對應一個data
對象dep
- 建立的時機:
- 在初始化
define
中各個屬性時建立對應的dep對象data
- 在
中的某個屬性值被設定為新的對象時data
- 對象的結構
{
id, // 每個dep都有一個唯一的id
subs //包含n個對應watcher的數組(subscribes的簡寫)
}
-
subs
屬性說明
* 當一個
被建立時, 内部會将目前watcher
對象添加到對應的watcher
對象的dep
subs
中
* 當此
屬性的值發生改變時, 所有data
中的subs
都會收到更新的通知, 進而最終更新對應的界面watcher
Compile
- 用來解析模闆頁面的對象的構造函數(一個執行個體)
- 利用
對象解析模闆頁面compile
- 每解析一個表達式(非事件指令)都會建立一個對應的
對象, 并建立watcher
與watcher
的關系dep
-
與complie
關系: 一對多的關系watcher
Watcher
- 模闆中每個非事件指令或表達式都對應一個
對象watcher
- 監視目前表達式資料的變化
- 建立的時機: 在初始化編譯模闆時
- 對象的組成
{
vm, //vm對象
exp, //對應指令的表達式
cb, //當表達式所對應的資料發生改變的回調函數
value, //表達式目前的值
depIds //表達式中各級屬性所對應的dep對象的集合對象
//屬性名為dep的id, 屬性值為dep
}
總結: dep與watcher的關系: 多對多
- 一個
中的屬性對應對應一個data
, 一個dep
中可能包含多個dep
(模闆中有幾個表達式使用到了屬性)watcher
- 模闆中一個非事件表達式對應一個
, 一個watcher
中可能包含多個watcher
(表達式中包含了幾個dep
屬性)data
-
資料綁定使用到2個核心技術:
*
* 消息訂閱與釋出defineProperty()
雙向資料綁定
- 雙向資料綁定是建立在單向資料綁定
的基礎之上的(model==>View)
-
雙向資料綁定的實作流程:
* 在解析
指令時, 給目前元素添加v-model
* 當input監聽
的input
發生改變時, 将最新的值指派給目前表達式所對應的value
data屬性