Vue2中组件与组件通讯

161 阅读3分钟

组件

组件:组成页面一部分的部件比如:导航条、轮播、侧边栏、底部、抽屉...

  • 为什么组件化:

vue强烈推荐组件化思想:扩展HTML元素(自定义标签),封装可以【重用】的代码(可以把html+css+js封装在一起)

组件的创建/注册方式:

全局/局部组件

		//全局组件
		Vue.component("全局组件名",{
			template:"<div css/js>内容
					<局部组件名></局部组件名>
				</div>", - html模板
			data(){return {}},
			methods:{},
			...//之前的模板语法都是支持的,但是data必须写为函数时写法,vue3的语法
			components:{//局部组件
				"局部组件名":{
					套娃
				}
			}
                 })
                 //以前这个new Vue({})我们可以看作是一个根组件

使用:在HTML直接写双标签,你的组件名就是标签名:<全局组件名></全局组件名>

注意:

1、起名字,如果js写驼峰,html不支持,必须替换写为横线连接符-

2、html片段,没有代码提示,没有高亮显示,但是不担心 - 以后vue单文件组件解决

3、css只能写成内联样式 - 以后vue单文件组件解决

4、template只能包含一个根节点

5、组件是一座孤岛,无法直接访问外面的组件的状态和方法 - 需要使用间接的组件通信才可以解决

6、data必须写为函数时写法,vue3的语法

7、所有的组件都放在一起的话,太乱了太丑了 - 以后vue单文件组件解决

何时使用全局或局部:

1、如果一个组件只会使用过一次推荐定义为局部

2、如果一个组件在不同的页面或者各个组件中都会使用到,推荐全局

组件通信

父传子:提升组件的复用性

比如:一个网页上任何一个页面都有一个导航条,但是显示效果可能不同,我们也可以实现一个组件,传入不同的参数进行通信

                <div id="box">
			<paoge-navbar></paoge-navbar>
			<paoge-navbar 自定义属性="值/根组件的变量"></paoge-navbar>  
                        //自定义属性要来进行传参
		</div>

		Vue.component("paogeNavbar",{
				template:`<div style="background:red;">
					<button v-show="bool"><</button>
					<span>{{自定义属性}}</span>
					<button>></button>
				</div>`,
				//props:["自定义属性",...],//第一种写法 数组语法糖
				props:{//第2种写法 对象语法糖
					自定义属性:{
						type:String/Number/Boolean,
						default:"默认值,不传自定义属性的时候使用的"
					}
				},
		}

子传父:但是封装了组件后,完成开关门

		<div id="box">
			<navbar @自定义事件名="爸爸的函数名"></navbar>
		</div>

		Vue.component("navbar",{
			template:`
				<div style="background: red;">
					<button @click="change">三</button>
					导航条				
				</div>`
			,
			methods:{
				change(){
					this.$emit("自定义事件名",this.data);
				}
			}
		})

		//一个页面只能有一个这个【根组件】
		new Vue({
			el:"#box",
			data:{
				bool:true,
			},
			methods:{
				爸爸的函数名(data){
					console.log("父组件定义的事件,操作");
				}
			}
		})	

总结:

父传子 - 用自定义属性搭配props

子传父 - 用自定义事件搭配this.$emit("自定义事件名")

非父子关系通信bus

bus:中央事件总线,实现较为复杂的通信

创建:var bus=new Vue();

方法:2个:使用前,考虑清楚谁是发布者,谁是订阅者,订阅者需要使用生命周期mounted来触发 - dom渲染完毕后

1、订阅者:

                bus.$on("自定义名称",(data)=>{
			data->下方发布者传输的数据
		})

2、发布者:

                 bus.$emit("自定义名称",传输的数据);

refs:父组件可以随意的摆弄子组件(获取/修改)

ref - 绑定在dom节点上,拿到的就是这个dom对象

ref - 绑定在组件上,拿到的就是当前组件对象

<组件 ref="自定义名称"></组件>

根组件中:

this.$refs - 得到所有添加了ref属性的组件对象

this.$refs.自定义名称 - 拿到某个子组件对象

this.$refs.自定义名称.变量 - 拿到某个子组件对象上的变量

组件注意:

1、ref和refs是固定关键字,不能修改

2、他打破了传统的通信流程,比如我们想要获取一个input的value值,再vue中可以用v-model,确实很棒,但是react中没有,则可以使用ref完成

3、尽量不要使用组件中的props去改变状态data,会导致数据流混乱(不易读) - 不推荐,也没有意义

4、如果组件中写了一个指令v-once,一次性的,状态改变,页面上的组件也不会变化,只需要打开页面渲染一次时

内置组件:

                <component :is="组件名"></component>
                <!-- 告诉他哪个需要显示 -->
		<keep-alive></keep-alive>
                <!-- 活着,就算选项卡切换,回来依然存在你输入的东西 -->
                <keep-alive>
                 <component :is="组件名"></component>
                </keep-alive>

以上包含了组建的通信,都要一个给,一个拿

面试题:Vue组件的通信有哪些方式?

1、父传子 - 用props自定义

2、子传父 - 用this.$emit("自定义事件")

3、兄弟:中间人模式

4、bus

5、refs

6、vuex - 状态管理器,最舒服,Vue由三部分组成:vue基础+vue router+vuex

slot:插槽

组件标签中默认是不允许再嵌套别的标签的,所有提供了slot扩展组件能力,提高了组件的复用性 比如:

                <组件>
			<template v-slot:名字>
				<span>111111111</span>
				<span>222222222</span>
				<span>333333333</span>
			<template>
			<template>
				<span>777777777</span>
				<span>888888888</span>
				<span>999999999</span>
			<template>
			<span slot="user">个人中心</span>
			<span>111111111</span>
			<span>222222222</span>
			<span>333333333</span>
			<span>777777777</span>
			<span>888888888</span>
			<span>999999999</span>
		</组件>

默认是不允许再嵌套别的标签的,但是搭配上slot就可以了,以下代码教你如何搭配

           Vue.component("组件",{
			template:`
				<div>
					<slot name="user"></slot> 
                                        //用上你写的<span slot="user">个人中心</span>
					<slot></slot>
                                        //用上所有没有名字的slot
				</div>
			`
            })