vue.js基础知识篇:组件详解

Posted 陈蒙的技术空间

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue.js基础知识篇:组件详解相关的知识,希望对你有一定的参考价值。

第11章:组件详解

 组件是Vue.js最推崇也最强大的功能之一,核心目标是可重用性。

我们把组件代码按照template、style、script的拆分方式,放置到对应的.vue文件中。

1.注册

Vue.js的组件注册分为全局注册和局部注册。

全局注册使用Vue.component方法。第一个参数是组件名字,第二个参数是组件的构造函数,要么是function,要么是object。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
      <div id="app">
          <didi-component></didi-component>
          <en-component></en-component>
      </div>
      <script src="js/vue.js"></script>
      <script>
          //第二个参数传入object的情况
          Vue.component("didi-component",{
              template:"<div>A custom component!</div>"
          });
          //第二个参数传入function的情况,它是一个组件构造器
          var ENcomponent=Vue.extend({
              template:"<div>A 2rd components</div>"
          });
          //注册
          Vue.component("en-component",ENcomponent);
          //创建根实例
          new Vue({
              el:"#app"
          })
      </script>
</body>
</html>

显示效果

 

局部注册,以vue实例选项components或者组件构造器即Vue.extend函数的components选项。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <didi-component></didi-component>
</div>
<script src="js/vue.js"></script>
<script>
    var Parent=Vue.extend({
        template:"<p>这里是父组件的内容</p><br/><child></child>",
        components:{
            "child":{
                template:"<div>我是子组件的内容</div>"
            }
        }
    })
    new Vue({
        el:"#app",
        components:{
            "didi-component":Parent
        }
    })
</script>
</body>
</html>

显示效果

2.数据传递

组件作为一个app(项目)的组成部分,总是要涉及到组件通信。组件通信属于数据传递的范畴,数据传递一共有3种方式:

props、组件通信、slot。

(1)props属性

首先区别一下props和data和propsData。props作用于父子组件之间的数据传递,data组件或者vue实例化时经常使用,propsData用来在组件初始化后覆盖props中的属性。接下来是如何使用props属性。

第一种方式,字面量语法

直接在组件的html代码中传入普通的字符串,在组件内部使用props属性。注意:html不区分大小写,名字为camelCase的属性会转化为短横线隔开(kebab-case)。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
     <hello-component msg="hello"></hello-component>
    <vivian my-data="3.1415"></vivian>
</div>
<script src="js/vue.js"></script>
<script>
    Vue.component("hello-component",{
        props:["msg"],
        template:"<span>{{msg}},front-end!</span>"
    });
    Vue.component("vivian",{
        props:["myData"],
        template:"<div>{{myData}}</div>",
        replace:true
    })
    new Vue({
        el:"#app"
    })
</script>
</body>
</html>

第二种,动态语法

下面的例子从父组件向子组件传递属性,每当父组件的数据变化时,该变化也会传导给子组件。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="app">
        <vivi-props></vivi-props>
    </div>
    <script src="js/vue.js"></script>
    <script>
        var Child=Vue.extend({
            props:["viviProps"],
            //传给子组件的属性名称
            template:"<div>{{viviProps}}</div>",
            //既然在props属性上定义了,那么就可以在模板里使用了
            replace:true
        });
        var Parent=Vue.extend({
            template:"<p>我是父组件的内容</p><br/><child :vivi-props=\'hello\'></child>",
            data:function(){
              return {"hello":"hello"}
            },
            //动态绑定的属性的值由父组件的data来定义
            components:{
                "child":Child
            }
        })
        new Vue({
            el:"#app",
            components:{
                "vivi-props":Parent
            }
        });
    </script>
</body>
</html>

第三种方式,使用.sync和.once修饰符。

默认或者使用.once修饰符是父组件到子组件的单向绑定。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="app">
        <input type="text" v-model="info.name"/>
        <child v-bind:msg.once="info"></child>
        <!--把根实例的info数据属性传递给子组件child的msg属性-->
    </div>
    <script src="js/vue.js"></script>
    <script>
        new Vue({
            el:"#app",
            data:{
                info:{
                    name:"顺风车"
                }
            },
            components:{
                "child":{
                    props:["msg"],
                    template:"<div>{{msg.name}}</div>"
                }
            }
        })
    </script>
</body>
</html>

.sync修饰符能做到双向绑定。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    父组件:
    <input v-model="val"><br/>
    子组件:
    <test :test.sync="val"></test>
</div>
<script src="js/vue.js"></script>
<script>
    var vm = new Vue({
        el: \'#app\',
        data: {
            val: 1
        },
        components: {
            "test": {
                props: [\'test\'],
                template: "<input v-model=\'test\'/>"
            }
        }
    });
</script>
</body>
</html>

显示结果

第4种方式,prop验证。

 我们把自己的组件给别人使用,那么要求使用者能够根据prop提供的对象正确使用。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    父组件:
    <input v-model="val"><br/>
    子组件:
    <test :test="val"></test>
</div>
<script src="js/vue.js"></script>
<script>
    var vm = new Vue({
        el: \'#app\',
        data: {
            val: 1
        },
        components:{
            test:{
                props: {
                    test: {
                        twoWay: true
                    }
                    //我们希望组件的使用者通过双向绑定来使用这个组件。
                },
                //把根实例的val属性传递给test属性。
                template: "<input v-model=\'test\'/>"
            }
        }
    });
</script>
</body>
</html>

我们看到这个代码 <test :test="val"></test> 会抛出错误如下:

那么正确的使用应该是如下,加上.sync修饰词,以满足twoWay:true的要求。

第5种方式,prop转换函数,coerce函数。可以理解为prop属性值的过滤器。

(2)组件通信

尽管this.$parent和this.$children(属性)可以访问父/子组件的数据,根实例的后代可以通过this.$root访问根实例,但这种方式应该尽量避免。

首先,因为父子组件紧密的耦合,只看父组件却很难理解父组件的状态,因为它能被任意的修改。再次,子组件要使用父组件的数据,应当避免直接依赖,尽量显式的使用props属性。

我们的方案是通过作用域传递事件。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
   <template id="child-template">
       <input v-model="msg">
       <button v-on:click="notify">Dispatch Event</button>
       <!--子组件绑定了notify函数-->
   </template>
    <div id="events-example">
        <p>Message:{{messages|json}}</p>
        <child></child>
    </div>
</div>
<script src="js/vue.js"></script>
<script>
    Vue.component("child",{
        template:"#child-template",
        data:function(){
            return {msg:"hello"}
        },
        methods:{
            notify:function(){
                if(this.msg.trim()){
                    this.$dispatch("child-msg",this.msg);
                    this.msg="";
                }
                //notify函数的功能是把msg属性的值dispatch到child-msg事件上,它会沿着父作用域的链冒泡
            }
        }
    });
    var parent=new Vue({
        el:"#events-example",
        data:{
            messages:[]
        },
        events:{
            "child-msg":function(msg){
                this.messages.push(msg);
            }
            //接收到child-msg事件后,那么执行push方法
        }
    })
    var vm = new Vue({
        el: \'#app\'
    });
</script>
</body>
</html>

接下来是在子组件v-on监听,更加简洁的代码。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app"Vue 基础篇二

vue.js基础知识篇:指令详解

vue.js之组件篇

vue基础篇---vue组件《2》

包学会之浅入浅出Vue.js:结业篇

包学会之浅入浅出Vue.js:结业篇