/
CATEGORY
Vue
/
如何在 Vue.js 中不使用 CSS 框架(ex.Element Plus ),自行寫出表格和分頁功能

如何在 Vue.js 中不使用 CSS 框架(ex.Element Plus ),自行寫出表格和分頁功能

MUKI AI Summary

JavaScript 和 CSS 框架常被用來加速網站開發,但不一定需要使用。Vue.js 可以不依賴 CSS 框架,自行實現表格和分頁功能。首先安裝 vue-router,設定路由。接著可使用假資料或 API 取得資料,並在表格中顯示第一頁內容。使用 vue-router 實現頁碼,透過 query 參數控制頁面顯示。監聽 route.query.page 變化,根據新頁碼更新資料。完整範例可在線上 DEMO 網址查看,提供了無需 CSS 框架的實作方式。...

前言

JavaScript 框架與 CSS 框架的相輔相成,為我們開發網站提供了許多便利性的幫助,但也許你偶爾會想著:「我們用 Vue.js 後,一定要使用對應的 CSS 框架才能做網站嗎?」

答案當然是否定的!畢竟 CSS 框架只是一個工具,他的優點是加速我們的設計與開發,但沒有了他,我們一樣能寫出具有特色的網站。

以我為例,我曾經用 Vue.js 寫一個網站後台,只用到 TailwindCSS,沒有用 Element Plus 這類的 CSS 框架,今天想跟大家分享的就是該網站的精華,第一篇就是如何自己寫出表格與分頁的功能。

步驟一:安裝 vue-router

首先,還是需要安裝 vue-router 套件,並且設定路由,這邊讓我們快速處理:

$ npm install vue-router@4

▼ 我建立了檔案 TablePagination.vue,並設定路由為 /tablepagination

import { createRouter, createWebHistory } from 'vue-router'

