关于Vue组件间的传值(2)---跨组件之间的传值

334 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第13天,点击查看活动详情
在项目开发过程中,最常用到的便是:vue组件间的传值。以下是本人总结的vue组件间传值的几种传值方式。首先可以大致区分为父子组件之间的传值,跨组件之间的传值和兄弟组件之间的传值。该文章讲解第二部分:跨组件之间的传值。

1. Provide / Inject

对于深层子组件需要父组件的内容时,也可以使用prop沿着组件链逐级传递,但会比较麻烦。实际上,我们可以使用provide/inject。无论组件层级结构多深,父组件都可以通过poject来提供数据,而子组件可以通过inject来接受使用这些数据。

父组件:

<script>
export default {
   data(){
     return{
        myName:'vivi'   
     }
   }
   provide(){
     return{
       name: myName    
     }
  }
}
</script>

需要接受信息的子组件

<script>
export default {
  inject: ['name'],
  created() {
    console.log(this.name) // 父组件注入的信息: vivi
  }
</script>

通常,我们会使用provide/inject来实现无感应式刷新页面,即刷新页面时不会出现空白页。具体demo如下:

首先在app.vue中注入reload更新方法。

<template>
    <div id="app">
        <router-view v-if="isRouterAlive"></router-view>
    </div>
</template><script>
    export default {
        name:'app',
        provide(){
            return {
                reload:this.reload
            }
        },
        data(){
            return {
                isRouterAlive:true
            }
        },
        methods:{
            reload(){
                this.isRouterAlive = false;
                this.$nextTick(()=>{
                    this.isRouterAlive = true;
                })
            }
        }
    }
</script>

接着,在子组件中使用inject响应该方法。当需要触发刷新时,即可调用到父组件的reload方法。

<template>
    <div>
        <button @click="needReload">触发刷新页面</button>
    </div>
</template><script>
    export default {
        inject:['reload'],
        methods:{
            needReload(){
               this.reload();
            }
        }
    }
</script>

2.$attrs和$listeners

  • $attrs 包含了父作用域不被props接收到的数据(除class和style),这部分数据可以通过v-bind="$attrs "传入内部组件。可以理解为:$attrs就是一个容器对象,这个容器对象会存放:父组件传过来的且子组件未使用props声明接收的数据

  • $listeners包含了父作用域中的 (不含 .native 修饰器的) 所有v-on 事件,可以通过 v-on="$listeners"传入内部组件

    接下来的实例则演示使用props逐级传递至嵌套的子组件和使用$attrs$listeners传递数据和方法的对比。

    父组件

    <template>
      <div>
         <child :name1="'vivi'" :name2="'xiao xiao'" @toSon="mydata"></child>   
      </div>
    </template><script>
        export default {
            methods:{
               components: {
                 child
                },
                mydata(){
                   console.log("我被孙子组件触发了");
                }
            }
        }
    </script>
    

    子组件

    <template>
      <div>
          <p>name1:{{name1}}</p>
          <p>name2:{{$attrs.name2}}</p> 
         <childSon :name1="name1" v-bind="$attrs" v-on="$listeners"></childSon>   
      </div>
    </template>
    <script>
        export default {
            props:['name1'],
            inheritAttrs:false,
            components: {
                 childSon
            }
    ​
        }
    </script>
    

    孙子组件

    <template>
      <div>
          <p>name1:{{name1}}</p>
          <p>name2:{{name2}}</p> 
          <button @click="changeParents">点击触发父组件的mydata事件</button>
      </div>
    </template>
    <script>
        export default {
            props:['name1','name2'],
            methods:{
                changeParents(){
                    this.$emit("toSon");
                }
            }
    ​
        }
    </script>