美文网首页
vue3 组件通信

vue3 组件通信

作者: 洪锦一 | 来源:发表于2024-08-01 13:17 被阅读0次

Vue3 组件通信和 Vue2 的区别:

  • 移出事件总线,使用mitt代替。
  • vuex换成了pinia
  • .sync优化到了v-model里面了
  • $listeners所有的东西,合并到$attrs中了。
  • $children被砍掉了。

常见搭配形式

1. props

props是使用频率最高的一种通信方式,常用与 :父 ↔ 子
父传子:属性值是非函数
子传父:属性值是函数

  • 父传子(属性值是非函数)
<child :name="name"/>
let name = ref('zs')
// 子组件接收
defineProps(['name'])
  • 子传父(属性值是函数)
// 父组件
<child :getName="getName" />
const getName= (value) => {
  console.log(value);
}

// 子组件
defineProps(['getName'])
<el-button @click="getName('我是子组件的值')">传值给父组件</el-button>

2. 自定义事件

概述:自定义事件常用于:子 => 父

// 父组件
<child @send-name="getName" />

const getName = (v1, v2) => {
  console.log(v1, v2);
}

//子组件
<el-button @click="handleSend">传值给父组件</el-button>

const $emits = defineEmits(['send-name'])

const handleSend = ()=>{
    $emits('send-name','参数1','参数2')
}

3. mitt

与消息订阅与发布(pubsub)功能类似,可以实现任意组件间通信

安装:npm i mitt

//utils/emitter.js

// 引入 mitt 
import mitt from "mitt";

// 创建 mitt
const emitter = mitt()

// 暴露 mitt
export default emitter
  • 发送事件
import emitter from "@/utils/emitter";
const handleSend = () => {
  emitter.emit('send-name', { name: '参数1' })
}
  • 监听事件
import emitter from "@/utils/emitter";
// 绑定事件
emitter.on('send-name', (obj) => {
  console.log(obj)
})

// 卸载
onUnmounted(()=>{
   emitter.off('send-name')
})
  • 示例
// 绑定事件
  emitter.on('abc',(value)=>{
    console.log('abc事件被触发',value)
  })
  emitter.on('xyz',(value)=>{
    console.log('xyz事件被触发',value)
  })

  setInterval(() => {
    // 触发事件
    emitter.emit('abc',666)
    emitter.emit('xyz',777)
  }, 1000);

  setTimeout(() => {
    // 清理事件
    emitter.all.clear()
  }, 3000); 

4. v-model

实现 父↔子 之间相互通信。

// 父组件
<child v-model="name" />
// v-modle 本质 上面的是下面的简写
<child :modelValue="name" @update:model-value="name = $event" />

let name = ref('my name is zs')

// 子组件 child
<input type="text" :value="modelValue" @input="emit('update:model-value',$event.target.value)">

defineProps(['modelValue'])
const emit = defineEmits(['update:model-value'])
  • 绑定多个值
// 父组件
<child v-model:name1="name1" v-model:name2="name2" />
let name1 = ref('zs')
let name2 = ref('ls')

// 子组件
<el-button @click="handleChange">开始传值</el-button>

defineProps(['name1', 'name2'])

const emit = defineEmits(['update:name1', 'update:name2'])

const handleChange = () => {
    emit('update:name1','zs1')
    emit('update:name2','ls1')
}

5. $attrs

$attrs用于实现当前组件的父组件,向当前组件的子组件通信(祖→孙)。
$attrs是一个对象,包含所有父组件传入的标签属性。
$attrs会自动排除props中声明的属性

// 父
<child :name1="name1" :name2="name2" :name3="name3" />
let name1 = ref('name1')
let name2 = ref('name2')
let name3 = ref('name3')
// 子
<son v-bind="$attrs" />
defineProps(['name1'])
// 孙
defineProps(['name2', 'name3'])

6. refs、parent

$refs用于 :父→子。 值为对象,包含所有被ref属性标识的DOM元素或组件实例。
$parent用于:子→父。 值为对象,当前组件的父组件实例对象。

  • ref 获取子组件数据
// 父组件
<child ref="childRef" />

let childRef = ref()

const getChild = () => {
  console.log(childRef.value.age);
  console.log(childRef.value.name);
}

// 子组件
let name = ref('zs')
let age = ref(16)

defineExpose({ name, age })
  • parent 子传父
// 父组件
let parentAge = ref(12)
const printName = () => {
  console.log('我是名称');
}
defineExpose({ parentAge,hanshu: printName })

