组件

  组件时可复用的Vue实例,且带有一个名字,把组件当成自定义元素使用。

// 定义一个名为 button-counter 的新组件
Vue.component('button-counter', {
  data: function () {
    return {
      count: 0
    }
  },
  template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})

  data:必须是一个函数,因此每一个实例可以维护一份被返回的对象的独立的拷贝。

  若不是独立的则会出现,所有的实例都是统一的。

data: function () {
  return {
    count: 0
  }
}

 

注册全局组件: 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="d1">
        <alert></alert>
    </div>
    <hr>
    <div id="d2">
        <alert></alert>
    </div>
</body>
<script src="vue.js"></script>
<script>
    <!--注意全局时,一定是component,局部是才是components-->
    //且方法要写在全局中,这样才都能调用。
    Vue.component("alert",{
        template:`<button v-on:click="ttt">弹弹{{count}}</button>`,
        // 这个里面的data后面跟的类型必须是一个方法,且return的必须是一个对象
        data:function () {
            return {
                count:0
            }
        },
        methods:{
            ttt:function () {
                this.count += 1
            }
        }
    });
    var app = new Vue({
        el:"#d1",
        data:{},
    });
    var app2 = new Vue({
        el:"#d2",
        data:{},
    })
</script>
</html>

 

注册局部组件:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>$Title$</title>
</head>
<body>
    <div id="d1">
        <alert></alert>
    </div>
    <hr>
<div id="d2">
    <!--<alert></alert>-->
</div>
</body>
<script src="vue.js"></script>
<script>
    <!--在外部定义一个变量-->
    var alertcomponent = {
        template:`<button v-on:click="ttt">{{count}}</button>`,
        data:function(){
          return {
              count:0
          }
        },
        methods:{
            ttt:function () {
                this.count += 1
            }
        }
    };
    
    var app = new Vue({
        el:"#d1",
        data:{},
        
        // components:{ alert:{
        //     template:`<button v-on:click="ttt">弹出{{count}}</button>`,
        //     data:function(){
        //         return {
        //             count:0
        //         }
        //     },
        
        // methods:{
        //     ttt:function () {
        //         this.count += 1
        //     }
        // }
        
        // 在内部接收这个alertcomponent变量,局部使用components,上面注释的在直接在内部使用的
        //没在外部定义alertcomponent变量。
        components:{
            alert:alertcomponent
        },
        
    });
    var app2 = new Vue({
        el:"#d2",
        data:{},
    })
</script>
</html>

 

通过Prop向子组件传递数据:

  Prop 是你可以在组件上注册的一些自定义特性。当一个值传递给一个 prop 特性的时候,它就变成了那个组件实例的一个属性。为了给博文组件传递一个标题,我们可以用一个 props 选项将其包含在该组件可接受的 prop 列表中:

Vue.component('blog-post', {
  props: ['title'],
  template: '<h3>{{ title }}</h3>'
})

  一个组件默认可以拥有任意数量的 prop,任何值都可以传递给任何 prop。在上述模板中,你会发现我们能够在组件实例中访问这个值,就像访问 data 中的值一样。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="d1">
        <!--利用v-bind绑定name属性。-->
        <alert v-for="item in list" v-bind:name="item"></alert>
    </div>
</body>
<script src="vue.js"></script>
<script>
    var alertcomponent = {
        template:`<button v-on:click = "ttt">{{name}}{{count}}</button>>`,
        //props 中是声明的传的参数,以及参数的类型。
        props:{
            name:String
        },
        data:function () {
            return {
                count:0
            }
        },
        methods:{
            ttt:function(){
                this.count += 1
            }
        }
    }
    var app = new Vue({
        el:"#d1",
        data:{
            list:[
                "1号",
                "2号",
                "3号",
            ]
        },
        components:{
            alert:alertcomponent
        },
    })
</script>
</html>

 

 

通过事件,子组件向父级组件发送消息:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="d1">
        <p>总点击数:{{totalCount}}</p>
        <!--监听事件,在全局中设置方法,每次触发都让变量数值变化-->
        <alert v-for="item in list" v-bind:name="item" v-on:chufa="add"></alert>
    </div>
</body>
<script src="vue.js"></script>
<script>
    var alertcomponent = {
        template:`<button v-on:click="ttt">{{name}}{{count}}</button>`,
        props:{
          name:String
        },
        data:function () {
            return {
                count:0
            }
        },
        methods:{
            ttt:function(){
                this.count += 1;
                //在此时要触发事件,告诉外部,内部已经有了数值变动
                this.$emit("chufa")
            }
        },
    }
    var app = new Vue({
        el:"#d1",
        data:{
            totalCount:0,
            list:[
            "1号",
            "2号",
            "3号",
        ]
        },
        components:{
            alert:alertcomponent
        },
        methods:{
          add:function () {
              this.totalCount += 1;
          }
        },
    })
