[TOC]
* * * * *
# 1 測試示例目錄名稱(benchmarks\,examples\,test\)
* benchmarks\ 目錄下主要包含Vue性能測試用例
* examples\ 目錄下主要包含Vue簡單使用示例
* test\ 目錄下主要包含Vue單元測試用例
# 2 單元測試目錄(test\)分析
* test\e2e\ 目錄下是nightwatch測試文件
* helpers\ 目錄下的文件在unit目錄的單元測試時使用
* ssr\ 目錄下的文件是服務器渲染測試文件
* unit\ 目錄下的文件是單元測試文件
## 2-1 測試助手目錄(helpers\)分析
* classlist.js 注冊toHaveClass函數,檢查元素是否包含特定class
* to-equal.js 注冊toEqual函數,比較兩個值是否相同
* to-have-been-warned.js 注冊toHaveBeenWarned,警告信息
* trigger-event.js 注冊triggerEvent,事件觸發函數
* vdom.js 注冊createTextVNode函數,創建虛擬節點
* wait-for-update.js 注冊waitForUpdate函數,等待刷新
>以上注冊都是在jasmine單元測試框架中進行注冊
> jasmine是javascript的行為驅動測試框架
> 有關jasmine的語法 見 [jsamine用法](http://www.ibm.com/developerworks/cn/web/1404_changwz_jasmine/)
## 2-2 單元測試目錄(unit\)分析
* index.js 單元測試入口文件,導入測試助手文件與所有測試文件
* features\ 功能性單元測試
* modules\ 模塊單元測試
## 2-3 功能單元測試目錄(unit\features\)分析
### .1(component\\)組件測試
> component.spec.js
~~~
;核心代碼
....
;component的測試使用示例.
vm = new Vue({
template: '<test></test>',
components: {
test: {
data () {
return { a: 123 }
},
template: '<span>{{a}}</span>'
}
}
}).$mount()
;實現一個test組件,test組件中的元素template屬性<span>{{a}}</span>
;并且test組件的span中包含的數據data屬性a:123.
;最后<test></test>渲染為<spane>123</span>
....
vm = new Vue({
template: '<div><table><tbody><test></test></tbody></table></div>',
components: {
test: {
data () {
return { a: 123 }
},
template: '<tr><td>{{a}}</td></tr>'
}
}
}).$mount()
;與上面相同實現<test></test>組件
...
vm = new Vue({
template: '<div><table><tbody><tr is="test"></tr></tbody></table></div>',
components: {
test: {
data () {
return { a: 123 }
},
template: '<tr><td>{{a}}</td></tr>'
}
}
}).$mount()
;使用<tr is="test"></tr>使用test組件模板
...
vm = new Vue({
template: '<div><test inline-template><span>{{a}}</span></test></div>',
data: {
a: 'parent'
},
components: {
test: {
data () {
return { a: 'child' }
}
}
}
}).$mount()
;使用inline-template聲明為行內組件
...
new Vue({
template: '<test></test>',
components: {
test: {
data () {
return { a: 123, b: 234 }
},
template: '<p>{{a}}</p><p>{{b}}</p>'
}
}
}).$mount()
; 組件中只可以包含一個根元素,不可使用多個元素并列
...
vm = new Vue({
template: '<component :is="view" :view="view"></component>',
data: {
view: 'view-a'
},
components: {
'view-a': {
template: '<div>foo</div>',
data () {
return { view: 'a' }
}
},
'view-b': {
template: '<div>bar</div>',
data () {
return { view: 'b' }
}
}
}
}).$mount()
; 使用:is="view" :view="view"動態切換組件內容
vm = new Vue({
template:
'<div>' +
'<component :is="$options.components.test"></component>' +
'<component :is="$options.components.async"></component>' +
'</div>',
components: {
test: {
template: '<span>foo</span>'
},
async: function (resolve) {
resolve({
template: '<span>bar</span>'
})
}
}
}).$mount()
;:is只可以用在名為component的組件元素中。
;:is不可以用在其他名稱的組件元素中
....
vm = new Vue({
template:
'<div>' +
'<component v-for="c in comps" :is="c.type"></component>' +
'</div>',
data: {
comps: [{ type: 'one' }, { type: 'two' }]
},
components: {
one: {
template: '<span>one</span>'
},
two: {
template: '<span>two</span>'
}
}
}).$mount()
;在component中可以使用v-for
...
vm = new Vue({
data: {
ok: false,
message: 'hello'
},
template: '<test v-show="ok">{{message}}</test>',
components: {
test: {
template: '<div><slot></slot> {{message}}</div>',
data () {
return {
message: 'world'
}
}
}
}
}).$mount()
; 在組件中使用v-show控制顯示
; 其中的message使用vue父級作用的值
vm = new Vue({
data: {
ok: false,
message: 'hello'
},
template: '<test v-if="ok">{{message}}</test>',
components: {
test: {
template: '<div><slot></slot> {{message}}</div>',
data () {
return {
message: 'world'
}
}
}
}
}).$mount()
; v-if在組件中的使用
...
vm = new Vue({
data: {
list: [{ a: 1 }, { a: 2 }]
},
template: '<test :collection="list"></test>',
components: {
test: {
template: '<ul><li v-for="item in collection">{{item.a}}</li></ul>',
props: ['collection']
}
}
}).$mount()
;使用:collection引用父級的props的list屬性。
;在子組件中使用v-for遍歷collectiond的props屬性
~~~
> component-async.spec.js
~~~
;核心實例代碼
....
const vm = new Vue({
template: '<div><test></test></div>',
components: {
test: (resolve) => {
setTimeout(() => {
resolve({
template: '<div>hi</div>'
})
// wait for parent update
Vue.nextTick(next)
}, 0)
}
}
}).$mount()
;組件異步填充.
...
vm = new Vue({
template: '<test></test>',
components: {
test: resolve => {
setTimeout(() => {
resolve({
template: '<div>hi</div>'
})
// wait for parent update
Vue.nextTick(next)
}, 0)
}
}
}).$mount()
;作為根元素填充
...
vm = new Vue({
template: '<component :is="view"></component>',
data: {
view: 'view-a'
},
components: {
'view-a': resolve => {
setTimeout(() => {
resolve({
template: '<div>A</div>'
})
Vue.nextTick(step1)
}, 0)
},
'view-b': resolve => {
setTimeout(() => {
resolve({
template: '<p>B</p>'
})
Vue.nextTick(step2)
}, 0)
}
}
}).$mount()
;:is="view" 根據view值動態切換組件渲染
vm = new Vue({
template: '<div><test v-for="n in list" :n="n"></test></div>',
data: {
list: [1, 2, 3]
},
components: {
test: resolve => {
setTimeout(() => {
resolve({
props: ['n'],
template: '<div>{{n}}</div>'
})
Vue.nextTick(next)
}, 0)
}
}
}).$mount()
;使用v-for循環遍歷
~~~
> component-keep-alive.spec.js
~~~
;組件keep-alive屬性的使用核心代碼
....
one = {
template: '<div>one</div>',
created: jasmine.createSpy('one created'),
mounted: jasmine.createSpy('one mounted'),
activated: jasmine.createSpy('one activated'),
deactivated: jasmine.createSpy('one deactivated'),
destroyed: jasmine.createSpy('one destroyed')
}
two = {
template: '<div>two</div>',
created: jasmine.createSpy('two created'),
mounted: jasmine.createSpy('two mounted'),
activated: jasmine.createSpy('two activated'),
deactivated: jasmine.createSpy('two deactivated'),
destroyed: jasmine.createSpy('two destroyed')
}
components = {
one,
two
}
;聲明兩個keep-alive組件的構子函數
function assertHookCalls (component, callCounts) {
expect([
component.created.calls.count(),
component.mounted.calls.count(),
component.activated.calls.count(),
component.deactivated.calls.count(),
component.destroyed.calls.count()
]).toEqual(callCounts)
}
;構子函數調用測試統計
const vm = new Vue({
template: '<div v-if="ok"><component :is="view" keep-alive></component></div>',
data: {
view: 'one',
ok: true
},
components
}).$mount()
;ok控制組件使用
;:is="view"控制組件的動態切換
vm = new Vue({
template: `<div>
<component
:is="view"
class="test"
keep-alive
transition="test"
transition-mode="out-in">
</component>
</div>`,
data: {
view: 'one'
},
components,
transitions: {
test: {
afterLeave () {
next()
}
}
}
}).$mount(el)
;使用transition="test" transition-mode="out-in"控制組件屬性
;class依次循環添加test-leave,test-leave-active,test-enter,test-enter-active,空,test-leave,test-leave-active,test-enter,test-enter-active,空等動畫屬性
...
vm = new Vue({
template: `<div>
<component
:is="view"
class="test"
keep-alive
transition="test"
transition-mode="in-out">
</component>
</div>`,
data: {
view: 'one'
},
components,
transitions: {
test: {
afterEnter () {
next()
}
}
}
}).$mount(el)
;與上個例子相似
;class依次循環添加test-enter,test-enter-active,空,test-leave,test-leave-active,空,test-enter,test-enter-active,空,test-leave,test-leave-active,空等動畫屬性。
...
~~~
> component-slot.spec.js
~~~
;component-slot使用實例
~~~~
### .2(directives\\)指令測試
代碼過多,按照組件的思路分析,
### .3(filter\\)過濾器測試
代碼過多,按照組件的思路分析,
### .4(global-api\\)api擴展測試
代碼過多,按照組件的思路分析,
### .5(instance\\)核心測試
代碼過多,按照組件的思路分析,
### .6(options\\)選項測試
代碼過多,按照組件的思路分析,
### .7(render\\)渲染測試
代碼過多,按照組件的思路分析,
### .8(transition\\)動畫測試
代碼過多,按照組件的思路分析,
## 2-4 模塊單元測試目錄(unit\modules)分析
# 3 deom示例目錄(examples\)分析
# 4 性能測試目錄(benchmarks\)分析
- 框架概述
- 框架目錄
- 類型檢查
- 測試示例
- 構建目錄
- 核心依賴
- 框架結構
- 模板編譯(compiler)
- directives(指令解析)
- parser(模板解析)
- codegen.js(生成渲染函數)
- error-detector.js(錯誤檢測)
- events.js(事件解析)
- helpers.js(編譯助手)
- index.js(編譯入口)
- optimizer.js(解析優化)
- 核心接口(core)
- components(框架組件)
- global-api(框架擴展)
- instance(Vue核心)
- observer(數據綁定)
- util(核心工具)
- vdom(虛擬dom)
- config.js(配置文件)
- index.js(入口文件)
- 構建入口(entries)
- web-compiler.js(編譯時)
- web-runtime.js(運行時)
- web-runtime-with-compiler.js(編譯運行時)
- web-server-renderer.js(服務端渲染)
- 平臺接口(platforms\web)
- compiler(web編譯時)
- runtime(web運行時)
- server(web服務渲染)
- util(web工具)
- 服務端渲染(server)
- create-renderer.js(渲染接口)
- render.js(函數渲染)
- render-stream.js(流渲染)
- 工具目錄(shared)
- util(工具文件)
- 框架流程
- Vue初始化
- Vue模板編譯
- Vue數據渲染
- Vue數據綁定
- 框架更新
- 更新日志
- 基礎原理
- js基礎
- 數據綁定基礎
- vdom基礎
- mvvm基礎
- 框架總結