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