</script>
</html>

 

插槽:

  如果我们向一个组件传递内容,如果直接在组件标签中放数据,则会报错,或者不会显示在页面上,所以我们需要Vue自定义的<slot>元素。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="d1">
        <p>总点击数:{{totalCount}}</p>
        <!--监听事件,在全局中设置方法,每次触发都让变量数值变化-->
        <alert v-for="item in list" v-bind:name="item" v-on:chufa="add">
            <span slot="keng1">你好</span>
            //在标签里属性写上slot="名字",就是指定占哪个位置。
            <span slot="keng2">世界</span>
        </alert>
    </div>
</body>
<script src="vue.js"></script>
<script>
    var alertcomponent = {
        template:`<div>
                        <button v-on:click="ttt">{{name}}{{count}}</button>
                        <slot name="keng1"></slot>
                        //给插槽取名字,后面站位的时候可以选择插槽占
                        <slot name="keng2"></slot>
                   </div>`,
        props:{
          name:String
        },
        data:function () {
            return {
                count:0
            }
        },
        methods:{
            ttt:function(){
                this.count += 1;
                //在此时要触发事件,告诉外部,内部已经有了数值变动
                this.$emit("chufa")
            }
        },
    }
    var app = new Vue({
        el:"#d1",
        data:{
            totalCount:0,
            list:[
            "1号",
            "2号",
            "3号",
        ]
        },
        components:{
            alert:alertcomponent
        },
        methods:{
          add:function () {
              this.totalCount += 1;
          }
        },
    })
</script>
</html>

组件注意事项:

  

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="d1">
        <table>
            <qingqiu></qingqiu>   // 若是有固定搭配的组件,则不能将组件直接放入,
            // 这样会使组件“跑到”外部,
            <tr is="qingqiu"></tr>  // 正确的放置方法:应该使用   is = 组件名,
            // 这样才会正确的显示信息,
            <!--注意:固定搭配的例如 : ul 和 li ,select 和 option ,table 和 tr-->
        </table>
    </div>
    <script src="vue.js"></script>
    <script>
        var app = new Vue({
            el:"#d1",
            data:{},
            components:{
                qingqiu:{
                    template:`<tr>tr标签</tr>>`
                }
            }
        })
    </script>
</body>
</html>

 

子组件触发原生事件:

  

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="d1">
        <alert v-on:click.native="waibu"></alert>
        <!--若是向从子组件直接触发原生事件,则需要写成 原生事件.native  这样方可触发-->
        <alert2 v-on:click_in="waibu"></alert2>
        <!--第二种方法则是通过子组件向父组件传输参数的原理:
            先触发子组件自定义的内部方法,然后通过 $emit("自定义事件名"),
            再触发外部方法。
        -->
    </div>
    <script src="vue.js"></script>
    <script>
        var app = new Vue({
            el:"#d1",
            data:{},
            components:{
                alert:{
                    template:`<button>子组件点击事件</button>`,
                },
                alert2:{
                    template:`<button v-on:click="run">子组件点击事件2</button>`,
                    methods:{
                        run:function(){
                            alert("先触发了内部的自定义方法")
                            this.$emit("click_in")
                        }
                    }
                }
            },
            methods:{
                waibu:function () {
                    alert("触发了外部")
                }
            }
        })
    </script>
</body>
</html>

 

组件之间的传值:

  需要一个中转站类的对象,来传输组件之间要传递的信息。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="d1">
        <alert1></alert1>
        <hr>
        <alert2></alert2>
    </div>
    <script src="vue.js"></script>
    <script>
        var bus = new Vue();
        //bus的作用用来中转信息
        var app = new Vue({
            el:"#d1",
            data:{

            },
            components:{
                alert1:{
                    template:`<button v-on:click="shijian1">组件1</button>`,
                    methods:{
                        shijian1:function(){
                            bus.$emit("shijian2")
                            //抛出shijian2 事件,bus实时监听
                        },
                    }
                },
                alert2:{
                    template:'<div>{{num}}</div>',
                    data:function () {
                        return {
                            num:0,
                        }
                    },
                    mounted:function () {
                        //在这个作用域中,this指的是alert2组件实例
                        console.log(this.num)
                        var _this = this;
                        // el 被挂载之后bus就监听事件
                        bus.$on("shijian2",function(){
                            //在这个作用域中,this指的是bus
                            console.log(this.num) // 这一步打印的是undefined
                            alert("事件2")
                            //修改alert2组件中的num值
                            _this.num += 1; // 这一步不能写this因为这一步的this指的是bus,并没有num属性。
                        })
                    }
                }
            }
        })
    </script>
</body>
</html>

 

posted @ 2018-07-25 18:46  Qingqiu_Gu  阅读(186)  评论(0编辑  收藏  举报