组件时可复用的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>