Vue组件通信的方式

1.父组件向子组件传值

  • 在父组件中引入子组件
  • 注册子组件
  • 在页面中使用,子组件标签上动态绑定传入动态值/静态值
  • 在子组件中,使用props来接受父组件传递过来的值

子组件接收的父组件的值分为引用类型普通类型两种:

  • 普通类型: String,Number,Boolean,Null
  • 引用类型: Array,Object
#父组件

<template>
  <div>
    <!-- 传递值 -->
    <Test
     :obj="obj" 
     info="测试"/>
  </div>
</template>

<script>
// 引入子组件
import Test from "../components/Test.vue";
export default {
  name: "about",
  // 注册子组件
  components: {
    Test,
  },
  data() {
    return {
      obj: {
        name: "whl",
        title: "qwe",
      },
    };
  },
};
</script>
<template>
    <div>
        <h1>{{obj.name}}</h1><br>
        <h2>{{obj.title}}</h2>
        <h3>{{info}}</h3>
    </div>
</template>

<script>
    export default {
        name:'test',
        props:{
            obj:Object,
            info: [String,Number]  //info值为其中一种类型即可,其他类型报警告
        }
    }
</script>

Vue是单项数据流,子组件不能直接修改父组件的值


2.子组件向父组件传值

  • 子组件通过绑定事件,通过this.$emit(‘自定义事件名字’,想传递的参数)
#父组件

<Test
     :obj="obj" 
     info="测试"
     @modify="modifyFatherValue"/>

<script>
// 引入子组件
import Test from "../components/Test.vue";
export default {
  name: "about",
  // 注册子组件
  components: {
    Test,
  },
  data() {
    return {
      msg:'我是父组件'
    };
  },
  methods:{
    // 接受子组件传递来的值,赋值给data中的属性
    modifyFatherValue(e){
      this.msg = e
    }
  }
};
</script>
# 子组件

<button @click="modifyValue">修改父组件的值</button>


<script>
    export default {
        name:'test',
        methods:{
            modifyValue(){
                this.$emit('modify','子组件传递过来的值')
            }
        }
    }
</script>


3.父组件通过$refs/$children来获取子组件的值

$refs:

  • 获取dom元素和组件实例来获取组件的属性和方法
  • 通过在子组件绑定ref,使用this.$refs.refName.子组件属性/子组件方法

$children

  • 当前实例的子组件,它返回的是一个自组件的集合,如果想获取哪个组件的属性和方法,可以通过
    this.$chidren[index].子组件的属性/子组件的方法

$refs

# 子组件
<script>
    export default {
        name:'test',
        data() {
            return {
                datas:"我是子组件值"
            }
        },
        props:{
            obj:Object,
            info: [String,Number]
        },
        methods:{
            getValue(){
                console.log('我是Test1')
            }
        }
    }
</script>
# 父组件
<template>
  <div>
   // 给子组件上绑定 ref  
    <Test
      ref="son"
    />
   <Test2/>
  </div>
</template>

// 通过 $refs 示例来获取 子组件的属性和方法

console.log( this.$refs.son.datas) 

this.$refs.son.getValue()

$children

//  通过 $children  来获取 子组件的属性和方法
this.$children[0].getValue(); // 我是 Test1
console.log(`---------${this.$children[1].datas}`); //我是子组件值

4.子组件通过$parent来获取父组件的实例的属性和方法

export default {
  data() {
    return {
      obj: {
        name: "whl",
      },
    };
  },
  methods: {
    getName() {
      console.log(this.obj.name);
    },
  },
};
 <script>
   export default {
       name:'test',
       created(){
        console.log( this.$parent.obj ) 
        this.$parent.getName()
       },
       
   }
</script>

5.$attrs和$listeners获取父组件实例的属性和方法(组件嵌套情况下使用)

在这里插入图片描述
在这里插入图片描述$attrs 的作用,某些情况下需要结合 inheritAttrs 一起使用

