pnpm+vite+vue3 开发技巧

pnpm+vite+vue3 开发技巧

当一个功能比较复杂时,比如列表的crud操作,特别是列表查询有联动时

  1. 列表有分页和关键词时,可通过功能将组件拆成若干 展示组件
  2. 每个展示组件都通过 defineProps 接收状态数据(用于展示,如列表)和行为函数(执行回调,用于将数据传回父组件)
  3. 然后通过状态组件将多个展示组件组装起来,状态组件中定义状态数据、行为函数等
  4. 将参与请求的多个参数,组装成一个状态数据对象 requestObj
  5. 在获取数据的方法里给状态数据对象赋值(当参数变化时)
  6. 在改变请求参数的地方调用获取数据的方法

案例

  1. 状态组件 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>
  1. 展示组件 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>
posted @ 2025-05-26 14:28  小小爬虫  阅读(41)  评论(0)    收藏  举报