首页 > 其他 > 详细

Vue组件基础用法

时间:2020-02-16 18:04:15      阅读:86      评论:0      收藏:0      [点我收藏+]

一:组件的基本用法

组件和创建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>
→ 组件自定义标签名使用全小写加-符号的格式(如上例中的my-component)
→ 组件template中的DOM结构必须仅被一个元素包围,例如上面的template : ‘<div>这是组件中的内容</div>‘如果写成template : ‘这是组件中的内容‘或者写成template : ‘<div>这是组件中的内容</div><div>这是组件另一个的内容</div>会无法渲染或者渲染不全。
→ 自定义的组件标签在有些时候使用会受到限制,例如:如果直接在<table>标签中使用<my-component>标签是无效的,解决方法是使用is属性来挂载组件:
<div id="app">
    <table>
        <tbody is=‘my-component‘></tbody>
    </table>
</div>
 二:组件的选项
组件和Vue实例一样,也可以有data,computed,methods选项,与Vue实例不同的是,data选项必须是一个函数,且将数据return出去(至于为什么要这样做,是因为组件是可以复用的,每个组件实例的数据应该互相独立互不影响,使用return返回一个数据对象可以保证每个组件的实例的数据都是独立的)。
<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>
View Code

在上述示例中,<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>
View Code

 上述代码示例中,当在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>
View Code
五:非父子组件之间的通信——中央事件总线bus
在Vue.js 1.x版本中,使用$dispath()和$broadcast()两个方法来向上级或者下级派发广播事件,这两种方法发出的事件,任何组件都是可以接收到且根据就近原则,事件会在第一次被接收到后停止冒泡,除非处理事件的方法又再一次返回true。
在Vue.js 2.x版本中,使用一个空的Vue对象作为中央事件总线,从而实现了任何组件之间的通信,包括父子组件、兄弟组件、跨级别组件,示例代码:
技术分享图片
 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>
View Code
上面的代码,首先创建一个名为bus的空Vue实例,然后定义组件my-component,这个组件中有个按钮,按钮会触发bus组件的on-message方法,在app初始化mounted阶段监听bus的on-message事件,并在回调中完成自己的业务逻辑。
除了使用中央事件总线,还可以使用父链或者子组件索引两种方式来完成组件通信。

六:组件之间的通信——父链和子组件索引

在子组件中,可以使用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>
View Code
建议的做法,父子组件之间还是使用props和emit来传递数据,子组件应避免直接修改父组件的数据。
在父组件中,如果通过使用this.$children得到子组件,然后通过遍历获取所需要的子组件是比较困难的,可以使用ref属性来为子组件指定索引名称,这样可以通过this.$refs.myRef来指定访问myRef这个子组件。
技术分享图片
 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>
View Code

$refs只在组件渲染完成后填充,并不是响应式的,应避免在模板和计算属性中使用$refs。

七:使用slot插槽分发内容
  任何一个复杂的Vue组件都是由props传递数据、events触发事件和slot内容分发这三个部分构成的。当需要组合使用不同的组件,混合父组件的内容和子组件的模板时,就需要使用slot,这个过程叫内容分发。
  关于父子组件的作用域:父组件模板的内容在父组件作用域中编译,子组件模板的内容在子组件作用域中编译。
  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>
View Code

(一)单个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>
View Code
(二)具名插槽的用法
给slot指定name属性可以分发多个内容:
技术分享图片
 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>
View Code
(三)作用域插槽的用法
作用域插槽使用一个(可复用的)模板来代替已渲染的元素,示例:
技术分享图片
 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>
View Code

子组件的模板中,<slot msg="来自子组件的内容"></slot>向插槽传递了一个msg,父组件使用了template元素,且有一个scope="props"的属性,然后在template内部就可以使用props.msg来访问子组件传递过来的数据了。(注意到这里的scope="props"中的props只是一个临时变量,可以为任意名字)

(四)访问slot
在Vue.js 2.x中,可以使用$slots来访问被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>
View Code

 

Vue组件基础用法

原文:https://www.cnblogs.com/zheng-hong-bo/p/12263133.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!