Vue之组件传值 provide-inject 非响应式,组件传值 provide-inject 响应式,自定义事件,动态组件,缓存组件,异步组件

本文介绍了Vue中组件间通信的各种方式,包括使用provide/inject实现非响应式和响应式传值,自定义事件的触发与监听,动态组件的切换以及如何保持组件状态。此外,还探讨了动态组件的缓存策略,利用keep-alive避免组件重复创建。最后,提到了异步组件的加载,如何实现懒加载并处理加载状态。这些技术对于优化Vue应用性能和提升用户体验至关重要。
摘要由CSDN通过智能技术生成

组件传值 provide-inject 非响应式

通常情况下,组件向组件传递数据,可以采用父子props层层传递,也可以使用busVuex直接交互

在Vue2.2.0之后,Vue还提供了provide/inject选项

但是不建议在应用中直接使用该办法,因为怕"管不好",如果管理不好后续做业务会很麻烦

App.vue

<template>
  <div>
    <Box1></Box1>
    <button @click="change">change1</button>
	<br>
    <div>
		<br>
      {{ msg }}
    </div>
  </div>
</template>

<script>
import Box1 from "./Box1.vue";
export default {
  data() {
    return {
      msg: "app组件提供的数据",
    };
  },
  provide: function () {
    return { msg: this.msg };
  },
  methods: {
    // msg里面的数据改了也没有效果,Box里面接收的数据不会改变
    change() {
      this.msg = "6666";
    },
  },
  components: {
    Box1,
  },
  mounted() {
    console.log(this.msg, 111111111111);
  },
};
</script>

Box.vue

<template>
	<div>
		<p>box1---{{msg}}</p>
	</div>
</template>

<script>
	export default {
		inject:["msg"],
		// 即可以接收数据也可以传递数据
		provide:{n:10}
	}
</script>

<style>
</style>

在这里插入图片描述
在这里插入图片描述

组件传值 provide-inject 响应式

App.vue

<template>
	<div>
		<Box1></Box1>
		<button @click="change">change</button>
		{{msg}}
	</div>
	
</template>

<script>
	import Box1 from "./Box1.vue"
	export default {
		data() {
			return {
				msg:"app组件提供的数据"
			}
		},
		provide:function(){
			// 将这里改了即可
			return {msg:()=>this.msg}
		},
		methods:{
			change(){
				this.msg="6666"
			}
		},
		components:{
			Box1
		},
		mounted() {
			console.log(this.msg,111111111111)
		}
	}
</script>

Box.vue

<template>
	<div>
		<p>box1---{{msg()}}</p>
	</div>
</template>

<script>
	export default {
		inject:["msg"],
	}
</script>

<style>
</style>

在这里插入图片描述
在这里插入图片描述

自定义事件

Vue提供的技术:继承Vue的组件有三个功能

  1. 触发x组件的a事件: x.$emit(“a事件”,参数…)
  2. 给x组件绑定a事件 x.$on(“a事件”,监听器函数)
  3. 给x组件解绑a事件 x.$off(“a事件”,监听器函数)

App.vue

<template>
	<div>
		<button @click="fn1">点击给app组件绑定一个a事件</button>
		<br>
		<button @click="fn2">触发自定义a事件</button>
	</div>
</template>

<script>
	export default {
		methods:{
			fn1(){
				this.$on("a",function(arg1,arg2){
					console.log("我自己设计的事件触发了 a",arg1)
				})
			},
			fn2(){
				this.$emit("a",100)
			}
		}
	}
</script>

fn1绑定一个a事件,事件触发就会打印数据,而事件触发的条件是fn2函数的调用,所以当点击 触发自定义a事件 时就触发了a事件,从而打印 我自己设计的事件触发了 a 100

中央传值

通过创建一个新的vm对象,专门统一注册事件,供所有组件共同操作,达到所有组件随意隔代传值的效果

App.vue

<template>
	<div>
		<Box1></Box1>
	</div>
</template>

<script>
	import Box1 from "./Box1.vue"
	export default {
		methods:{
			
		},
		components:{
			Box1
		}
	}
</script>

<style>
</style>


Box.vue

<template>
	<div>
		<h1>box3</h1>
		<button @click="fn">给box1传值</button>
	</div>
</template>

<script>
	export default {
		methods: {
			fn() {
				this.$bus.emit("box1data", "box1的数据")
			}
		}
	}
</script>

<style>
</style>

main.js

import Vue from 'vue'
import App from './App.vue'
Vue.prototype.$bus=new Vue({
	data:{
		arr:[]
	},
	methods:{
		on(eventname,callback){
			if(this.arr.includes(eventname)){
				throw "eventname events already regist!!"
			}else{
				this.arr.push(eventname)
				this.$on(eventname,callback)
			}		
		},
		emit(eventname,...arg){
			this.$emit(eventname,...arg)
		},
		off(eventname,callback){
			this.$off(eventname,callback)
		}
	}
})
var vm=new Vue({
  render: h => h(App),
})
vm.$mount('#app')

在main.js中实例一个新vm对象,在其余组件中就能直接调用,就不需要一层一层的传值

动态组件

有的时候,我们希望页面中的某个地方,在不同组件之间进行动态切换,这时候除了条件渲染,还可以使用动态组件

