หมวดหมู่: Programming

Vue.js: TabulatorPlusVue.js: TabulatorPlus

สำหรับการใช้งานใน Vue 3 ( Composition API ) หลักการจะคล้ายกับ React แต่เราจะเปลี่ยนจาก useRef และ useEffect มาใช้ ref และ Lifecycle Hooks ของ Vue อย่าง onMounted และ onBeforeUnmount แทนครับ

นี่คือตัวอย่างการเขียนแบบจัดเต็มที่ครอบคลุมทั้งการสร้าง, การใช้ซ้ำ ( Reused ), การอัปเดต และการล้างหน่วยความจำครับ
UserTable.vue

<template>
  <div class="table-wrapper">
    <div class="controls">
      <button @click="refreshData">Refresh Data</button>
      <button @click="clearTableFilters">Clear Filters</button>
    </div>

    <div ref="tableElement"></div>
  </div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount, watch } from 'vue';
import TabulatorPlus from './TabulatorPlus';
// นำเข้า CSS พื้นฐาน
import "tabulator-tables/dist/css/tabulator.min.css";

// 1. รับ Props จากภายนอก
const props = defineProps({
  tableData: {
    type: Array,
    required: true
  }
});

// 2. กำหนดตัวแปรสำหรับ DOM และ Instance
const tableElement = ref(null);      // เก็บ reference ของ HTML Element
const tabulatorInstance = ref(null); // เก็บ Instance ของ Tabulator (Reused Instance)

// 3. การสร้างตาราง (Initialize) เมื่อ Component Mount
onMounted(() => {
  if (tableElement.value) {
    tabulatorInstance.value = new TabulatorPlus(tableElement.value, {
      data: props.tableData,
      columns: [
        { title: "Name", field: "name", width: 200 },
        { title: "Age", field: "age" },
        { title: "Location", field: "location" },
      ],
    }, "vue-user-settings"); // storageKey สำหรับ persistence
  }
});

// 4. การ Refresh ข้อมูล (เมื่อ Props เปลี่ยนแปลง)
watch(() => props.tableData, (newData) => {
  if (tabulatorInstance.value) {
    // ใช้ .setData() เพื่ออัปเดตข้อมูลเดิม แทนการสร้างตารางใหม่ (ดีต่อ Performance)
    tabulatorInstance.value.setData(newData);
  }
}, { deep: true });

// 5. วิธีเรียกใช้ Method ภายใน Instance (Reused Instance)
const refreshData = () => {
  if (tabulatorInstance.value) {
    // เช่น สั่งวาดตารางใหม่เพื่อให้ขนาดพอดีกับ Container
    tabulatorInstance.value.redraw(true);
  }
};

const clearTableFilters = () => {
  if (tabulatorInstance.value) {
    tabulatorInstance.value.clearFilter(true);
  }
};

// 6. การล้างข้อมูล (Unmount)
onBeforeUnmount(() => {
  if (tabulatorInstance.value) {
    console.log("Destroying Tabulator Instance...");
    // ทำลาย Instance เพื่อป้องกัน Memory Leak
    tabulatorInstance.value.destroy();
    tabulatorInstance.value = null;
  }
});
</script>

<style scoped>
.table-wrapper {
  padding: 1rem;
}
.controls {
  margin-bottom: 1rem;
  display: flex;
  gap: 10px;
}
/* คุณสามารถเพิ่ม CSS เพื่อแต่งตารางที่นี่ได้ */
:deep(.tabulator) {
  border-radius: 4px;
}
</style>

คำอธิบายการทำงาน

  • Reused Instance: เราใช้ const tabulatorInstance = ref(null) เพื่อเก็บตัว Instance ไว้ตลอดอายุของ Component ทำให้เราสามารถเรียกใช้ Method ของ Tabulator ( เช่น .setData(), .redraw(), .getFilters() ) ได้จากทุกฟังก์ชันใน <script setup>
  • Refresh ข้อมูล: ใช้ watch คอยดูการเปลี่ยนแปลงของ props.tableData หากข้อมูลเปลี่ยน เราจะส่งข้อมูลใหม่เข้าตารางทันทีผ่าน .setData() โดยไม่ต้องทำลายและสร้างตารางใหม่ให้หน้าจอกระพริบ
  • Unmount & Cleanup: สำคัญมากสำหรับ Single Page Application (SPA) เราใช้ onBeforeUnmount เพื่อสั่ง .destroy() ตารางเดิมทิ้ง เพื่อคืนค่าหน่วยความจำและล้าง Event Listeners ที่ค้างอยู่ในระบบ
  • CSS Scoping: ใน Vue คุณสามารถใช้ :deep(.tabulator) ในส่วน <style scoped> เพื่อเจาะเข้าไปแต่งสไตล์ของตาราง Tabulator ได้โดยไม่ไปกระทบตารางอื่นในโปรเจกต์

ทิป ( Pro-Tip )

หากคุณใช้ Vue 3 แนะนำให้ใช้ shallowRef แทน ref สำหรับเก็บ tabulatorInstance เพราะ Tabulator เป็น Object ขนาดใหญ่ที่มีความซับซ้อนสูง การให้ Vue เข้าไปทำ Dependency Tracking ( Deep Reactivity ) กับมันอาจทำให้ Performance ตกได้ครับ

import { shallowRef } from 'vue';
const tabulatorInstance = shallowRef(null); // เร็วกว่า ref ปกติในกรณีนี้

อ่านเพิ่มเติม