Vue组件以及组件之间的通信
一、组件的注册
1、 全局组件注册
1. 注册基本语法Vue.component
Vue.component("my_header", { template: `<div><h1>{{title}}</h1></div>`, data() { return { title: "这是头部" } } });
2. 第一个参数"my_header":组件名称
3. 第二个参数{}:配置信息
4. 配置信息里面必须要有template,它的值是这个组件的html代码
5. 还可以有data、methods等参数,不同的是data不是对象了,而是函数,return返回的值,在template中可以获取并使用
函数详写是 data:function(){}; ES6中可以直接简写 data(){return },其他函数一样可以简写省略 :function
6. Vue里面有的参数,组件里面多数也有,但是有一些参数是组件不能有的,比如el参数,所有组件都是Vue可复用的实例
7. 全局组件,所有app都可以使用
8. demo
<body> <div id="app"> <my_header></my_header> </div> <hr> <div id="app2"> <my_header></my_header> </div> <script> Vue.component("my_header", { template: `<div><h1>{{title}}</h1></div>`, data() { return { title: "这是头部" } } }); const app = new Vue({ el: "#app", }); const app2 = new Vue({ el: "#app2" }) </script> </body>
2、局部组件注册
1. 在某个app下注册组件,其他app不能使用
2. 基本语句:某个app内使用参数components: {组件名称1: 配置信息1, 组件名称2: 配置信息2}
3. demo
<body> <div id="app"> <my_com></my_com> <my_com></my_com> </div> <script> // 组件配置信息(对象) let my_com_config = { template: `<div><h1>这是局部组件</h1></div>` }; const app = new Vue({ el: "#app", components: { // 组件名称: 配置信息 my_com: my_com_config } }); </script> </body>
3、子组件的注册
1. 在某个组件内,也可以使用components使用另一个组件
2. 子组件需要这个组件的template代码内使用
3. demo
<body> <div id="app"> <my_com></my_com> </div> <script> let child_config = { template: `<div><h2>我是子组件</h2></div>` }; let my_com_config = { // 在组件的代码里面引用它的子组件 template: `<div> <h1>这是一个组件</h1> <child></child> </div>`, // 在某个组件内部也可以定义的它的子组件 components: { child: child_config } }; const app = new Vue({ el: "#app", components: { my_com: my_com_config } }) </script> </body>
二、组件之间的通信
1、父子组件之间的通信
1. 在父组件的配置信息template中引用子组件,给子组件设置一个属性,值是父组件data的值
2. 在子组件中配置一个props参数(数组),里面是那个属性名
3. 然后在子组件的template代码中就可以直接使用这个属性获取到父组件传过来的值
4. demo
<body> <div id="app"> <my_com></my_com> </div> <script> let child_config = { template: `<div> <h2>我是子组件</h2> <p>父亲对我说:{{father_say}}</p> </div>`, props: ["father_say"] }; let my_com_config = { template: `<div> <h1>这是一个组件</h1> <child :father_say="f_say"></child> </div>`, components: { child: child_config }, data(){ return { f_say: "好好学习" } } }; const app = new Vue({ el: "#app", components: { my_com: my_com_config } }) </script> </body>
2、子父组件之间的通信
1. 子组件向父组件传数据,需要提交一个事件
2. 在一个事件中通过this.$emit("事件名称", "要传的值")提交另一个事件给父亲
3. 在父组件中绑定子组件提交过来的事件,创建一个方法处理这个事件
4. data函数接收子组件提交过来的数据
5. demo
<body> <div id="app"> <my_com></my_com> </div> <script> let child_config = { // 设置一个click事件,通过click事件向父亲提交一个事件son_say和数据 template: `<div> <h2>我是一个子组件</h2> <button @click="my_click">点击向父亲说话</button> </div>`, methods: { my_click() { // 向父亲说话 // 子组件提交事件 this.$emit("son_say", "我会好好学习的") } } }; let my_com_config = { // 父组件接收子组件提交的事件son_say,并给这个事件设置一个处理方法my_son_say // 处理后的数据就可以使用了{{say}} template: `<div> <h1>这是一个组件</h1> <child @son_say="my_son_say"></child> <p>儿子跟我说:{{say}}</p> </div> `, components:{ child: child_config }, data(){ return { say: "" } }, // 接收子组件传来的数据data,并赋值给say,在代码中展示出来 methods: { my_son_say: function (data) { this.say = data } } }; const app = new Vue({ el: "#app", components: { my_com: my_com_config } }) </script> </body>
3、非父子组件之间的通信
1. 定义一个Vue实例作为两个组件之间通信的桥梁
2. 其中一个组件向中间调度器提交事件:Event.$emit("事件名称", data)
3. 另一个组件要监听中间调度器里的事件:Event.$on("事件的名称", function(data){
4. 注意this的问题:函数里面的this是最近的调用者,外面的this才是这个组件
5. demo
<body> <div id="app"> <ming></ming> <hong></hong> </div> <script> // 这个Vue实例不用传数据,只是用于两个组件之间通信的桥梁 // 一个组件给这个实例提交事件,另一个组件在这个实例里监听这个事件 let other = new Vue(); let ming_config = { template: `<div> <h1>我是明哥</h1> <button @click="my_click">给小红打电话</button> </div>`, methods: { my_click: function() { // 给小红打电话,说晚上等我,一起嗨 // 两个组件之间没有关系(不是父子),需要通过一个Vue对象进行通信 // 给other对象提交事件 other.$emit("call", "晚上等我,一起嗨") } } }; let hong_config = { template: `<div> <h1>我是红姐</h1> <p>明哥勇猛地跟涐说:{{ming_say}}</p> </div>`, data(){ return { ming_say: "" } }, // 钩子方法,组件加载完成后会执行这个方法 mounted(){ // 和$emit是一对的,$emit是提交事件,$on是监听$emit提交的事件 // 第一个参数是监听的事件名称,第二个参数是监听到后要执行的回调函数 let that = this; // 这个this是hong这个组件 other.$on("call", function(data){ // data是ming传过来的数据,里面的this是other的 that.ming_say = data; }) } }; const app = new Vue({ el: "#app", components: { ming: ming_config, hong: hong_config } }) </script> </body>
三、混合和插槽
1、混合
1. 当两个组件复用共用的代码块时
2. 定义公共的代码块
3. 复用语法:mixins: [变量名]
4. demo
<body> <div id="app"> <com1></com1> <com2></com2> </div> <script> // 定义公用代码 let base = { data() { return { is_show: false } }, methods: { show_text: function(){ this.is_show = true; }, hide_text(){ this.is_show = false; } } }; let com1 = { template: `<div> <button @click="show_text">点击显示文本</button> <button @click="hide_text">点击隐藏文本</button> <div v-show="is_show">威猛的明哥出现了</div> </div>`, // 继承公用代码 mixins: [base], // 还可以修改继承过来的代码 data(){ return { is_show: true } } }; let com2 = { template: `<div> <button v-on="{mouseenter: show_text, mouseleave: hide_text}">鼠标移入显示文本,移出隐藏</button> <div v-show="is_show">威猛的明哥出现了</div> </div>`, // 继承代码 mixins: [base] }; const app = new Vue({ el: "#app", components: { com1: com1, com2: com2, } }) </script> </body>
2、 插槽
1. 把组件的template定义在html里面
2. 在script中通过id找到这段template
3. template代码内定义slot插槽,并使用name属性区分不同的插槽信息
4. 使用组件的时候通过slot,可以给组件添加上不同的内容
5. 生成的组件代码中不会有template标签
6. demo
<body> <div id="app"> <com> <h3 slot="title">Python</h3> <p slot="brief">从入门到精通</p> </com> <com> <h3 slot="title">Mysql</h3> <p slot="brief">从删库到跑路</p> </com> </div> <!--组件的template还可以单独写出来--> <template id="my_com"> <div> <h1>这是一个组件</h1> <!--用slot定义插槽--> <slot name="title"></slot> <slot name="brief"></slot> <hr> </div> </template> <script> let com = { // 找到template模板 template: "#my_com" }; const app = new Vue({ el: "#app", components: { com: com } }) </script> </body>