vue3 - 组件间的传值
组件间传参
父传子v-on/props
父组件使用v-on:
绑定要传的参数:parentData="parentData"
:
<template><div><Child1 :parentData="parentData"></Child1></div>
</template>
<script setup lang="ts">
import Child1 from './components/Child1.vue';
import { ref } from 'vue';const parentData = ref('父级组件参数:parentData');onMounted(() => {
});
</script>
子组件使用props
接收
<template>
<div>父级组件参数:<p>{{ modelValue }}</p><p>{{ parentData }}</p>
</div>
</template>
<script setup lang="ts">
const props = defineProps({modelValue: {type: String,required: false},parentData: {type: String,default: '父级组件参数:default'}
});
</script>
子传父emit
父组件自定义事件changeData
传递给子组件
<template><div><h2>父级组件</h2><Child1 :parentData="parentData" v-model="defaultData" @changeData="changeData"></Child1></div>
</template>
<script setup lang="ts">
import Child1 from './components/Child1.vue';
import { onMounted, reactive, ref, watch } from 'vue';const defaultData = ref('v-model绑定参数:defaultData');
const parentData = ref('父级组件参数:parentData');const changeData = (data: string) => {console.log('子组件传给父组件参数:', data);parentData.value = data;
};
</script>
子组件触发事件将需要传递给父组件的参数给事件,使用defineEmits
接收事件,emit
触发事件。
<template><div><!-- 父组件参数 --><div>父级组件参数:<p>{{ modelValue }}</p><p>{{ parentData }}</p><button @click="emit('changeData', '子组件传给父组件参数')">子组件传给父组件参数</button></div></div>
</template>
<script setup lang="ts">
import { onMounted, reactive, ref, watch } from 'vue';
const props = defineProps({modelValue: {type: String,required: false},parentData: {type: String,default: '父级组件参数:default'}
});/*** 子组件传给父组件参数* 1. 定义事件* 2. 通过emit触发事件* 3. 父组件通过@changeData="changeData"接收事件*/
const emit = defineEmits(['changeData'])
</script>
父传子:依赖/注入:provide/inject
父组件使用provide
定义要传递给后代组件的方法、参数。(当需要给深层的某个子组件传递参数时,使用props
传参需要一层一层的传递,不好维护代码,可使用provide/inject
来实现)
<template><div><h2>父级组件</h2><button @click="provideData = '更新后的父级组件provide参数:provideData'">更新provideData</button><Child1></Child1></div>
</template>
<script setup lang="ts">
import Child1 from './components/Child1.vue';
import { ref, provide } from 'vue';const provideData = ref('父级组件provide参数:provideData');
provide('provideData1', provideData); // 传递响应式参数,父组件更新值,子组件跟着更新数据
provide('provideData2', provideData.value); // 直接传递值,父组件更新后子组件不会更新
</script>
子组件通过inject
<template><div class="child1"><div>父级组件参数:<p>inject:provideData1: {{ provideData1 }}</p><p>inject:provideData2: {{ provideData2 }}</p></div></div>
</template>
<script setup lang="ts">
import { inject, ref } from 'vue';const provideData1 = inject('provideData1');
const provideData2 = inject('provideData2');</script>
<style scoped lang='scss'>
.child1{border: 1px solid #ccc;
}
</style>
状态管理pinia
1.安装:
npm install pinia
2.main.ts
创建一个 pinia 实例 (根 store) 并将其传递给应用
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'const pinia = createPinia()
const app = createApp(App)app.use(pinia)
app.mount('#app')
使用pinia参考地址:https://pinia.vuejs.org/zh/core-concepts/
3.定义store
/src/stores/counter.ts
import { ref, computed } from 'vue'
import { defineStore } from 'pinia'export const useCounterStore = defineStore('counter', () => {const count = ref(0)const name = ref('Eduardo')const doubleCount = computed(() => count.value * 2)function increment() {count.value++}return { count, doubleCount, increment }
})
4.使用
<script setup>
import { useCounterStore } from '@/stores/counter'
// 在组件内部的任何地方均可以访问变量 `store` ✨
const store = useCounterStore()// ❌ 下面这部分代码不会生效,因为它的响应式被破坏了
// 与 reactive 相同: https://vuejs.org/guide/essentials/reactivity-fundamentals.html#limitations-of-reactive
const { name, doubleCount } = store
name // 将会一直是 "Eduardo" //
doubleCount // 将会一直是 0 //
setTimeout(() => {store.increment()
}, 1000)// 这一部分代码就会维持响应式
// 💡 在这里可以直接使用 `store.doubleCount`
const doubleValue = computed(() => store.doubleCount)
</script>
父传子:插槽 Slots
父组件使用slots
传递html代码给子组件显示
<template><div><h2>父级组件</h2><Child1><div><p>父组件代码片段1</p></div><p>父组件代码片段2</p><template #header><p>父组件代码片段3</p></template></Child1></div>
</template>
<script setup lang="ts">
import { te } from 'element-plus/es/locales.mjs';
import Child1 from './components/Child1.vue';
import { ref, provide } from 'vue';
</script>
<template><div class="child1"><slot name="header">子组件头部插槽(具名插槽)</slot><div>子组件内容1</div><slot>子组件默认插槽</slot><div>子组件内容2</div></div>
</template>
<script setup lang="ts">
import { ref } from 'vue'</script>
<style scoped lang='scss'>
.child1 {border: 1px solid #ccc;
}
</style>
父组件中具名插使用<template #插槽名>
,子组件定义<slot name="header"></slot>
,当父组件为给插槽传递内容时,会显示<slot></slot>
标签之间的插槽默认内容,没有则不显示。
子传父:插槽 Slots
子组件定义传递的参数
<template><slot name="header" :count ="1" :text='text1'></slot><slot :count ="2" :text='text2'></slot>
</template>
父组件接收子组件的参数
<template #header="headerProps">{{ headerProps.count }} {{ headerProps.text }}
</template><template #header="{count,text}">{{ count }}{{text}}
</template><!-- 默认插槽 -->
<template v-slot="defaultProps">{{ defaultProps.count }} {{ defaultProps.text }}
</template><template v-slot="{count,text}">{{ count }}{{text}}
</template><template #default="defaultProps">{{ defaultProps.count }} {{ defaultProps.text }}
</template><template #default="{count,text}">{{ count }}{{text}}
</template>
注:这个传参方式主要在封装组件时使用,例如element plus组件中
table
。
父传子
父组件使用子组件暴露的方法,执行方法,将参数传递给方法中
<template><div><Child1 ref='child'></Child1></div>
</template>
<script setup lang="ts">
import Child1 from './components/Child1.vue';
import { ref } from 'vue';const params = ref({name:'',type:''
})
const child = ref(null);onMounted(() => {child.value.open(params.value)
});
</script>
<script setup lang="ts">
const open = (params)=>{console.log('父组件传递的参数:',params)
}// 暴露方法给父组件
defineExpose({open
});
</script>