avatar

组件化开发

组件化开发

组件化的基本使用

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
<div id="app">
<!-- 3.使用组件 -->
<my-cpn></my-cpn>
<my-cpn></my-cpn>
<my-cpn></my-cpn>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script>
// 1.创建组件构造器对象
const cpnc = Vue.extend({
template:`
<div>
<h2>标题</h2>
<p>内容1...<p>
<p>内容2...<p>
</div>`
})
// 2.注册组件
Vue.component('my-cpn', cpnc)

const app = 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
<div id="app">
<h2>全局组件</h2>
<my-cpn></my-cpn>

<h2>局部组件</h2>
<cpnc></cpnc>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script>
// 1.创建组件构造器对象
const cpnc = Vue.extend({
template:`
<div>
<h2>标题</h2>
<p>内容1</p>
<p>内容2</p>
</div>`
})

// 2.注册组件(全局组件,可以在多个vue实例中使用)
Vue.component('my-cpn', cpnc)

const app = new Vue({
el:"#app",
components:{
//局部组件创建
cpnc:cpnc
}
})
</script>

父组件与子组件的区别

Vue->cpn2->cpn1 (爷爷->爸爸->儿子)

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

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script>
// 1.创建组件构造器对象
const cpn1 = Vue.extend({
template:`
<div>
<h2>标题1</h2>
<p>组件1</p>
</div>`
})

// 组件2中注册并使用组件1
const cpn2 = Vue.extend({
template:`
<div>
<h2>标题2</h2>
<p>组件2</p>
<cpn1></cpn1>
</div>`,
components:{
cpn1:cpn1
}
})

// 在Vue实例中注册组件2
const app = new Vue({
el:"#app",
components:{//局部组件创建
cpn2:cpn2
}
})
</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
<div id="app">
<cpn1></cpn1>
<cpn2></cpn2>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script>
// 1.注册全局组件语法糖
Vue.component('cpn1', {
template:`
<div>
<h2>全局组件语法糖</h2>
<p>全局组件语法糖</p>
</div>`
})

const app = new Vue({
el:"#app",
//局部组件创建
components:{
cpn2:{
template:`
<div>
<h2>局部组件语法糖</h2>
<p>局部组件语法糖</p>
</div>`
}
}
})
</script>

组件模板分离写法

推荐使用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
33
34
35
<div id="app">
<cpn1></cpn1>
<cpn2></cpn2>
</div>

<!-- 1.script标签注意类型是text/x-template -->
<script type="text/x-template" id="cpn1">
<div>
<h2>组件模板的分离写法</h2>
<p>script标签注意类型是text/x-template</p>
</div>
</script>

<!-- 2.template标签 -->
<template id="cpn2">
<div>
<h2>组件模板的分离写法</h2>
<p>template标签</p>
</div>
</template>

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
components: { //局部组件创建
cpn1:{
template:'#cpn1'
},
cpn2: {
template: '#cpn2'
}
}
})
</script>

组件的数据存放

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<div id="app">
<cpn1></cpn1>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
components: { //局部组件创建
cpn1:{
template:'<div>{{msg}}</div>',
data(){
return {
msg:"组件的数据存放必须要是一个函数"
}
}
}
}
})
</script>

组件的data为什么要是函数

组件中的data写成一个函数,数据以函数返回值形式定义,这样每复用一次组件,就会返回一份新的data,类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据。而单纯的写成对象形式,就使得所有组件实例共用了一份data,就会造成一个变了全都会变的结果。

如例所示,cpn1的data公用,cpn2的每个data都独立

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
<div id="app">
<h2>data不使用函数</h2>
<cpn1></cpn1>
<cpn1></cpn1>
<hr>
<h2>data使用函数</h2>
<cpn2></cpn2>
<cpn2></cpn2>
<hr>
</div>

<template id="cpn1">
<div>
<button @click="count--">-</button>
当前计数:{{count}}
<button @click="count++">+</button>
</div>
</template>

<template id="cpn2">
<div>
<button @click="count--">-</button>
当前计数:{{count}}
<button @click="count++">+</button>
</div>
</template>

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script>
const obj = {
count:0
};
const app = new Vue({
el: "#app",
components: { //局部组件创建
cpn1: {
template: '#cpn1',
data() {
return obj;
}
},
cpn2: {
template: '#cpn2',
data() {
return {
count: 0
}
}
}
}
})
</script>

