vue组件间通信技巧--父子组件,兄弟组件,隔代组件

1. 父子组件

方法一:
父组件传递参数给子组件通过props如下:

// 父组件
<template>
  <div>
    <hello-world msg="hello world"/>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue';

export default {
  name: 'App',
  components: {
    HelloWorld
  },
}
</script>

// 子组件使用参数
<template>
  <div>
    <h1>{{ msg }}</h1>
  </div>
</template>

<script>
export default {
  name: "HelloWorld",
  props: {
    msg: String
  },
};
</script>

子组件要跟父组件通信:
子组件可以用emit发出事件广播,父组件监听即可

// 父组件增加监听方法
<template>
  <div>
    <hello-world msg="hello world" @click-it="handleClick" />
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue';

export default {
  name: 'App',
  components: {
    HelloWorld
  },
  setup() {
    const handleClick = (param) => {
      console.log('你点我干嘛!!', param);
    }
    return {
      handleClick
    }
  }
}
</script>

// 子组件
<template>
  <div>
    <h1 @click="handleClick">{{ msg }}</h1>
  </div>
</template>

<script>
export default {
  name: "HelloWorld",
  props: {
    msg: String
  },
  // vue3.0写法,通过上下文context的emit方法,触发事件
  // 或者不用setup,在methods里写方法,通过this.$emit触发
  setup(props, context) {
    const handleClick = () => {
      context.emit('click-it', 12);
    }
    return {
      handleClick
    }
  }
};
</script>

方法二:

通过ref或者$parent / $children访问父子实例

ref如果用在普通DOM元素,引用的就是该DOM元素,如果用在子组件上,引用的就是组件实例

// 父组件通过ref调用子组件的方法
<template>
  <div>
  	<!-- vue2.0写法 -->
  	<!-- <hello-world msg="hello world" ref="helloWorldRef" @dblclick="handleClick" /> -->
    <hello-world msg="hello world" ref="helloWorldRef" @dblclick="handleClick" />
  </div>
</template>

<script>
import { ref } from 'vue';
import HelloWorld from './components/HelloWorld.vue';
export default {
  name: 'App',
  components: {
    HelloWorld
  },
  // vue2.0写法
 // methods: {
//	handleClick() {
  //    this.$refs.helloWorldRef.handleClick();
  //  }
  //}
  setup() {
    const helloWorldRef = ref('hello');
   
    const handleClick = () => {
      helloWorldRef.value.handleClick();
    }
    return {
      handleClick,
      helloWorldRef
    }
  }
}
</script>
// 子组件
<template>
  <div>
    <h1>{{ msg }}</h1>
    </p>
  </div>
</template>

<script>
export default {
  name: "HelloWorld",
  props: {
    msg: String
  },
  setup(props, context) {
    const handleClick = () => {
      console.log('你点我干嘛!!');
    }

    return {
      handleClick
    }
  }
};
</script>

2. 兄弟组件

通过EventBus,定义一个vue实例作为事件中心,触发和监听事件,可以实现父子,兄弟,隔代组件之间的通信

// vue 2.0
const eventBus = new Vue()
eventBus.$emit('some-action', value);
eventBus.$on('some-action', (value) => {})

3. 隔代组件

隔代组件也可以通过EventBus来实现,也可以通过$attrs / $listeners

在vue2.0中:

孙子组件的$attrs中包含了父组件中,不在props中指定过的属性,如果父组件没有设置props,则$attrs就包含了祖先组件传入的所有属性;

在父级组件中,可以通过v-bind="$attrs"来把属性传入子级组件。

同理:
$listeners是所有绑定的方法,可以通过v-on="$listeners"传入子级组件

在vue3.0中

$attrs / $listeners都继承到了setup(props, context)context上下文对象的attrs属性里(属性和方法都在一起)

// -------------------
// 祖先组件
<template>
  <div>
  // 往子组件传入参数,属性值和方法都可以
    <hello-world msg="hello world" ref="helloWorldRef" @dblclick="handleClick" />
  </div>
</template>

<script>
import { ref } from 'vue';
import HelloWorld from './components/HelloWorld.vue';
import { eventBus } from './utils/eventBus';

export default {
  name: 'App',
  components: {
    TodoList,
    HelloWorld
  },
  setup() {
    const helloWorldRef = ref('hello');
    const handleClick = () => {
      helloWorldRef.value.handleClick();
    }
    return {
      handleClick,
      helloWorldRef
    }
  }
}
</script>

// -----------------------
//父级组件

<template>
  <div>
    <h1>{{ msg }}</h1>
    // 通过v-bind="attrs"传递到孙级组件
    <vote v-bind="attrs"/>
    <button @click="count++">count is: {{ count }}</button>
    <p>
      Edit
      <code>components/HelloWorld.vue</code> to test hot module replacement.
    </p>
  </div>
</template>

<script>
import Vote from './vote.vue';

import { watchEffect } from "vue";
export default {
  name: "HelloWorld",
  components: {
    Vote
  },
  props: {
  	// props里指定的属性,不会通过v-bind="attrs"传递到下一级组件
    // msg: String
  },
  setup(props, context) {
  // vue3.0中,attrs属性绑定在context上下文对象上
    console.log(context.attrs)
    const handleClick = () => {
      console.log('你点我干嘛!!');
    }

    return {
    // 暴露出attrs对象,便于模板中传递给下一级组件
      attrs: context.attrs,
      handleClick
    }
  }
};
</script>
// -----------------------------
// 孙级组件
// 创建组件方式跟以前一样
<template>
  <div>
    <h3>{{msg}}投票</h3>
  </div>
</template>
<script>
import { ref, reactive, computed } from 'vue';
export default {
  // 设置props接收属性,便于模板里直接使用
  props: {
    msg: String,
  },
  setup(props, context) {
    // cann't use this
    console.log(context.attrs);
    return {
      // 。。。
    }
  },
}
</script>

vue2.0用法差不多,只不过$attrs, $listeners挂在this上

4. 不管几代都能通信的方法:

  1. vuex

  2. Vue.observable()

observable返回的是一个响应式数据
如下:在需要的组件里引入store响应式数据,同时引用mutations里的方法修改数据即可。

import Vue from 'vue';

const initialStore = {
  count: 0,
}
export const store = Vue.observable(initialStore);

export const mutations = {
  countAdd() {
    store.count += 1;
  },
  countMinus() {
    store.count -= 1;
  }
}
  1. provide / inject
    https://cn.vuejs.org/v2/api/#provide-inject

provide在祖先组件中指定,可以是一个对象,也可以是一个返回对象的方法;该对象包含可注入其子孙的 property
inject在子代组件中指定,可以是一个数组或者一个对象
这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效,跟react里的context差不多

// 父级组件提供 'foo'
var Provider = {
  provide: {
    foo: 'bar'
  },
  // ...
}

// 子组件注入 'foo'
var Child = {
  inject: ['foo'],
  created () {
    console.log(this.foo) // => "bar"
  }
  // ...
}

特别注意:provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的 property 还是可响应的

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值