component 标签的 is属性语法:is后跟组件的变量名决定使用哪个组件来渲染

注意: is是组件名 :is是data中的变量中保存的组件名

App.vue

<template>
	<div>
		<button @click="mytemp='Box1'">1</button>
		<button @click="fn('Box2')">2</button>
		<button @click="mytemp='Box3'">3</button>
		<component v-bind:is="mytemp"></component>
	</div>
</template>

<script>
	import Box1 from "./Box1.vue"
	import Box2 from "./Box2.vue"
	import Box3 from "./Box3.vue"
	export default {
		data() {
			return {
				arr: [true,false,false],
				mytemp:"Box2"
			}
		},
		components:{
			Box1,
			Box2,
			Box3
		},
		methods:{
			fn(index){
				this.mytemp=index
			}
		}
	}
</script>

Box1.vue

<template>
	<div>
		box1
	</div>
</template>

<script>
	export default {
		
	}
</script>

<style>
</style>

Box2.vue

<template>
	<div>
		box2
	</div>
</template>

<script>
	export default {
		
	}
</script>

<style>
</style>

Box3.vue

<template>
	<div>
		box3
	</div>
</template>

<script>
	export default {
		
	}
</script>

<style>
</style>

我们给button绑定点击事件,当我们点击的时候就会切换box,而这个效果的实现是使用了component 标签的 is属性,给is一个v-bind指令,那么当我们点击的不同的box时,就会往fn函数里面传入不同的参数,这个参数又赋值给了mytemp,这时页面上的mytemp就会动态的改变成相应的数据了,也就实现了动态切换效果

缓存组件

动态组件的切换,切换后是不会缓存之前被切换掉的组件的,每次切换新组件的时候,Vue 都创建了一个新的组件对象

有时候我们希望在A组件时用户做了一些操作,切换B组件时做了一些操作,当切回A组件时希望记住A的操作,不要重新创建A组件,keep-alive可以缓存动态切换的组件

App.vue

<keep-alive>
	<component v-bind:is="mytemp"></component>
</keep-alive>

Box.vue

<template>
	<div class="box">
		box1<br>
		email:<input type="text" v-model="email"> <br>
		pwd:<input type="password" v-model="pwd">
	</div>
</template>

<script>
	export default {
		data() {
			return {
				email: "",
				pwd:""
			}
		}
	}
</script>

<style scoped="scoped">
	.box{
		width: 400px;
		height: 400px;
		background-color: aliceblue;
	}
</style>

App.vue里面的内容都是一样的,只是给div加了一个keep-alive标签而已,这样我们就把用户输入的信息缓存了起来

异步组件

Vue允许将组件定义为一个异步解析(加载)组件定义的工厂函数,即Vue只在实际需要渲染组件时,才会触发调用工厂函数,并且将结果缓存起来,用于将来再次渲染

就有点类似于懒加载,在用户用到的时候才会去加载,因为一个完整的网站内容是非常多的,如果不管用户使不使用都全部一股脑的加载,那么势必会造成网页打开卡顿,性能不好,用户体验感差,所以我们要使用异步组件来懒加载

App.vue

<template>
	<div>
		<h1>test</h1>
		<button @click="fn">b</button>
		<component :is="n"></component>
		
		<Box2></Box2>
	</div>
</template>

<script>
	// 需要使用的就在这里引入,直接打包
	// 不需要一开始就使用的就在下面加载,用户需要使用的时候在点击加载
	import a from "./a.vue"
	// import b from "./b.vue"
	// 官方提供的加载前后的提示效果
	import LoadingComponent from "./LoadingComponent.vue"
	import ErrorComponent from "./ErrorComponent.vue"
	
	export default {
		data() {
			return {
				n: "Box1"
			}
		},
		methods: {
			fn() {
				this.n = "Box2"
			}
		},
		components: {
			Box1: a,
			// Box2: function(resolve) {
			// 	require(['./b.vue'], resolve)
			// }
			// Box2:()=>import("./b.vue") //最常用的方式

			Box2: () => ({
				// 需要加载的组件 (这个 `import` 函数会返回一个 `Promise` 对象。)
				component: import('./b.vue'),
				// 异步组件加载时使用的组件
				loading: LoadingComponent,
				// 加载失败时使用的组件
				error: ErrorComponent,
				// 展示加载时组件的延时时间。默认值是 200 (毫秒)
				delay: 200,
				// 如果提供了超时时间且组件加载也超时了,
				// 则使用加载失败时使用的组件。默认值是:`Infinity`
				timeout: 3000
			})
		}


	}
</script>

<style>
</style>

a.vue

<template>
	<div>
		a
	</div>
</template>

<script>
	export default {
		
	}
</script>

<style>
</style>

b.vue

<template>
	<div>
		b
	</div>
</template>

<script>
	export default {
		
	}
</script>

<style>
</style>

LoadingComponent.vue

<template>
	<div>
		加载中.....
	</div>
</template>

<script>
	export default {
		
	}
</script>

<style>
</style>

ErrorComponent.vue

<template>
	<div>
		网络不行 加载失败了 刷新试试
	</div>
</template>

<script>
	export default {
		
	}
</script>

<style>
</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值