[TOC]
* * * * *
## 1 源代碼文件
### 1-1 VM創建入口
~~~
src\vmodel\parts\share.js
~~~
### 1-2 VM創建實現
~~~
src\vmodel\modern.js
~~~
## 2 流程分析
### 2-1 VM創建接口define
>[success] 接口實現文件 src\vmodel\parts\share.js
~~~
function define(definition) {
var $id = definition.$id
if (!$id && avalon.config.debug) {
avalon.warn('vm.$id must be specified')
}
var vm = $$midway.masterFactory(definition, {}, {
pathname: '',
id: $id,
master: true
})
if (avalon.vmodels[$id]) {
throw Error('error:[', $id, '] had defined!')
}
return avalon.vmodels[$id] = vm
}
~~~
> definition:vm對象結構參數
~~~
var vm = avalon.define({
$id: 'test',
a: 11,
b: {
c: 22
}
})
~~~
> definition為
~~~
{
$id: 'test',
a: 11,
b: {
c: 22
}
}
~~~
* * * * *
> define() 中
> 首先獲取$id為參數definition的$id,上面的test.
> if()判斷$id是否獲取成功,
> 然后調用$$midway.masterFactory()創建vm
> 這里的masterFactory()是vm創建的實現核心
> 然后檢測avalon.vmodels是否包含$id索引
> 然后將創建的vm以$id為索引保存到avalon.vmodels全局數組中
~~~
avalon.define = define
~~~
> 導出define到全局接口avalon.define()
### 2-2 VM創建實現masterFactory
>[success] 創建實現文件 src\vmodel\parts\share.js
~~~
function masterFactory(definition, heirloom, options) {
var $skipArray = {}
if (definition.$skipArray) {
$skipArray = avalon.oneObject(definition.$skipArray)
delete definition.$skipArray
}
var keys = {}
options = options || {}
heirloom = heirloom || {}
var accessors = {}
var hashcode = makeHashCode("$")
var pathname = options.pathname || ""
options.id = options.id || hashcode
options.hashcode = hashcode
var key, sid, spath
for (key in definition) {
if ($$skipArray[key])
continue
var val = keys[key] = definition[key]
if (!isSkip(key, val, $skipArray)) {
sid = options.id + "." + key
spath = pathname ? pathname + "." + key : key
accessors[key] = makeAccessor(sid, spath, heirloom)
}
}
accessors.$model = modelAccessor
var $vmodel = new Observer()
Object.defineProperties($vmodel, accessors)
for (key in keys) {
$vmodel[key] = keys[key]
if (key in $skipArray) {
delete keys[key]
} else {
keys[key] = true
}
}
makeObserver($vmodel, heirloom, keys, accessors, options)
return $vmodel
}
~~~
> definition:avalon.define()傳遞參數
> heirloom:avalon.mediatorFactory(vm1,vm2)的合并vm
> options:
* * * * *
>[info] definition.$skiparray處理
* * * * *
> 首先獲取definition.$skipArray并保存
> 這里的$skipArray信息不需要進行監聽,
> 調用avalon.oneObject()創建一個簡單對象,
> 見框架工具的 另:全局函數
* * * * *
>[info] 變量聲明
* * * * *
> 然后聲明一系列創建過程中使用到變量
> keys 需要監聽的鍵信息
> options 額外參數
> heirloom 繼承的vm
> accessors
> hashcode 默認hanscode
> pathname
> options.id
> options.hashcode
> key definition的鍵key
> sid 節點內部鍵? $.key
> spath 節點內部路徑? pathname.key.key
* * * * *
>[info] 遍歷definition鍵創建訪問器
* * * * *
> 接著遍歷definition的鍵
如果是key存在$$skipArray中跳到下個key處理
保存非$$skipArray的key與值到val和keys[key]
這里的$$skipArray在下面介紹
調用isSkip()檢查key,val與$skipArray的關系
如果不是$skipArray的key。
則創建sid,spath,
然后以sid,spath,heirloom調用makeAccessor()創建訪問器
isSkip()下面介紹
makeAccessor()是創建訪問器的核心函數,下面分析
* * * * *
>[info] 創建$vmodel,并掛載訪問器
* * * * *
> 將訪問的$model設置為默認訪問modelAccessor
> 創建$vmodel為空對象
> 調用Object.defineProperties()掛載訪問,
> 這里的definProperties()是mvvm框架的實現核心。
> 具體使用基礎原理的 Object對象
* * * * *
>[info] $vmodel監控屬性生成
* * * * *
> 將全部keys的key與值保存到$vmodel[key]
> 然后刪除keys中在$skipArray的key。
> 這里的$skipArray不需要監控。
> $skipArray與$$skipArray不同
* * * * *
>[info] $vmodel高級屬性生成
* * * * *
> 調用makeObserver()創建高級屬性
> 包括$model,$id,$hashcode,$element,$render等
> makeObserver()在內部調用hideProperty()
> 這里的hideProperty()也就是調用Object.defineProperty()
> 下面詳細分析
* * * * *
>[info] $vmodel返回
* * * * *
> 返回$vmodel。
由avalon.define()可知,最后這個$vmodel
以$id為索引保存到全局avalon.vmodel數組中
~~~
$$midway.masterFactory = masterFactory
~~~
> 導出masterFactory到$$midway
最后在上面的avalon.define()函數中調用
## 3 其他代碼
VM創建相關其他代碼見
附:VM生成
## 4 總結
### 4-1意義
avalon.define()創建vm對象。
正如概述中對mvvm的解析。
這個vm是連接視圖html與后端數據api的關鍵
也就是mvvm中的vm,m對應后端api,v對應視圖html
### 4-2 思路
調用
Object.defineProperty()
Object.defineProperties()
創建vm對象
相關原理見基礎原理 Object對象
### 4-3參考鏈接
[avalon2學習教程02vm](https://segmentfault.com/a/1190000004882922)
- 概述
- 框架目錄
- 組件目錄(components\)
- 生成目錄(dist\)
- 測試目錄(karma\)
- 示例目錄(perf\)
- 主體目錄(src)
- 其他文件
- 框架流程
- 前:章節說明
- 主:模板掃描(avalon.scan())
- 主:VM創建(avalon.define())
- 主:同步刷新(avalon.batch())
- 附:節點解析(avalon.lexer())
- 附:虛擬DOM(avalon.vdomAdaptor())
- 附:渲染函數(avalon.render())
- 附:VM生成(avalon.masterFactory())
- 附:節點diff(avalon.diff())
- 主:界面事件(test)
- 框架工具
- 另:全局函數
- 另:全局正則
- 另:事件接口
- 另:組件接口
- 另:DOMApi
- 框架驅動
- D : 指令實現
- D:兼容處理
- 使用范例
- 基礎原理
- js模塊
- js對象
- js函數
- js數組
- js字符串
- dom接口
- 框架心得
- 心:總體思路