组件与传值
1125字约4分钟
2024-07-27
父子组件传值和通信
首先声明一下:各个人写法不一样,我写比较常用正常的写法。
特别提醒:新手需要联合起来看。
1.父组件中写法
<!-- 父组件 parent.vue -->
<template>
<div>
<!--
:message="parentMepssage" 表示将父组件中的parentMepssage变量,传递到子组件中定义message参数上。
@update="getMsg" 表示当子组件触发update事件时,会自动调用父组件中的getMsg方法。将传递过来的参数会自动填入getMsg方法的参数中。
-->
<child-component :message="parentMepssage" @update="getMsg"></child-component>
</div>
</template>
<script lang="ts" setup>
// 使用组件的前提是引入对应的vue文件
import ChildComponent from './child.vue';
const parentMessage =ref('Hello world')
// 声明一个方法来接受数据
const getMsg=(data:any)=>{
// 此处data表示子组件传递过来的参数
console.log(data)
}
</script>
2.子组件中写法
<!-- 子组件 child.vue -->
<template>
<div>
<!-- 使用传过来的父组件参数 -->
<p>{{ message }}</p>
</div>
</template>
<script lang="ts" setup >
// defineProps 创建组件接收的参数
// withDefaults 设置对象的默认值
// defineEmits 创建父组件可以监听的事件
import { defineProps,withDefaults,defineEmits } from 'vue';
// 此处创建两个事件update和over
const emit =defineEmits(['update','over'])
// 声明一个方法来表示我什么时候触发事件
const sendMsg=()=>{
// 表示当前函数被调用的时候触发update事件,并在第二个参数传入所需值
// data可以是任意值
emit('update',data)
}
// 使用interface定义一个类型,并描述数据模样。
interface PropsOption {
message: string;
// ?是表明该参数可传
list?: Array<string>;
// 表示该对象的key可以是任何数据类型,value可以是任何数据类型
[key:any]: any;
}
// 声明子组件要接受的参数,不设置默认值
const props = defineProps<PropsOption>();
// 声明子组件要接受的参数,设置默认值
const props = withDefaults(defineProps<PropsOption>(), {
message: 'Hello from parent'
});
</script>
非父子组件之间传值与通信
其主要是当两个组件之间没有任何层级使用关系的时候如何通信,例如:
A页面下A1组件,B页面下B1组件。
A1和B1组件之间没有层级关系,但是需要通信和使用同一个值。
1.使用provide/inject
<!-- 父组件 parent.vue -->
<script lang="ts" setup>
import { provide } from 'vue';
import ChildComponent from './child.vue';
// 声明一个变量
const message = ref('Hello world');
// 使用provide注入,设置key,val=message
// 此处表述将key='messageKey',value = message注入到全局中
provide('messageKey', message);
</script>
<!-- 子组件 child.vue -->
<script lang="ts" setup>
import { inject } from 'vue';
// inject 获取对应key的值
// inject('messageKey') 表示获取全局中key为messageKey的值
const message = inject('messageKey');
</script>
2.使用vuex或pinia
建议使用pinia,vuex存在页面刷新后数据丢失情况。 pinia:通过localStorage存储数据,页面刷新后数据不会丢失。
// 使用之前得有该数据存储中心
// userStore.ts
import { defineStore } from 'pinia';
import { ref } from 'vue';
// 'user' localStorage中存储key值,建议一个不同的存储模块一个名字,不要重复使用同一个key
export const useUserStore = defineStore('user', () => {
// 声明响应式数据
const username = ref('');
// 声明一个通用方法
const setUser = (name: string) => {
username.value = name;
};
return { user, setUser };
});
任意页面和组件都可以使用该值和方法
<script lang="ts" setup>
// 引入userStore 存储模块
import { useUserStore } from '@/store/userStore';
// 调用useUserStore方法,返回存储中所有的内容信息
const userStore = useUserStore();
// 调用 setUser 方法
userStore.setUser('张三');
// 我们可以使用对象结构,出存储模块中的方法和值,写法如下:
const {setUser,username} = useUserStore()
// ps:因为上面存储模块的写法是函数对象形式,并用ref声明了响应式数据。所以可以直接修改username的值
username.value = '李四'
</script>
3.使用eventBus
可以eventBus是中央事件总线,允许不同组件之间进行通信。
// eventBus.ts
import mitt from 'mitt';
// 创建一个mitt实例
const emitter = mitt();
// 导出实例
export default emitter;
// 在需要使用的地方引入
import emitter from '@/utils/eventBus';
// 发送事件
emitter.emit('eventName', data);
// 接收事件
emitter.on('eventName', (data) => {
// 处理接收到的数据
});
4.hooks
hooks本身是作为组件逻辑、属性的独立封装,具备可复用功能,可以抽离为 hooks 独立文件。
// hooks.ts
import { ref } from 'vue';
// 声明一个响应式数据
export const message = ref('Hello world');
// 在需要使用的地方引入
import {message} from '@/hooks';
// 使用
console.log(message.value);