有 4 个组件:App.vue / child1.vue / child2.vue / child3.vue,这 4 个组件分别的依次嵌套的关系。

// App.vue
<template>
  <div id="app">
    <p>App.vue</p><hr>
    // 这里我们可以看到,app.vue向下一集的child1组件传递了5个参数,分别是name / age / job / sayHi / title
    <child1 :name="name" :age="age" :job="job" :say-Hi="say" title="App.vue的title"></child1>
  </div>
</template>
<script>
const child1 = () => import("./components/child1.vue");
export default {
  name: 'app',
  components: { child1 },
  data() {
    return {
      name: "whl",
      age: "22",
      job: "FE",
      say: "this is Hi~"
    };
  }
};
</script>
// child1.vue
<template>
  <div class="child1">
    <p>child1.vue</p>
    <p>name: {{ name }}</p>
    <p>childCom1的$attrs: {{ $attrs }}</p>
    <p>可以看到,$attrs这个对象集合中的值 = 所有传值过来的参数 - props中显示定义的参数</p>
    <hr>
    <child2 v-bind="$attrs"></child2>
  </div>
</template>
<script>
const child2 = () => import("./child2.vue");
export default {
  components: {
    child2
  },
  // 这个inheritAttrs默认值为true,不定义这个参数值就是true,可手动设置为false
  // inheritAttrs的意义在用,可以在从父组件获得参数的子组件根节点上,将所有的$attrs以dom属性的方式显示
  inheritAttrs: true, // 可以关闭自动挂载到组件根元素上的没有在props声明的属性
  props: {
    name: String // name作为props属性绑定
  },
  created() {
    // 这里的$attrs就是所有从父组件传递过来的所有参数 然后 除去props中显式定义的参数后剩下的所有参数!!!
    console.log(this.$attrs); //  输出{age: "22", job: "FE", say-Hi: "this is Hi~", title: "App.vue的title"}
  }
};
</script>
// child2.vue
<template>
  <div class="child2">
    <p>child2.vue</p>
    <p>age: {{ age }}</p>
    <p>childCom2: {{ $attrs }}</p>
    <hr>
    <child3 v-bind="$attrs"></child3>
  </div>
</template>
<script>
const child3 = () => import("./child3.vue");
export default {
  components: {
    child3
  },
  // 将inheritAttrs设置为false之后,将关闭自动挂载到组件根元素上的没有在props声明的属性
  inheritAttrs: false,
  props: {
    age: String
  },
  created() {
    // 同理和上面一样,$attrs这个对象集合中的值 = 所有传值过来的参数 - props中显示定义的参数
    console.log(this.$attrs);
  }
};
</script>
// child3.vue
<template>
  <div class="child3">
    <p>child3.vue</p>
    <p>job: {{job}}</p>
    <p>title: {{title}}</p>
    <p>childCom3: {{ $attrs }}</p>
  </div>
</template>
<script>
export default {
  inheritAttrs: true,
  props: {
    job: String,
    title: String
  }
};
</script>

具体的显示效果
在这里插入图片描述
将inheritAttrs设置为false后,组件根元素上不会显示没有在props声明的属性

$listeners

三个依次嵌套的组件A,B,C

# 组件A
<template>
  <div class="child1">
    <child2 v-on:receive="reciveMessage"></child2>
  </div>
</template>
<script>
const child2 = () => import("./child2.vue");
export default {
  components: {
    child2
  },
  methods: {
    reciveMessage() {
      console.log("reciveMessage success");
    }
  }
};
</script>
# 组件B
<template>
  <div class="child2">
    <child3 v-bind="$attrs" v-on="$listeners"></child3>
  </div>
</template>
<script>
const child3 = () => import("./child3.vue");
export default {
  components: {
    child3
  }
};
</script>
# 组件C
<template>
  <div class="child3">
    <p @click="startReceive">child3</p>
  </div>
