環境
このページで使用しているフレームワークやライブラリのバージョンは、以下のとおりです。
vue.js | 3.2.31 |
vue3-sfc-loader | 0.8.4 |
vue-good-table-next | 0.1.0 |
vue-good-table-nextとは?
「vue-good-table-next」は、ソート、ページネーション、フィルターなどの機能をもったテーブルを実装できるVueライブラリです。
「vue-good-table-next」は、「Vue2.x」で動作する「vue-good-table」を「Vue3.x」に対応させたバージョンです。
GitHub(2024年7月25日時点)の「vue-good-table-next」バージョンは「0.1.0」で、"README"にも以下の注意書きがあります。
This project is a port of Vue-good-table for Vue 3.x. The current version is stable enough to start developing new projects but work is still in progress and changes could be made in the short-term. Thus the project is not yet intended to be used in a production environment.
ただ、基本的な動作は安定しているようです。
テーブル用ライブラリの比較
多機能なテーブルを実装するためのライブラリやプラグインは、以下のようにいろいろ提供されています。
この記事では「vue-good-table-next」を紹介しますが、各種のライブラリの特徴を比較表にまとめました。(2024年7月25日時点)
なお、この比較表は、「vue-good-table-next」をインポートしたSFCで表示しています。
カスタマイズの自由度では「vue-tables2(v-tables3)」が優れているのですが、Vue3の対応が不完全なので、総合的に「vue-good-table-next」を選びました。
WordPressの投稿でvue-good-table-nextを使う
上記の各種ライブラリの比較表の部分には、WordPressのブロックエディタで以下の「カスタム HTML」ブロックを配置しています。
<script src="https://cdn.jsdelivr.net/npm/vue@3.2.31/dist/vue.global.js"></script>
<div id="app"></div>
<script type="module">
////////////////////////////////////////////////////////////////////////////////
// vue3-sfc-loader モジュール
////////////////////////////////////////////////////////////////////////////////
import { loadModule } from "https://cdn.jsdelivr.net/npm/vue3-sfc-loader@0.8.4/dist/vue3-sfc-loader.esm.js";
////////////////////////////////////////////////////////////////////////////////
// vue3-sfc-loader オプション
// SFCファイルから外部のモジュールをimportできるオプション
// 参考:https://github.com/FranckFreiburger/vue3-sfc-loader/issues/14#issuecomment-908849863
////////////////////////////////////////////////////////////////////////////////
const vue3_sfc_loader_options = {
moduleCache: { vue: Vue },
getFile(url) {
url = /.*?\.js|.mjs|.css|.less|.vue$/.test(url)
? url
: `${url}.vue`;
const type = /.*?\.js|.mjs$/.test(url)
? ".mjs"
: /.*?\.vue$/.test(url)
? ".vue"
: /.*?\.css$/.test(url)
? ".css"
: ".vue";
const getContentData = (asBinary) =>
fetch(url).then((res) =>
!res.ok
? Promise.reject(url)
: asBinary
? res.arrayBuffer()
: res.text()
);
return { getContentData: getContentData, type: type };
},
addStyle(textContent) {
let styleElement = document.createElement("style");
document.head.insertBefore(
Object.assign(styleElement, { textContent }),
document.head.getElementsByTagName("style")[0] || null
);
},
handleModule(type, getContentData, path, options) {
switch (type) {
case ".css":
return options.addStyle(getContentData(false));
case ".less":
console.error(".......");
}
},
log(type, ...args) {
console.log(type, ...args);
},
};
////////////////////////////////////////////////////////////////////////////////
// Vue.js アプリケーションインスタンス
////////////////////////////////////////////////////////////////////////////////
const app = Vue.createApp({
components: {
"table-library-comparison-table": Vue.defineAsyncComponent(() =>
loadModule(
"../wp-content/themes/cocoon-child-master/vue-components/table_library_comparison_table.vue",
vue3_sfc_loader_options
)
),
},
template: `<table-library-comparison-table />`,
});
app.mount("#app");
</script>
いつものように、「vue3-sfc-loader」で"table_library_comparison_table.vue"を読み込んでいます。
“table_library_comparison_table.vue”の中身
"table_library_comparison_table.vue"の全体です。
<script setup>
////////////////////////////////////////////////////////////////////////////////
// vue-good-table-next モジュール
////////////////////////////////////////////////////////////////////////////////
import { VueGoodTable } from "https://cdn.jsdelivr.net/npm/vue-good-table-next@0.1.0/dist/vue-good-table.cjs.min.js";
////////////////////////////////////////////////////////////////////////////////
// data
////////////////////////////////////////////////////////////////////////////////
const table_columns = [
{
label: "比較項目",
field: "comparison_items",
thClass: "vgt-center-align vgt-comparison-items",
tdClass: "vgt-center-align vgt-comparison-items",
sortable: true,
html: true,
},
{
label: "vue-good-table-next",
field: "vue_good_table_next",
thClass: "vgt-center-align vgt-vue-good-table-next",
tdClass: "vgt-center-align vgt-vue-good-table-next",
html: true,
},
{
label: "vue-tables2",
field: "vue_tables2",
thClass: "vgt-center-align vgt-vue-tables2",
tdClass: "vgt-center-align vgt-vue-tables2",
html: true,
},
{
label: "Vuetable-2",
field: "vuetable_2",
thClass: "vgt-center-align vgt-vuetable-2",
tdClass: "vgt-center-align vgt-vuetable-2",
html: true,
},
{
label: "Grid.js",
field: "grid_js",
thClass: "vgt-center-align vgt-grid-js",
tdClass: "vgt-center-align vgt-grid-js",
html: true,
},
];
const table_rows = Vue.ref([]);
const search_options = {
enabled: true,
trigger: "enter",
placeholder: "テーブルを検索します",
};
const sort_options = {
enabled: false,
};
const pagination_options = {
enabled: true,
mode: "pages",
perPage: -1, // -1のときは全項目
position: "top",
perPageDropdown: [3, 5],
dropdownAllowAll: true,
setCurrentPage: 1,
nextLabel: "次へ",
prevLabel: "前へ",
rowsPerPageLabel: "1ページに表示する比較項目数",
ofLabel: " / ",
pageLabel: "ページ", // for 'pages' mode
allLabel: "全項目",
};
////////////////////////////////////////////////////////////////////////////////
// onMountedライフサイクルフック
////////////////////////////////////////////////////////////////////////////////
Vue.onMounted(() => {
table_rows.value = [
{
comparison_items: "Vue3対応",
vue_good_table_next: "〇<br>基本的な動作は安定",
vue_tables2: "<span style='font-size: 1.2em;'>△</span><br>v-tables3で対応しているが不完全",
vuetable_2: "<span style='font-size: 1.8em;'>×</span>",
grid_js: "〇<br>オリジナルがJavaScriptライブラリなので、Vue3のコンポーネントでラップ可能"
},
{
comparison_items: "ソート",
vue_good_table_next: "〇",
vue_tables2: "〇",
vuetable_2: "〇",
grid_js: "〇"
},
{
comparison_items: "ページネーション",
vue_good_table_next: "〇",
vue_tables2: "〇",
vuetable_2: "〇",
grid_js: "〇"
},
{
comparison_items: "グループ表示",
vue_good_table_next: "〇",
vue_tables2: "<span style='font-size: 1.2em;'>◎</span><br>指定の要素で自動的にグループ化",
vuetable_2: "?",
grid_js: "<span style='font-size: 1.8em;'>×</span>"
},
{
comparison_items: "ヘッダー/セルの<br>HTML対応",
vue_good_table_next: "〇",
vue_tables2: "〇",
vuetable_2: "〇",
grid_js: "〇"
},
{
comparison_items: "テーブル構成の<br>カスタマイズ",
vue_good_table_next: "〇<br>ある程度可能",
vue_tables2: "<span style='font-size: 1.2em;'>◎</span><br>カスタムテンプレートで自由度大",
vuetable_2: "?",
grid_js: "<span style='font-size: 1.8em;'>×</span>"
},
];
});
</script>
<template>
<VueGoodTable v-bind:columns="table_columns" v-bind:rows="table_rows" v-bind:search-options="search_options"
v-bind:sort-options="sort_options" v-bind:pagination-options="pagination_options">
<template #table-column="props">
<span v-if="props.column.label == 'vue-tables2'">
{{ props.column.label }}<br>(v-tables3)
</span>
<span v-else>
{{ props.column.label }}
</span>
</template>
</VueGoodTable>
</template>
<style>
@import "https://cdn.jsdelivr.net/npm/vue-good-table-next@0.1.0/dist/vue-good-table-next.css";
table.vgt-table th,
table.vgt-table td {
vertical-align: middle !important;
}
th.vgt-comparison-items {
min-width: 10em !important;
}
th.vgt-vue-good-table-next,
th.vgt-vue-tables2,
th.vgt-vuetable-2,
th.vgt-grid-js {
min-width: 15em !important;
}
td.vgt-vue-good-table-next,
td.vgt-vue-tables2,
td.vgt-vuetable-2,
td.vgt-grid-js {
font-size: 0.8em;
}
</style>
////////////////////////////////////////////////////////////////////////////////
// vue-good-table-next モジュール
////////////////////////////////////////////////////////////////////////////////
import { VueGoodTable } from "https://cdn.jsdelivr.net/npm/vue-good-table-next@0.1.0/dist/vue-good-table.cjs.min.js";
"vue-good-table-next"モジュールをCDNサイト「https://cdn.jsdelivr.net」からインポートします。
<template>
<VueGoodTable v-bind:columns="table_columns" v-bind:rows="table_rows" v-bind:search-options="search_options"
v-bind:sort-options="sort_options" v-bind:pagination-options="pagination_options">
<template #table-column="props">
<span v-if="props.column.label == 'vue-tables2'">
{{ props.column.label }}<br>(v-tables3)
</span>
<span v-else>
{{ props.column.label }}
</span>
</template>
</VueGoodTable>
</template>
インポートした"VueGoodTable"を<template>タグで配置します。
基本は、作成したSFCのローカル変数を"VueGoodTable"のプロパティーにバインドしているだけですが、
<template #table-column="props">
…
</template>
の部分については、「vue-good-table-next」の公式ドキュメントの「Custom column headers」を参照してください。
また、テーブルのコンテンツ("table_rows")は、あえて"Vue.onMounted();"の中で設定しました。
実際の用途では、"table_rows"を動的に変更すると、テーブルのコンテンツがリアクティブに再表示されます。
まとめ
「vue-good-table-next」を使うと、WordPressの投稿に多機能なテーブルを手軽に実装できます。
しかも、Vueを使っているので、テーブルのコンテンツも簡単に更新/再表示ができます。
コメント