一:组件的基本用法
组件和创建Vue实例类似,需要先注册后才能使用,Vue组件注册方式分为全局注册和局部注册,全局注册的组件在任何使用Vue的地方均可使用,局部注册的组件只能在实例作用于范围内使用。
全局注册:
Vue.component('my-component', {
template : '<div>这是组件中的内容</div>'
});
或者使用局部注册:
var myTemplateContent = {
template : '<div>这是组件中的内容</div>'
};
new Vue({
el : '#app',
components : {
'my-component' : this.myTemplateContent
}
});
使用组件:
<div id="app"> <my-component></my-component> </div>
<div id="app">
<table>
<tbody is='my-component'></tbody>
</table>
</div>
<body>
<div id="app">
<my-component></my-component>
</div>
<script>
var myTemplateContent = {
template : '<div>{{message}}</div>',
data : function(){
return {message : '这是组件中的内容'}
}
};
new Vue({
el : '#app',
components : {
'my-component' : this.myTemplateContent
}
})
</script>
</body>
三:使用props在组件之间传递数据
组件可以进行层级嵌套,父组件的data是不能直接被子组件访问的,需要通过props参数来传递数据,传递的值可以是一个字符串数组或者对象。

1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset=utf-8>
5 <title>Test page</title>
6 <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
7 </head>
8 <body>
9 <div id="app">
10 <my-component message="来自父组件的数据"></my-component>
11 </div>
12
13 <script>
14
15 var myTemplateContent = {
16 props : ['message'],
17 template : '<div>{{message}}</div>'
18 };
19
20 new Vue({
21 el : '#app',
22 components : {
23 'my-component' : this.myTemplateContent
24 }
25 })
26 </script>
27 </body>
28 </html>
在上述示例中,<my-component message="来自父组件的数据"></my-component>的message属性值可以是v-bind动态绑定的数据,当绑定的数据更新时,模板内容也会动态更新:

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<title>Test page</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<input type="text" v-model='inputValue'>
<my-component :message='inputValue'></my-component>
</div>
<script>
var myTemplateContent = {
props : ['message'],
template : '<div>{{message}}</div>'
};
new Vue({
el : '#app',
components : {
'my-component' : this.myTemplateContent
},
data : {
inputValue : ''
}
})
</script>
</body>
</html>
上述代码示例中,当在input输入框中输入值时,会更新data中的inputValue,因此my-component组件的message属性值也会动态更新,组件的内容也随之动态更新。
组件之间除了可以进行数据通信,还可以进行组件之间的事件调用,从而完成消息发送和接收。
四:使用自定义事件从子组件向父组件传递数据
类似观察者模式,在Vue中,子组件使用$emit()来触发事件,父组件使用$on()来监听子组件的事件。
在下面的例子中,子组件my-component有两个按钮,handleIncrease和handleReduce分别用于增加和减少模板的data组件的counter值,然后使用$emit()方法通知父组件的increase和reduce方法。$emit()方法的第一个参数是自定义事件的名称,后续参数是要传递的数据。父组件使用handleGetTotal方法将接收到的参数赋值给自身的total值上。

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<title>Test page</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<p>总数:{{total}}</p>
<my-component @increase="handleGetTotal" @reduce="handleGetTotal"></my-component>
</div>
<script>
var myTemplateContent = {
template : '\
<div>\
<button @click="handleIncrease">+1</button>\
<button @click="handleReduce">-1</button>\
</div>',
data : function (){
return {counter : 0}
},
methods : {
handleIncrease : function(){
this.counter++;
this.$emit('increase', this.counter);
},
handleReduce : function(){
this.counter--;
this.$emit('reduce', this.counter);
}
}
};
new Vue({
el : '#app',
components : {
'my-component' : this.myTemplateContent
},
data : {total : 0},
methods : {
handleGetTotal : function(total){
this.total = total;
}
}
})
</script>
</body>
</html>

