4.1 简单轮子 VueContainer 布局组件
[toc]
需求分析
API设计
VueMain.vue
VueContainer.vue
VueHeader.vue
VueHeader.vue
VueFooter.vue
VueAside.vue
组件UI结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
<!-- 三栏布局 -->
<v-layout>
<v-header></v-header>
<v-content></v-content>
<v-footer></v-footer>
</v-layout>
<!-- 三栏布局 中栏 左侧菜单栏 -->
<v-layout>
<v-header></v-header>
<v-layout>
<v-sider></v-sider>
<v-content></v-content>
</v-layout>
<v-footer></v-footer>
</v-layout>
<!-- 三栏布局 中栏 右侧菜单栏-->
<v-layout>
<v-header></v-header>
<v-layout>
<v-content></v-content>
<v-sider></v-sider>
</v-layout>
<v-footer></v-footer>
</v-layout>
<!-- 左右两栏布局 左侧菜单栏 -->
<v-layout>
<v-sider></v-sider>
<v-layout>
<v-header></v-header>
<v-content></v-content>
</v-layout>
<v-footer></v-footer>
</v-layout>
|
- 重复使用
<v-layout>
作为嵌套容器,相当于div
标签
组件代码
- 分别创建组件
VueContainer.vue
VueMain.vue
VueHeader.vue
VueAside.vue
VueFooter.vue
- 全局注册组件
Vue.component('v-container', VueContainer)
Vue.component('v-main', VueMain)
Vue.component('v-header', VueHeader)
Vue.component('v-asider', VueAside)
Vue.component('v-footer', VueFooter)
- IDE 自动导入
import VueContainer from ...
./src/components/layout/VueContainer.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
<template>
<section class="container">
<slot></slot>
</section>
</template>
<script lang="ts">
import {Component, Vue} from 'vue-property-decorator';
@Component
export default class VueContainer extends Vue {
name = 'VueContainer';
}
</script>
<style lang="scss" scoped>
.container {
display: flex;
flex-direction: column;
flex-grow: 1;
}
</style>
|
LayoutGroups.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
<template>
<div>
<details open>
<summary>三栏布局</summary>
<vue-main style="height: 20vh;">
<vue-header class="demo">Header</vue-header>
<vue-container class="demo">Content</vue-container>
<vue-footer class="demo">Footer</vue-footer>
</vue-main>
</details>
<br>
<details open>
<summary>三栏布局 中栏 左侧菜单栏</summary>
<vue-main style="height: 20vh;">
<vue-header class="demo">Header</vue-header>
<vue-container class="demo">
<vue-aside>Aside</vue-aside>
<vue-container>Content</vue-container>
</vue-container>
<vue-footer class="demo">Footer</vue-footer>
</vue-main>
</details>
<br>
</div>
</template>
<script lang="ts">
import {Component, Vue} from 'vue-property-decorator';
import VueMain from './layout/VueMain.vue';
import VueContainer from './layout/VueContainer.vue';
import VueAside from './layout/VueAside.vue';
import VueHeader from './layout/VueHeader.vue';
import VueFooter from './layout/VueFooter.vue';
@Component({
components: {
VueMain,
VueContainer,
VueAside,
VueHeader,
VueFooter
}
})
export default class extends Vue {
name = 'LayoutGroups';
}
</script>
<style lang="scss" scoped>
@import '../style/global.scss';
.demo {
border: 1px solid orange;
min-height: 40px;
}
</style>
|
父子组件嵌套时创建和挂载的顺序
父子组件嵌套时,父组件视图和子组件视图在页面中渲染谁先谁后?
- 不确定
- 子组件先于父组件
mounted
- 所有子孙组件都
mounted
后,根(父)组件最后mounted
到页面中
测试的顺序
- 父组件
beforeCreated
- 父组件
created
- 子组件
beforeCreated
- 子组件
created
- 子组件
mounted
- 父组件
mounted
- …
父子组件嵌套时,所有组件视图都渲染完成后再执行回调操作
1
2
3
4
5
6
7
|
...
mounted() {
this.$nextTick(()=>{
// 仅在渲染整个视图之后,再立即运行的代码
})
}
...
|
组件name
属性的作用
- 使用浏览器vue插件时可以直接看到组件原来的命名,而不是直接显示HTML标签名
- 组件的实例中的
name
属性
- 可以通过判断是否存在特定的
name
,从而来实现相应的逻辑
打印出VueContainer.vue
中,所有子组件的name
属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
<template>
<section class="container">
<slot></slot>
</section>
</template>
<script lang="ts">
import {Component, Vue} from 'vue-property-decorator';
@Component
export default class VueContainer extends Vue {
name = 'VueContainer';
mounted() {
this.$children.forEach((vm)=> {
console.log(vm.$options.name);
})
}
}
</script>
|
实现判断子组件中有VueAside
,方向变为row
- 获取子组件的集合(数组)
this.$children
VueContainer.vue
单元测试