vue2中的组件

  • 作用:基于组件开发,易维护易复用

  • 分类:使用的作用域不同分为全局组件局部组件

  • 注意

    • 组件名需要与原来的html标签不一致,且不要有大写字母
    • 组件的data数据是一个函数,将对象return出去,与vue实例不一致
    • 组件的template只能存在一个根标签

一、全局组件

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
<div id="app">
<my-component></my-component>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component('MyComponent', {
template: `
<div>
<h1>组件</h1>
<hr>
<button @click="toggle">切换</button>
<hr>
<h2 v-show="isShow">{{ msg }}</h2>
</div>
`,
data(){
return {
msg: "定义数据",
isShow: true
}
},
methods: {
toggle(){
this.isShow = !this.isShow;
}
}
})
new Vue({
el: "#app",
})
</script>

二、局部组件

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
<div id="app">
<my-component/>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
new Vue({
el: "#app",
components: {
'my-component': {
template: `
<div>
<button @click="over">Another year over</button>
<hr>
<h4 v-for="(val, key) in person">
{{ key }}{{ val }}
</h4>
</div>
`,
data(){
return{
person: {
name: "半月",
age: 18,
sex: "男"
}
}
},
methods: {
over(){
this.person.age++;
}
}
}
}
})
</script>

三、组件的参数传递

1)父组件传递参数给子组件

  1. 使用v-bind:自定义属性向子组件传递参数

  2. 子组件中使用props接收参数,props的值是一个数组

  3. 同data一致,使用插值表达式在子组件的模板中使用props的参数即可使用v-bind:自定义属性向子组件传递参数子组件中使用props接收参数,props的值是一个数组同data一致,使用插值表达式在子组件的模板中使用props的参数即可

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
<div id="app">
<my-component :msg="msg"/>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
new Vue({
el: "#app",
data: {
msg: "传递的值"
},
components: {
'my-component': {
template: `
<div>
<h1>{{ subName }}</h1>
<hr>
<h2>{{ msg }}</h2>
</div>
`,
data(){
return{
subName: "子组件"
}
},
props: [
"msg"
]
}
}
})
</script>

2)子组件传递参数给父组件

  1. 在子组件标签上自定义一个事件,内容指向父组件的一个方法,作为该自定义事件的参数接收方法

  2. 在子组件中调用**this.$emit(“自定义事件名”, 传递的参数)**方法,触发参数的传递

  3. 在父组件的接收方法中,来处理子组件传递的参数

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
<div id="app">
<h1>父组件</h1>
<h4>{{ subMsg }}</h4>
<hr>
<my-component @transmit="accept"/>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
new Vue({
el: "#app",
data: {
subMsg: ""
},
methods: {
accept(input){
this.subMsg = input;
}
},
components: {
'my-component': {
template: `
<div>
<h1>子组件</h1>
<button @click="send">发送数据</button>
<hr>
</div>
`,
data(){
return{
msg: "子组件的数据"
}
},
methods: {
send(){
this.$emit("transmit", this.msg);
}
}
}
}
})
</script>

3)非父子组件传递参数

  1. 创建一个空的vue实例对象,var data = new Vue(),用于充当事件中心的角色

  2. 在A组件中通过 data.$emit(自定义事件名, 传递的参数),触发自定义事件

  3. 在B组件中通过 data.$on(自定义事件名, function(input){...}),来监听自定义事件,通过处理函数来接收处理传递的参数

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
<div id="app">
<coma></coma>
<hr>
<comb></comb>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 1、创建一个空的vue实例对象
var data = new Vue();
new Vue({
el: "#app",
components: {
coma: {
template: `
<div>
<h1>{{ h1 }}</h1>
<button @click="send">发送</button>
</div>
`,
data() {
return{
h1: "组件A",
msg: "传递的参数"
}
},
methods: {
// 2、通过事件中心,触发自定义事件
send(){
data.$emit("sendMsg", this.msg);
}
}
},
comb: {
template: `
<div>
<h1>{{ h1 }}</h1>
<p>{{ msg }}</p>
</div>
`,
data(){
return{
h1: "组件B",
msg: ""
}
},
// 3、在生命周期created函数中监听自定义事件
created(){
data.$on("sendMsg", (msg) => {
this.msg = msg;
})
}
}
}
})
</script>

四、内置组件