</template>
<script>
export default {
  methods: {
    startReceive() {
      this.$emit("receive");
      console.log("startReceive");
    }
  }
};
</script>

这里的结果是,当我们点击C组件的 child3 文字,触发 startReceive 事件,A组件就可以接收到,并触发 recive打印结果如下:

reciveMessage success"
startReceive

6.跨组件之间的传递EventBus

  • 通过新建一个 js 文件,导入 vue , 导出 vue 实例; 然后通过 给导出的实例 上绑定事件 $emit 事件 , 然后再通过 $on 监听触发的事件,这样就可以达到全局组件数据共享。
  • 它可以满足任意场景传递数据, 父子组件传值 , 子父传值 , 兄弟组件之间传值 , 跨级组件之间传值 .
// Vue.js

import Vue from 'vue'
export default new Vue()
// 组件A
<template>
    <div>  
        <button @click="changeValue">改变</button>
    </div>
</template>

<script>
import whlVue from '../util/vue.js';
    export default {
        name:'A',
        data(){
            return {
                title:'whl',
                status: false
            }
        },
        methods:{
          changeValue(){
             // 通过给 vue实例绑定事件
             whlVue.$emit("getTitle", this.title)   
          }  
        }
    }
</script>
// 组件B
<template>
  <div>
    <h1>B组件</h1>
    <h1>{{ title }}</h1>
  </div>
</template>

<script>
import whlVue from "../util/vue.js";
export default {
  name: "B",
  data() {
    return {
      title: "dataB",
    };
  },
  mounted(){
    // 通过 vue 实例.$on  监听事件名,来接收跨级组件传递过来的值
    whlVue.$on("getTitle", (data) => {
      this.title = data;
      console.log(data)
    });
  }
};
</script>

7.Vuex之后会补充


8.provide和inject实现父组件向子孙组件传值(不限层级)

  • provideinject 这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,在关系成立的时间里始终生效。
  • provide/inject可以轻松实现跨级访问父组件的数据

provide

  • 是一个对象或者返回一个对象的函数
  • 包含可注入其子孙组件的属性

inject

  • 是一个字符串数组或者是一个对象
  • 在子组件或者子孙组件中注入provide提供的父组件属性
//对象
provide:{
    name:'whl'
}
//返回对象的函数
provide(){
    return {
        name: 'whl'
    }
}

#inject
inject:['name']
# 父组件
<template>
    <div>
        <h1>我是父组件</h1>
        <Son />
    </div>
</template>

<script>
import Son from '../components/son/SonOne'
    export default {
        name:'father',
        provide(){
            return {
                fatherName: 'whl'
            }
        },
        components:{
            Son
        },
        data(){
            return{
                title:'我是父组件 '
            }
        },
        
    }
</script>
# 子组件
<template>
    <div>
        <h1>我是子组件</h1>
       
    </div>
</template>

<script>
import SonTwo from '../son/SonTwo'
    export default {
        name:'sonone',
        components:{
           SonTwo
        },
        inject:['fatherName'],
        created(){
             console.log(`${this.fatherName}-----------SonTwo`)
        },
        data(){
            return{
                title:'我是子组件 '
            }
        },
        
    }
</script>
# 子孙组件
<template>
    <div>
        <h1>我是子孙组件</h1>
       
    </div>
</template>

<script>
import SonTwo from '../son/SonTwo'
    export default {
        name:'sonone',
        components:{
           SonTwo
        },
        inject:['fatherName'],
        created(){
             console.log(`${this.fatherName}-----------SonTwo`)
        },
        data(){
            return{
                title:'我是子孙组件 '
            }
        },
        
    }
</script>

总结:

父子通信:

  • props/$emit
  • $parent/$children
  • $attrs/$listeners
  • provide/inject
  • ref

跨级通信

  • $attrs/$listeners
  • provide/inject

兄弟通信

  • 使用vuex
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值