const routes = [
  {
    path: '/tablepagination',
    name: 'TablePagination',
    component: () => import('./views/TablePagination.vue')
  }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router

步驟二:取得資料(假資料或 API 皆可)

我這邊會用假資料為例,但不管你是想要測試,或是已經有現成的 API 資料可撈取,都可以用類似的方式做到。

▼ 我用亂數產生了一些資料,並且模擬 API 回傳的格式如下

<script setup lang="ts">
import { reactive } from 'vue'

// 產生假資料
const randomData = (s: number, n: number) => {
  return Array.from({ length: n }, () => ({
    id: s++,
    name: `MUKI_${s}`,
    age: Math.floor(Math.random() * 100)
  }))
}

// 模擬 API 回傳的資料格式,包含頁碼
const data = reactive({
  pages: {
    limit: 12,
    total_page: 5,
    now_page: 1
  },
  details: randomData(0, 12)
})
</script>

步驟三:在表格顯示第一頁的內容

▼ 在表格顯示 data.details 的資料,這是第一個客製化,用 <table> 標籤以及 v-for 語法就能做到。此外我用了 TailwindCSS 幫我快速處理樣式,如果你沒有用 TailwindCSS,可以把 class 內的資料改成你自己的設定

<table v-if="data.details.length > 0">
    <thead>
      <tr class="text-left border-b border-gray-300">
        <th class="w-28 py-1">ID</th>
        <th class="w-28 py-1">Name</th>
        <th class="w-28 py-1">Age</th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="item in data.details" :key="item.id" :class="{ 'bg-gray-200': item.id % 2 === 1  }">
        <td class="py-1">{{ item.id }}</td>
        <td class="py-1">{{ item.name }}</td>
        <td class="py-1">{{ item.age }}</td>
      </tr>
    </tbody>
  </table>

▼ 呈現在表格的樣子

步驟四:使用 vue-router 製作頁碼

▼ 先做好頁碼的樣式

<template>
<ol v-if="data.pages.total_page > 1" class="flex mt-10">
  <li class="px-4">
    第一頁
  </li>
  <li v-for="item in data.pages.total_page" :key="item" class="px-4" :class="{ current: item === current }">
    {{ item }}
  </li>
  <li class="px-4">
    最後一頁
  </li>
</ol>
</template>


<style lang="postcss" scoped>
.current {
  @apply rounded-lg text-white bg-orange-500;
}
</style>

▼ 這個頁碼有「第一頁」以及「最後一頁」,另外會根據 data 裡的 total_page 顯示所有的頁碼

接著,我們可以使用 <router-link>qeury 帶入參數 page 以及頁碼 (1, 2, 3, 4...),query 同時會更改網址;舉例來說:如果想分享第二頁的內容,就能直接複製網址,對方貼上後,會跳到第二頁並顯示該內容。

▼ 切到第二頁,網址也會跟著改變

▼ 使用 <router-link>query 製作該功能

<!-- 第一頁是固定的參數,所以 page 帶 1 -->
<router-link :to="{ query: { page: 1 } }">第一頁</router-link>

<!-- 根據 total_page 跑迴圈的頁碼,page 帶 item 變數  -->
<li v-for="item in data.pages.total_page" :key="item" class="px-4" :class="{ current: item === current }">
  <router-link :to="{ query: { page: item } }">{{ item }}</router-link>
</li>

<!-- 最後一頁是總頁數,page 帶 total_page -->
<router-link :to="{ query: { page: data.pages.total_page } }">最後一頁</router-link>

▼ 再來監聽 route.query.page 的變化,根據新頁碼帶對應的 API 資料,但我沒有串 API,所以用模擬資料的函式 randomData(),抓新的資料至 data.details

<script setup lang="ts">
import { watch } from 'vue'
  
watch(() => route.query.page, (newPage) => {
  /* route.query.page 變化時,current 的值也會跟著改變,讓當前頁有不同的樣式 */
  current.value = Number(newPage) || 1
  data.details = randomData(0, 12)
})
</script>

完整範例

▼ 完整的 TablePagination.vue

<template>
  <table v-if="data.details.length > 0">
    <thead>
      <tr class="text-left border-b border-gray-300">
        <th class="w-28 py-1">ID</th>
        <th class="w-28 py-1">Name</th>
        <th class="w-28 py-1">Age</th>
      </tr>
    </thead>
    <tbody>
      <tr
        v-for="item in data.details"
        :key="item.id"
        :class="{
          'bg-gray-200': item.id % 2 === 1
        }"
      >
        <td class="py-1">{{ item.id }}</td>
        <td class="py-1">{{ item.name }}</td>
        <td class="py-1">{{ item.age }}</td>
      </tr>
    </tbody>
  </table>

  <ol v-if="data.pages.total_page > 1" class="flex mt-10">
    <li class="px-4">
      <router-link :to="{ query: { page: 1 } }">第一頁</router-link>
    </li>
    <li
      v-for="item in data.pages.total_page"
      :key="item"
      class="px-4"
      :class="{ current: item === current }"
    >
      <router-link :to="{ query: { page: item } }">{{ item }}</router-link>
    </li>
    <li class="px-4">
      <router-link :to="{ query: { page: data.pages.total_page } }">最後一頁</router-link>
    </li>
  </ol>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, watch } from 'vue'
import { useRoute } from 'vue-router'

const current = ref(1)
const route = useRoute()

const randomData = (s: number, n: number) => {
  return Array.from({ length: n }, () => ({
    id: s++,
    name: `MUKI_${s}`,
    age: Math.floor(Math.random() * 100)
  }))
}
const data = reactive({
  pages: {
    limit: 12,
    total_page: 5,
    now_page: 1
  },
  details: randomData(0, 12)
})

onMounted(() => {
  current.value = Number(route.query.page) || 1
})

watch(
  () => route.query.page,
  (newPage) => {
    current.value = Number(newPage) || 1
    data.details = randomData(0, 12)
  }
)
</script>

<style lang="postcss" scoped>
.current {
  @apply rounded-lg text-white bg-orange-500;
}
</style>

➩➩ 線上 DEMO 網址: https://lfdt4x-5173.csb.app/tablepagination?page=1

▼ codesandbox 範例

歡迎給我點鼓勵,讓我知道你來過 :)

20
MUKI says:

如果文章有幫助到你,歡迎分享給更多人知道。文章內容皆為 MUKI 本人的原創文章,我會經常更新文章以及修正錯誤內容,因此轉載時建議保留原出處,避免出現版本不一致或已過時的資訊。

本文地址:https://muki.tw/create-tables-pagination-in-vue-js-without-using-css-framework/ 已複製

Subscribe
Notify of
guest

0 則留言
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Copyright © since 2008 MUKI space* / omegaSS theme All Rights Reserved.