vue3 组件通信

142 阅读1分钟

1、props/$emit

父传子 使用props

//父组件
<template>
  <childrenComp :arr="arr" />
  <input type="text" v-model="data" />
  <button @click="handleAdd">添加</button>
</template>
<script setup>
import { ref } from 'vue';
import childrenComp from '@/components/children-comp.vue';
const data = ref('');
const arr = ref([]);

const handleAdd = () => {
  arr.value.push(data.value);
  value.value = '';
};
</script>
<style></style>
//子组件
<template>
  <div class="hello">
    <ul>
      <li v-for="(item, index) in props.arr" :key="index">
        {{ item }}
      </li>
    </ul>
  </div>
</template>

<script setup>
import { defineProps } from 'vue';
const props = defineProps({
  arr: {
    type: Array,
    default: () => [],
  },
});
</script>

子传父,使用$emit

//子组件
<template>
  <div class="hello">
    <input type="text" v-model="data" />
    <button @click="handleAdd">添加</button>
  </div>
</template>

<script setup>
import { ref, defineEmits } from 'vue';

const data = ref('');
const emits = defineEmits(['add']);
const handleAdd = () => {
  emits('add', data.value);
  data.value = '';
};
</script>
//父组件
<template>
  <ul>
    <li v-for="(item, index) in arr" :key="index">
      {{ item }}
    </li>
  </ul>
  <childrenComp @add="addItem" />
</template>
<script setup>
import { ref } from 'vue';
import childrenComp from '@/components/children-comp.vue';
const arr = ref([]);

const addItem = (item) => {
  arr.value.push(item);
};
</script>

2、ref

子组件

<template>
  <div class="hello">
    <input type="text" v-model="data" />
    <button @click="handleAdd">添加</button>
  </div>
</template>

<script setup>
import { ref, defineExpose } from 'vue';

const data = ref('');
const arr = ref([]);
const handleAdd = () => {
  arr.value.push(data.value);
  data.value = '';
};
defineExpose({ arr });  //通过defineExpose暴露给父组件的数据
</script>

父组件

<template>
  <ul>
    <li v-for="(item, index) in childrenRef?.arr" :key="index">
      {{ item }}
    </li>
  </ul>
  <childrenComp ref="childrenRef" />
</template>
<script setup>
import { ref } from 'vue';
import childrenComp from '@/components/children-comp.vue';
const childrenRef = ref();
</script>

3、v-model

父组件

<template>
  <ul>
    <li v-for="(item, index) in list" :key="index">
      {{ item }}
    </li>
  </ul>
  <childrenComp v-model:list="list" />
  // Vue 会自动将其解释为:<childrenComp :list="list" @update:list="list = $event"/>
</template>
<script setup>
import { ref } from 'vue';
import childrenComp from '@/components/children-comp.vue';
const list = ref([1, 2, 3, 4]);
</script>
<style></style>

子组件

<template>
  <div class="hello">
    <input type="text" v-model="data" />
    <button @click="handleAdd">添加</button>
  </div>
</template>

<script setup>
import { ref, defineEmits, defineProps } from 'vue';
const props = defineProps({
  list: {
    type: Array,
    default: () => [],
  },
});
const emits = defineEmits(['update:list']);

const data = ref('');

const handleAdd = () => {
  const arr = [...props.list, data.value];
  emits('update:list', arr); // 触发父组件@update:list的事件,$event就是arr
  data.value = '';
};
</script>

4、provide/inject,该API可以实现父组件向子组件传递数据,无论层级有多深,都可以通过这对API实现

父组件使用provide提供响应式数据

<template>
  <div class="hello">
    <input type="text" v-model="data" />
    <button @click="handleAdd">添加</button>
  </div>
  <childrenComp v-model:list="list" />
</template>
<script setup>
import { provide, ref } from 'vue';
import childrenComp from '@/components/children-comp.vue';
const list = ref([]);
provide('list', list);
const data = ref('');
const handleAdd = () => {
  list.value.push(data.value);
  data.value = '';
};
</script>

子组件使用inject获取数据

<template>
  <ul>
    <li v-for="(item, index) in list" :key="index">
      {{ item }}
    </li>
  </ul>
</template>

<script setup>
import { inject } from 'vue';
const list = inject('list');
</script>

5、pinia是vue中的状态管理工具,功能比较强大,单独写一篇,这里就省略了。。。