[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基础
- 框架总结