1)component

  • 作用:用于动态渲染组件

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
<div id="app" class="container">
<h1>{{ title }}</h1>
<button @click="option('coma')" class="btn btn-info">登录</button>
<button @click="option('comb')" class="btn btn-info">注册</button>
<component :is="com"></component>
</div>

<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>
new Vue({
el: "#app",
data: {
title: "ref操作虚拟dom",
com: "coma"
},
methods: {
option(key){
this.com = key;
}
},
components: {
coma: {
template: `<h1>登录组件</h1>`
},
comb: {
template: `<h1>注册组件</h1>`
}
}
})
</script>

2)tarnsition

  • 作用:实现过度效果和动画

  • 属性:

    • name:可以自定义前缀,设置后各个状态的类名前缀将会改变
  • 步骤:

    1. 使用transition标签包裹元素或组件
    2. 对各个状态的类名进行样式的编写
      • 显示阶段类名:v-enter-active
        • 显示阶段开始:v-enter
        • 显示阶段结束:v-enter-to
      • 隐藏阶段:v-leave-active
        • 隐藏阶段开始:v-leave
        • 隐藏阶段结束:v-leave-to

2.1)使用内置状态类名

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
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<style>
.costom-enter, .costom-leave-to{
opacity: 0;
}
.costom-enter-to, .costom-leave{
opacity: 1;
}
.costom-enter-active, .costom-leave-active{
transition: opacity 0.7s;
}
</style>

<div id="app" class="container">
<h1>{{ title }}</h1>
<button @click="toggle" class="btn btn-info">显示/隐藏</button>
<transition name="costom">
<component is="coma" v-if="isShow"></component>
</transition>
</div>

<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>
new Vue({
el: "#app",
data: {
title: "transition过度动画",
isShow: true
},
methods: {
toggle(){
this.isShow = !this.isShow;
}
},
components: {
coma: {
template: `<h1>登录组件</h1>`
}
}
})
</script>

2.2)使用动画类库的类

  • Animate.css是一款强大的CSS3动画类库

    • 说明:是一款强大的CSS3动画类库,通过使用定义好动画类名,完成动画效果
    • 官网:https://animate.style/
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
<link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<div id="app" class="container">
<h1>{{ title }}</h1>
<button @click="show = !show">切换</button>
<hr>
<transition
name="custom-classes-transition"
enter-active-class="animated flipInX"
leave-active-class="animated flipOutX"
>
<p v-if="show">hello</p>
</transition>
</div>

<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>
new Vue({
el: "#app",
data: {
title: "animated动画类库",
show: true
},
})
</script>

3)transition-group

  • 作用:渲染多个元素,列表的动画

  • 注意:

    • 默认渲染为 span,通过指定tag更换为其他元素
    • 内部的v-for元素总要指定key属性
    • 过度动画处于内部的元素中,而不是transition
    • v-move对于设置过渡的切换时机和过渡曲线非常有用
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<style>
.list-group{
width: 200px;
}

.list-group-item{
transition: all .7s;
display: inline-block;
width: 30px;
height: 30px;
text-align: center;
line-height: 30px;
margin-right: 10px;
margin-bottom: 10px;
padding: 0;
}
/* .list-enter-active, .list-leave-active {
transition: all 0.7s;
} */
.list-enter, .list-leave-to {
opacity: 0;
transform: translateY(-60px);
}
.list-leave-active {
position: absolute;
}
</style>
<div id="app" class="container">
<button v-on:click="shuffle" class="btn btn-default">洗牌</button>
<button v-on:click="add" class="btn btn-info">随机添加</button>
<button v-on:click="remove" class="btn btn-success">随机移除</button>
<hr>
<transition-group name="list" tag="ul" class="list-group">
<li v-for="item in items" v-bind:key="item" class="list-group-item">
{{ item }}
</li>
</transition-group>
</div>

<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>
new Vue({
el: "#app",
data: {
title: "animated动画类库",
items: [1,2,3,4,5,6,7,8,9],
nextNum: 10
},
methods: {
randomIndex() {
return Math.floor(Math.random() * this.items.length)
},
add() {
this.items.splice(this.randomIndex(), 0, this.nextNum++)
},
remove() {
this.items.splice(this.randomIndex(), 1)
},
shuffle: function() {
let array = this.items;
let len = array.length;
for (let i = len - 1; i > 0; i--) {
let j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
this.items = Array.from(array);
}
}
})
</script>