// 子组件
<button @click="getParent($parent)">年龄-1</button>

const getParent = (parent) => {
    parent.hanshu()
    parent.parentAge-=1
}

7. provide、inject

实现祖孙组件直接通信
在祖先组件中通过provide配置向后代组件提供数据
在后代组件中通过inject配置来声明接收数据

// 祖组件
let name = ref('zs')
let age = ref(18)
const updateAge = () => {
  age.value += 1
}
provide('name', name)
provide('ageContent', { age, updateAge })

// 孙组件
let name = inject('name')
let { age, updateAge } = inject('ageContent')

setInterval(() => {
  updateAge()
}, 1000);

8. pinia

vue3 pinia

9. slot

  • 默认插槽
// 父组件
<child title="默认插槽">
   <ul>
       <li v-for="i in 10" :key="i">{{i}}</li>
   </ul>
</child>

// 子组件
<div class="child">
    <h3>{{title}}</h3>
    <slot></slot>
</div>
defineProps(['title'])
  • 具名插槽
// 父组件 v-slot: 可以简写成#
<child title="默认插槽">
  <template #c1>
    我是c1内容
  </template>
  <template v-slot:c2>
    我是c2内容
  </template>
</child>

// 子组件
<div class="child">
    <h3>{{title}}</h3>
    <slot name='c1'></slot>
    <slot name='c2'></slot>
</div>
defineProps(['title'])
  • 作用域插槽

数据在组件的自身,但根据数据生成的结构需要组件的使用者来决定。

// 父组件 
<div class="parent">
  <child v-slot="params">
    <ul>
      <li v-for="item in params.dataList" :key="item.age">{{item.name}}</li>
    </ul>
  </child>

  <child v-slot:default="params">
    <ol>
      <li v-for="item in params.dataList" :key="item.age">{{item.name}}</li>
    </ol>
  </child>

  <child #default="params">
    <dl>
      <dt>{{ params.title }}</dt>
      <dd v-for="item in params.dataList" :key="item.age">{{item.name}}</dd>
    </dl>
  </child>
</div>

// 子组件
<div class="child">
  <slot :dataList="dataList" title="作用域插槽"></slot>
</div>

<script setup>
 let dataList = reactive([
    { name: 'zs', age: 11 },
    { name: 'ls', age: 22 },
    { name: 'wu', age: 33 },
  ])
</script>

总结

  • props 父传子,子传父
  • 自定义事件 子传父
  • mitt 任意组件通信
  • v-model 父传子,子传父
  • $attrs 父传子,父传孙,祖孙通信
  • $refs 父传子
  • $pare 子传父
  • provide、inject 祖传通信
  • pinia 任意组件通信
  • slot 父传子,子传父

相关文章

  • Vue3 的 7 种和 Vue2 的 12 种组件通信

    Vue2.x组件通信12种方式写在后面了,先来 Vue3 的 Vue3 组件通信方式 props $emit ex...

  • 7个 Vue3 中的组件通信方式

    原文链接 : 7个 Vue3 中的组件通信方式[https://tzy1997.com/articles/vu98...

  • provide inject在vue2和vue3中的使用

    vue2父组件 vue2子组件 vue3父组件 vue3子组件 vue3官方详细使用provide inject地...

  • Vue3学习与实战 · 组件通信

    在使用Vue3构建中大型web应用时, 组件通信 肯定是不可避免的。本文就具体介绍一下使用Vue3的 props、...

  • vue3 常用watch及defineExpose

    vue3 watch监听的两张方法 vue3 父组件调用子组件实例

  • vue中的组件通信

    一、组件通信(组件传值) 1.1父子组件通信 1.2子父组件通信 1.3非父子组件通信(兄弟组件通信)

  • 组件通信

    组件通信分为几种: 父组件给子组件通信 子组件给父组件通信 兄弟组件通信 1.父组件给子组件通信 法一...

  • 组件通信

    组件关系 组件关系可以分为父子组件通信、兄弟组件通信、跨级组件通信。 父子组件通信 1. 子组件使用 $emit(...

  • vue3 中对 dialog 封装

    vue3 中对 dialog 封装 子组件 父组件

  • react之组件通信

    需要组件之进行通信的几种情况: 父组件向子组件通信 子组件向父组件通信 跨级组件通信 没有嵌套关系组件之间的通信 ...

网友评论

      本文标题:vue3 组件通信

      本文链接:https://www.haomeiwen.com/subject/hxlohjtx.html