1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset=utf-8>
5 <title>Test page</title>
6 <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
7 </head>
8 <body>
9 <div id="app">
10 <p>{{message}}</p>
11 <my-component ></my-component>
12 </div>
13
14 <script>
15 //空的Vue对象作为"中介"
16 var bus = new Vue();
17
18 var myTemplateContent = {
19 template : '<button @click="handleEvent">传递事件</button>',
20 methods : {
21 handleEvent : function(){
22 bus.$emit('on-message', '来自my-component组件中的内容')
23 }
24 }
25 };
26
27 new Vue({
28 el : '#app',
29 components : {
30 'my-component' : this.myTemplateContent
31 },
32 data : {message : ''},
33 mounted : function(){
34 var that = this;
35 //Vue实例初始化时,监听来自bus的事件
36 bus.$on('on-message', function(msg){
37 that.message = msg;
38 })
39 }
40 })
41 </script>
42 </body>
43 </html>
六:组件之间的通信——父链和子组件索引
在子组件中,可以使用this.$parent来直接访问组件的父组件,父组件也可以用this.$children来访问它的所有子组件,且可以向上/向下无线递归访问,直到实例根元素或者最内层元素。实例代码:
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset=utf-8>
5 <title>Test page</title>
6 <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
7 </head>
8 <body>
9 <div id="app">
10 <p>{{message}}</p>
11 <my-component ></my-component>
12 </div>
13
14 <script>
15 //空的Vue对象作为"中介"
16 var bus = new Vue();
17
18 var myTemplateContent = {
19 template : '<button @click="handleEvent">通过父链直接修改数据</button>',
20 methods : {
21 handleEvent : function(){
22 this.$parent.message = '来自组件my-component的内容';
23 }
24 }
25 };
26
27 new Vue({
28 el : '#app',
29 components : {
30 'my-component' : this.myTemplateContent
31 },
32 data : {message : ''}
33 })
34 </script>
35 </body>
36 </html>
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset=utf-8>
5 <title>Test page</title>
6 <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
7 </head>
8 <body>
9 <div id="app">
10 <button @click="handleRef">通过ref获取子组件实例</button>
11 <my-component ref="comMy"></my-component>
12 </div>
13
14 <script>
15 var myTemplateContent = {
16 template : '<div>子组件</div>',
17 data : function(){
18 return {
19 message : '子组件内容'
20 }
21 }
22 };
23
24 new Vue({
25 el : '#app',
26 components : {
27 'my-component' : this.myTemplateContent
28 },
29 methods : {
30 handleRef : function(){
31 //通过refs访问指定的子组件实例
32 var msg = this.$refs.comMy.message;
33 console.log(msg)
34 }
35 }
36 })
37 </script>
38 </body>
39 </html>
$refs只在组件渲染完成后填充,并不是响应式的,应避免在模板和计算属性中使用$refs。
七:使用slot插槽分发内容
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset=utf-8>
5 <title>Test page</title>
6 <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
7 </head>
8 <body>
9 <div id="app">
10 <!--这里的showChild绑定的是父组件的数据-->
11 <my-component v-show="showChild"></my-component>
12 </div>
13 <script>
14 var myTemplateContent = {
15 template : '<div>子组件</div>'
16 };
17 new Vue({
18 el : '#app',
19 components : {
20 'my-component' : this.myTemplateContent
21 },
22 data : {
23 showChild : true
24 }
25 })
26 </script>
27
28 <div id="app2">
29 <my-component ></my-component>
30 </div>
31 <script>
32 var myTemplateContent = {
33 //这里的showChild绑定的是子组件的数据
34 template : '<div v-show="showChild">子组件</div>',
35 data : function(){
36 return {
37 showChild : true
38 }
39 }
40 };
41 new Vue({
42 el : '#app2',
43 components : {
44 'my-component' : this.myTemplateContent
45 }
46 })
47 </script>
48 </body>
49 </html>
(一)单个Slot插槽的用法

1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset=utf-8>
5 <title>Test page</title>
6 <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
7 </head>
8 <body>
9 <div id="app">
10 <child-component>
11 <p>分发的内容</p>
12 <p>更多分发的内容</p>
13 </child-component>
14 </div>
15 <script>
16 var myTemplateContent = {
17 template : '\
18 <div>\
19 <slot>\
20 <p>如果父组件没有插入内容,此行文字将作为默认内容</p>\
21 </slot>\
22 </div>'
23 };
24 new Vue({
25 el : '#app',
26 components : {
27 'child-component' : this.myTemplateContent
28 }
29 })
30 </script>
31 </body>
32 </html>

1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset=utf-8>
5 <title>Test page</title>
6 <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
7 </head>
8 <body>
9 <div id="app">
10 <child-component>
11 <h2 slot="header">标题</h2>
12 <p>分发的内容</p>
13 <p>更多分发的内容</p>
14 <div slot="footer">底部信息</div>
15 </child-component>
16 </div>
17 <script>
18 var myTemplateContent = {
19 template : '\
20 <div class="container">\
21 <div class="header">\
22 <slot name="header"></slot>\
23 </div>\
24 <div class="main">\
25 <slot></slot>\
26 </div>\
27 <div class="footer">\
28 <slot name="footer"></slot>\
29 </div>\
30 </div>'
31 };
32 new Vue({
33 el : '#app',
34 components : {
35 'child-component' : this.myTemplateContent
36 }
37 })
38 </script>
39 </body>
40 </html>

1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset=utf-8>
5 <title>Test page</title>
6 <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
7 </head>
8 <body>
9 <div id="app">
10 <child-component>
11 <template scope="props">
12 <p>来自父组件的内容</p>
13 <p>{{props.msg}}</p>
14 </template>
15 </child-component>
16 </div>
17 <script>
18 var myTemplateContent = {
19 template : '\
20 <div class="container">\
21 <slot msg="来自子组件的内容"></slot>\
22 </div>'
23 };
24 new Vue({
25 el : '#app',
26 components : {
27 'child-component' : this.myTemplateContent
28 }
29 })
30 </script>
31 </body>
32 </html>
子组件的模板中,<slot msg="来自子组件的内容"></slot>向插槽传递了一个msg,父组件使用了template元素,且有一个scope="props"的属性,然后在template内部就可以使用props.msg来访问子组件传递过来的数据了。(注意到这里的scope="props"中的props只是一个临时变量,可以为任意名字)
(四)访问slot
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset=utf-8>
5 <title>Test page</title>
6 <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
7 </head>
8 <body>
9 <div id="app">
10 <child-component>
11 <h2 slot="header">标题</h2>
12 <p>分发的内容</p>
13 <p>更多分发的内容</p>
14 <div slot="footer">底部信息</div>
15 </child-component>
16 </div>
17 <script>
18 var myTemplateContent = {
19 template : '\
20 <div class="container">\
21 <div class="header">\
22 <slot name="header"></slot>\
23 </div>\
24 <div class="main">\
25 <slot></slot>\
26 </div>\
27 <div class="footer">\
28 <slot name="footer"></slot>\
29 </div>\
30 </div>',
31 mounted : function(){
32 var header = this.$slots.header;
33 var main = this.$slots.default;
34 var footer = this.$slots.footer;
35 console.log({
36 header,
37 main,
38 footer
39 })
40 }
41 };
42 new Vue({
43 el : '#app',
44 components : {
45 'child-component' : this.myTemplateContent
46 }
47 })
48 </script>
49 </body>
50 </html>
来源:https://www.cnblogs.com/zheng-hong-bo/p/12263133.html
