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


    组件传值 provide-inject 非响应式

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

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

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

    App.vue

    <template>
      <div>
        <Box1>Box1>
        <button @click="change">change1button>
    	<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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    Box.vue

    <template>
    	<div>
    		<p>box1---{{msg}}p>
    	div>
    template>
    
    <script>
    	export default {
    		inject:["msg"],
    		// 即可以接收数据也可以传递数据
    		provide:{n:10}
    	}
    script>
    
    <style>
    style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

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

    组件传值 provide-inject 响应式

    App.vue

    <template>
    	<div>
    		<Box1>Box1>
    		<button @click="change">changebutton>
    		{{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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    Box.vue

    <template>
    	<div>
    		<p>box1---{{msg()}}p>
    	div>
    template>
    
    <script>
    	export default {
    		inject:["msg"],
    	}
    script>
    
    <style>
    style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

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

    自定义事件

    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>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    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>
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    Box.vue

    <template>
    	<div>
    		<h1>box3h1>
    		<button @click="fn">给box1传值button>
    	div>
    template>
    
    <script>
    	export default {
    		methods: {
    			fn() {
    				this.$bus.emit("box1data", "box1的数据")
    			}
    		}
    	}
    script>
    
    <style>
    style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    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')
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

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

    动态组件

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

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

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

    App.vue

    <template>
    	<div>
    		<button @click="mytemp='Box1'">1button>
    		<button @click="fn('Box2')">2button>
    		<button @click="mytemp='Box3'">3button>
    		<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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    Box1.vue

    <template>
    	<div>
    		box1
    	div>
    template>
    
    <script>
    	export default {
    		
    	}
    script>
    
    <style>
    style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    Box2.vue

    <template>
    	<div>
    		box2
    	div>
    template>
    
    <script>
    	export default {
    		
    	}
    script>
    
    <style>
    style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    Box3.vue

    <template>
    	<div>
    		box3
    	div>
    template>
    
    <script>
    	export default {
    		
    	}
    script>
    
    <style>
    style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    我们给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>
    
    • 1
    • 2
    • 3

    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>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

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

    异步组件

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

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

    App.vue

    <template>
    	<div>
    		<h1>testh1>
    		<button @click="fn">bbutton>
    		<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>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    a.vue

    <template>
    	<div>
    		a
    	div>
    template>
    
    <script>
    	export default {
    		
    	}
    script>
    
    <style>
    style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    b.vue

    <template>
    	<div>
    		b
    	div>
    template>
    
    <script>
    	export default {
    		
    	}
    script>
    
    <style>
    style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    LoadingComponent.vue

    <template>
    	<div>
    		加载中.....
    	div>
    template>
    
    <script>
    	export default {
    		
    	}
    script>
    
    <style>
    style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    ErrorComponent.vue

    <template>
    	<div>
    		网络不行 加载失败了 刷新试试
    	div>
    template>
    
    <script>
    	export default {
    		
    	}
    script>
    
    <style>
    style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
  • 相关阅读:
    【第二章 SQL-DDL(查询、创建、删除、使用数据库)(查询、创建数据库中的表)】
    shap库源码和代码实现
    设计模式 单一职责原则、开放封闭原则、依赖倒置原则、里氏代换原则
    zabbix部署与监控
    Flutter 小计1
    使用Minifilter过滤驱动保护文件
    Python并发执行(未完待续)
    C陷阱与缺陷 第8章 建议与答案 8.2 答案
    Python 人工智能 Machine Learning 机器学习基础知识点详细教程(更新中)
    MySQL 数据库的体系结构
  • 原文地址:https://blog.csdn.net/chuxialia/article/details/126770409