搜索文档
Props 传参
父传子
vue
<script setup lang="ts">
import User from "@/components/User.vue";
</script>
<template>
<User name="iGma" />
</template>vue
<script setup lang="ts">
defineProps(['name'])
</script>
<template>
<p>{{ name }}</p>
</template>子传父
vue
<script setup lang="ts">
import User from "@/components/User.vue";
function getUserData(data: string) {
console.log('子组件返回的数据', data);
}
</script>
<template>
<User name="iGma" :sendData="getUserData" />
</template>vue
<script setup lang="ts">
defineProps(['name', 'sendData'])
</script>
<template>
<p>{{ name }}</p>
<button @click="sendData('子组件数据')">发送数据</button>
</template>自定义事件
自定义事件是由子组件向父组件发射的事件,在发射事件的同时也可传递参数。
vue
<script setup lang="ts">
import User from "@/components/User.vue";
function getUserData(data: string) {
console.log('子组件返回的数据', data);
}
</script>
<template>
<User @getUserData="getUserData" />
</template>vue
<script setup lang="ts">
const event = defineEmits(['getUserData']);
function sendData() {
event('getUserData', 'iGma')
}
</script>
<template>
<button @click="sendData">发送数据</button>
</template>mitt
mitt 适用于任何组件间传递数据,类似于 Vue2 中的全局事件总线。
安装 mitt
sh
npm i mitt创建资源站 @/utils/emitter.ts
ts
import mitt from "mitt";
export default mitt();发送数据组件:App.vue;接收数据组件:User.vue
vue
<script setup lang="ts">
import User from "@/components/User.vue";
import emitter from "@/utils/emitter.ts";
function sendData() {
emitter.emit('appSendData', 'iGma');
}
</script>
<template>
<button @click="sendData">发送数据</button>
<User />
</template>vue
<script setup lang="ts">
import emitter from "@/utils/emitter.ts";
import {onUnmounted} from "vue";
emitter.on('appSendData', (data) => {
console.log('data', data);
})
onUnmounted(() => {
emitter.off('appSendData');
})
</script>
<template></template>v-model
双向绑定语法,即可以子传父,也可父传子。
vue
<script setup lang="ts">
import iGmaInput from "@/components/iGmaInput.vue";
import {ref} from "vue";
let msg = ref();
</script>
<template>
<iGmaInput v-model="msg" />
</template>vue
<script setup lang="ts">
defineProps(['modelValue']);
const emit = defineEmits(['update:modelValue']);
</script>
<template>
<input
:value="modelValue"
@input="emit('update:modelValue', (<HTMLInputElement>$event.target).value)"
/>
</template>在自定义组件中使用 v-model 默认会给子组件传入一个 modelValue 属性,同时通过 update:modelValue 返回数据。也可以通过 v-model:xxx 传递多组双向绑定数据。
vue
<script setup lang="ts">
import iGmaInput from "@/components/iGmaInput.vue";
import {ref} from "vue";
let account = ref();
let password = ref();
</script>
<template>
<iGmaInput v-model:account="account" v-model:password="password" />
</template>vue
<script setup lang="ts">
defineProps(['account', 'password']);
const emit = defineEmits(['update:account', 'update:password']);
</script>
<template>
<input
:value="account"
@input="emit('update:account', (<HTMLInputElement>$event.target).value)"
/>
<input
:value="password"
@input="emit('update:password', (<HTMLInputElement>$event.target).value)"
/>
</template>$attrs
适用于祖孙之间传递数据,在父组件中实现过度即可。
vue
<script setup lang="ts">
import A from "@/components/A.vue";
import {reactive} from "vue";
let data = reactive({a: 1, b: 2, c: 3});
</script>
<template>
<A v-bind="data" />
</template>vue
<script setup lang="ts">
import B from "@/components/B.vue";
</script>
<template>
<B v-bind="$attrs" />
</template>vue
<script setup lang="ts">
defineProps(['a', 'b', 'c']);
</script>
<template>
<p>a: {{ a }}</p>
<p>b: {{ b }}</p>
<p>c: {{ c }}</p>
</template>$refs 和 $parent
父操作子数据 $refs
vue
<script setup lang="ts">
import User from "@/components/User.vue";
function updateUserData(refs:any) {
refs['userRef'].info.age += 5;
}
</script>
<template>
<User ref="userRef" />
<button @click="updateUserData($refs)">修改子组件的数据</button>
</template>vue
<script setup lang="ts">
import {reactive} from "vue";
let info = reactive({name: 'iGma', age: 18});
defineExpose({info}); // 对外暴露
</script>
<template>
<p>姓名: {{info.name}}</p>
<p>年龄: {{info.age}}</p>
</template>子修改父数据 $parent
vue
<script setup lang="ts">
import User from "@/components/User.vue";
import {reactive} from "vue";
let data = reactive({name: 'iGma', age: 18});
defineExpose({data})
</script>
<template>
<p>姓名: {{data.name}}</p>
<p>年龄: {{data.age}}</p>
<User />
</template>vue
<script setup lang="ts">
function updateParentData(parent: any) {
parent.data.age += 5;
}
</script>
<template>
<button @click="updateParentData($parent)">修改父组件数据</button>
</template>Provide 和 Inject
适用于祖孙之间传递数据,不同于 $attrs 的是,通过 provide 和 inject 可以不打扰中间的组件,同时只要组件中使用 provide 发送数据后,组件的所有后辈组件都可以使用 inject 接收。
vue
<script setup lang="ts">
import A from "@/components/A.vue";
import {provide, ref} from "vue";
let name = ref('iGma');
let age = ref(18);
// 向后代提供数据
provide('name', name);
provide('age', age);
</script>
<template>
<A />
</template>vue
<script setup lang="ts">
import B from "@/components/B.vue";
</script>
<template>
<B />
</template>vue
<script setup lang="ts">
import {inject} from "vue";
// 接收祖辈传来的数据
let name = inject('name', '无名氏');
let age = inject('age', 20);
</script>
<template>
<p>姓名: {{name}}</p>
<p>年龄: {{age}}</p>
<button @click="age++">修改年龄</button>
</template>插槽
默认插槽
vue
<script setup lang="ts">
import User from "@/components/User.vue";
</script>
<template>
<User>
<h2>iGma</h2>
</User>
</template>vue
<script setup lang="ts">
</script>
<template>
<div class="user">
<slot />
</div>
</template>具名插槽
vue
<script setup lang="ts">
import User from "@/components/User.vue";
</script>
<template>
<User>
<template #s1>
<h2>姓名:iGma</h2>
</template>
<template #s2>
<h2>年龄:18</h2>
</template>
</User>
</template>vue
<script setup lang="ts">
</script>
<template>
<div class="user">
<slot name="s1"/>
<slot name="s2"/>
</div>
</template>作用域插槽
vue
<script setup lang="ts">
import User from "@/components/User.vue";
</script>
<template>
<User>
<template #s1="{hobby}">
<ul>
<li v-for="(item, index) in hobby" :key="index">{{item}}</li>
</ul>
</template>
</User>
<User>
<template #s1="{hobby}">
<ol>
<li v-for="(item, index) in hobby" :key="index">{{item}}</li>
</ol>
</template>
</User>
</template>vue
<script setup lang="ts">
import {reactive} from "vue";
let hobby = reactive(['抽烟', '喝酒', '烫头']);
</script>
<template>
<div class="user">
<slot name="s1" :hobby="hobby"/>
</div>
</template>