pnpm+vite+vue3 开发技巧
pnpm+vite+vue3 开发技巧
当一个功能比较复杂时,比如列表的crud操作,特别是列表查询有联动时
- 列表有分页和关键词时,可通过功能将组件拆成若干 展示组件
- 每个展示组件都通过 defineProps 接收状态数据(用于展示,如列表)和行为函数(执行回调,用于将数据传回父组件)
- 然后通过状态组件将多个展示组件组装起来,状态组件中定义状态数据、行为函数等
- 将参与请求的多个参数,组装成一个状态数据对象 requestObj
- 在获取数据的方法里给状态数据对象赋值(当参数变化时)
- 在改变请求参数的地方调用获取数据的方法
案例
- 状态组件 Posts.vue
<script setup>
import request from "@/utils/request.js";
import { ref} from "vue";
import PostCard from "@/components/PostCard.vue";
const posts = ref([]);
const total = ref(100);
const requestObj = ref({
page: 1,
size: 12,
userId: 1,
title: ''
});
function getPosts({page, size, userId, title} = {}) {
page = page || requestObj.value.page;
size = size || requestObj.value.size;
userId = userId || requestObj.value.userId;
title = title || requestObj.value.title;
requestObj.value = {page, size, userId, title};
request('https://jsonplaceholder.typicode.com/posts', {
params: {
'_page': page,
'_limit': size,
'userId': userId,
'title': title,
}
}).then(data => {
posts.value = data;
})
}
function handleSizeChange(val) {
getPosts({...requestObj.value, page: 1, size: val});
}
function handleCurrentChange(val) {
getPosts({...requestObj.value, page: val});
}
function handleWordChange(val) {
getPosts({...requestObj.value, page: 1, words: val});
}
// 初始化请求一次
getPosts();
</script>
<template>
<div>
<el-input v-model="requestObj.title" style="width: 240px" placeholder="Please input" @keyup.enter="handleWordChange" />
<PostCard v-for="post in posts" :key="post.id" :post="post"/>
<el-pagination
v-model:current-page="requestObj.page"
v-model:page-size="requestObj.size"
:page-sizes="[12, 24, 26, 48]"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</template>
<style scoped>
</style>
- 展示组件 PostCard.vue
<template>
<div class="post-card">
<h2 class="post-title">{{ post.title }}</h2>
<div class="post-meta">
<span>用户ID: {{ post.userId }}</span>
<span>文章ID: {{ post.id }}</span>
</div>
<p class="post-body">{{ formattedBody }}</p>
</div>
</template>
<script setup>
import { computed } from 'vue';
const props = defineProps({
post: {
type: Object,
required: true,
default: () => ({
userId: 0,
id: 0,
title: '',
body: ''
})
}
});
const formattedBody = computed(() => {
return props.post.body.replace(/\n/g, '<br>');
});
</script>
<style scoped>
.post-card {
border: 1px solid #eee;
border-radius: 8px;
padding: 16px;
margin: 16px 0;
max-width: 600px;
}
.post-title {
color: #333;
margin-bottom: 8px;
}
.post-meta {
display: flex;
gap: 16px;
margin-bottom: 12px;
color: #666;
font-size: 14px;
}
.post-body {
color: #444;
line-height: 1.6;
white-space: pre-line;
}
</style>
不积跬步无以至千里

浙公网安备 33010602011771号