不管是套用多少层的组件,它的参数传递都是相通的。
如果是父组件往子组件里传递参数,就用属性进行传递,如果是点击操作,就是emit方法传递。当子组件的点击,传递的内容是自身的组件里的内容,不涉及父组件的内容,就无需使用emit方法,直接在子组件里提交数据即可。
创建子组件Form文件夹,里面有两个子组件index.vue和input.vue:
components/Tweet/Form/Input.vue
<template>
<div>
<div class="flex items-center flex-shrink-0 p-4 pb-0">
<div class="flex w-12 items-start">
<UAvatar :src="user?.profileImage" />
</div>
<div class="w-full p-2">
<UTextarea v-model="text" />
</div>
</div>
<UButton label="发布" @click="handleFormSubmit" />
</div>
</template>
<script setup lang="ts">
const { postTweet } = useTweets();
/**
* 属性
*/
type Props = { user: any };
defineProps<Props>();
const text = ref('');
// const emit = defineEmits<{ (e: 'submit', data: any): void }>();
const emit = defineEmits(['onSubmit']);
async function handleFormSubmit() {
// emit('onSubmit', {
// text: text.value,
// });
// alert(JSON.stringify({text:text.value}));
try {
const response = await postTweet({ text: text.value });
console.log(response);
} catch (error) {
console.log(error);
}
}
</script>
components/Tweet/Form/index.vue
<template>
<div>
<TweetFormInput :user="user" />
</div>
</template>
<script setup lang="ts">
const { postTweet } = useTweets();
/**
* 属性
*/
type Props = { user: any };
defineProps<Props>();
async function handleFormSubmit(formData: any) {
// 提交表单
try {
const response = await postTweet(formData);
console.log(response);
} catch (error) {
console.log(error);
}
}
</script>
然后就是Form里的index.vue组件添加到页面里,调用这个组件。因为子组件input.vue里,就是一个输入文本框,加上图形和按钮:
图像是当前登录用户的属性里面的profileImage的值,需要设置成属性,传递到外面,最终由页面里获取user的值,传递到组件index.vue,再传递给子组件input.vue里。
pages/index.vue
<template>
<div :class="['font-normal', { 'bg-black text-white': false }]">
<div v-if="isAuthLoading">
<AppLoadingPage />
</div>
<!-- main -->
<div v-else-if="user">
<MainSection>
<TweetForm :user="user" />
</MainSection>
</div>
<!-- 登录页面 -->
<div v-else>
<AppAuthPage />
</div>
</div>
</template>
<script setup lang="ts">
useHead({
title: '首页',
});
/**
* user
* 判断是否从后台获取用户信息
* 如果没有,则显示登录页面
* useAuthUser
*/
const { useAuthUser, initAuth, useAuthLoading } = useAuth();
const user = useAuthUser();
const isAuthLoading = useAuthLoading();
onBeforeMount(() => {
initAuth();
});
</script>
<style lang="postcss" scoped>
.center-box {
@apply flex items-center justify-center;
}
.tt {
animation: mask 12s ease infinite forwards;
}
</style>
当然,也可以在子组件input.vue里获取user的值,就不需要添加属性了,直接赋值操作。
当点击按钮提交时,即可存储到数据库当中去:
添加到数据库的方法,直接写在composables方法组件里:
composables/useFetchApi.ts
export default (
url: string,
options: {
headers?: Record<string, string>;
method?: 'GET' | 'POST' | 'PUT' | 'DELETE';
body?: any;
} = {},
) => {
const { useAuthToken } = useAuth();
return $fetch(url, {
...options,
headers: {
...(options.headers || {}),
Authorization: `Bearer ${useAuthToken().value}`,
},
});
};
composables/useTweets.ts
export default () => {
const postTweet = (formData: any) => {
const form = new FormData();
form.append('text', formData.text);
return useFetchApi('/api/user/tweets', {
method: 'POST',
body: form,
});
};
return {
postTweet,
};
};