组件通信:父->子

  1. 子组件props中写入要接收父组件数据的变量

  2. 在组件的模板中使用props中的变量

  3. 使用子组件时,将props中的变量与父组件中的数据用v-bind绑定起来

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
<div id="app">
<!-- 此处写cMovies、Cmovies等都是对的 -->
<!-- 因为HTML 中的 attribute 名是大小写不敏感的,所以浏览器会把所有大写字符解释为小写字符 -->
<cpn :cmovies="movies"></cpn>
</div>

<template id="cpn">
<div>
<ul>
<li v-for="(item, index) in cmovies">{{item}}</li>
</ul>
</div>
</template>

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script>
const cpn = {
template: '#cpn',
// 数组写法
// props: ['cmovies', 'cmessage'],
props: {
//对象写法
// 1.类型限制(多个类使用数组)
// cmovies:Array,
// cmessage:String,
// cmessage:['String','Number'],
// 2.提供一些默认值,以及必传值
cmessage: {
type: String,
default: 'zzzzz',
required: true //在使用组件必传值
},
//类型是Object/Array,默认值必须是一个函数
cmovies: {
type: Array,
default () {
return [1, 2, 3, 4]
}
},
// 3.自定义验证函数
// vaildator: function (value) {
// //这个传递的值必须匹配下列字符串中的一个
// return ['zzzzz', 'ttttt', 'yyy'].indexOf(value) !== -1
// }
// 4.自定义类型
// cmessage:Person,
}
}

const app = new Vue({
el: "#app",
data: {
message: "Hello VueJs!",
movies: ['海贼王', '火影忍者', '圣斗士', '妖精的尾巴']
},
components: {
cpn
}
})
</script>

组件通信:子->父

  1. 在子组件的methods中,利用emit发送监听标识与子组件的数据

this.$emit(‘itemclick’, item) /itemclick为监听信号, item为发送出去的数据

  1. 使用子组件时,监听子组件的itemclick,此时携带了子组件的数据

<cpn @itemclick=”cpnClcik(item)”>

  1. 触发itemclick执行父组件中的方法,此时将子组件的数据传入了父组件,并在父组件中调用

cpnClcik(item) {console.log(‘cpnClick’+item.name);}

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
<div id="app">
<!-- 不写参数默认传递btnClick的item -->
<cpn @itemclick="cpnClcik"></cpn>
</div>

<template id="cpn">
<div>
<button v-for="(item, index) in categoties" :key="index" @click="btnClick(item)">{{item.name}}</button>
</div>
</template>

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script>
const cpn = {
template: "#cpn",
data() {
return {
categoties: [{
id: 'aaa',
name: '热门推荐'
},
{
id: 'bbb',
name: '手机数码'
},
{
id: 'ccc',
name: '家用家电'
},
{
id: 'ddd',
name: '电脑办公'
},
]
}
},
methods: {
btnClick(item) {
this.$emit('itemclick', item)
}
},
};
const app = new Vue({
el: "#app",
data:{},
methods: {
cpnClcik(item) {
console.log('cpnClick'+item.name);
}
},
components: {
cpn
},
})

父访问子:children, ref

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
<div id="app">
<cpn></cpn>
<cpn></cpn>
<cpn ref="aaa"></cpn>
<button @click="btnClick" >按钮</button>
</div>

<template id="cpn">
<div>
我是子组件
</div>
</template>

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script>
const cpn = {
template: "#cpn",
data() {
return {
name:"我是子组件的name"
}
},
methods: {
showMessage(){
console.log("showMessage");
}
},
};
const app = new Vue({
el: "#app",
data() {
return {
message:"hello"
}
},
methods: {
btnClick(){
// 1.children
console.log(this.$children[0].showMessage)
for (let cpn of this.$children) {
console.log(cpn.showMessage)
}

// 2.$ref
console.log(this.$refs.aaa.name)
}
},
components: {
cpn
},
})
</script>

子访问父:parent, root

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

<template id="cpn">
<div>
子组件消息:{{message}}
<button @click="btnClick" >子组件按钮</button>
</div>
</template>

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script>
const cpn = {
template: "#cpn",
data() {
return {
message:"我是子组件的name"
}
},
methods: {
btnClick(){
console.log("子组件按钮被点击")
// 1.访问父组件$parent
this.message = this.$parent.message
// 2.访问根组件$root
console.log(this.$root)
console.log(this.$root.message)
}
},
};
const app = new Vue({
el: "#app",
data() {
return {
message:"我是父组件消息"
}
},
components: {
cpn
},
})
</script>
文章作者: Gy
文章链接: http://sgyat.cn/2021/03/11/Vue总结(五)/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 年轻没有梦
打赏
  • 微信
    微信
  • 支付宝
    支付宝

评论