環境
このページで使用しているフレームワークやライブラリのバージョンは、以下のとおりです。
vue.js | 3.2.31 |
vue3-sfc-loader | 0.8.4 |
Vueのコンポーネントとは?
Vueでは、大きなアプリケーション(下図の左側)を小さな部品の組み合わせで構成(下図の右側)することができます。
この小さな部品(下図の緑色の箱)に相当するのがコンポーネントです。
詳しくは、Vueの公式ドキュメント「コンポーネントによる構成」を参照してください。
単一ファイルコンポーネントとは?
単一ファイルコンポーネント(Single-File Component:以後SFCと呼ぶ)は、Vueを使う上で、とても便利な仕組みです。
SFCは、下図のように、「JavaScript:<script>タグ」「HTML:<template>タグ」「CSS:<style>タグ」を1つにまとめて記述したファイルのことです。
このファイルの拡張子は「*.vue」で、SFCのことを、別名「*.vue」ファイルということがあります。
SFCの「JavaScript:<script>タグ」でコンポーネントの動作や処理を記述することができ、「HTML:<template>タグ」「CSS:<style>タグ」でコンポーネントの外観を指定することができます。
つまり、「*.vue」ファイル1つで、コンポーネントの動作と外観が規定できるということです。
大きなアプリケーションを小さなコンポーネントに分解すれば、ソースコードの可読性も上がりますし、メンテナンスも容易になります。
また、このSFCに汎用性を持たせて、再利用できるように作っておけば、いろいろなアプリケーションで流用できます。
ブラウザ環境で単一ファイルコンポーネントを使うには?
とっても便利なSFCなのですが、ブラウザ環境で動作するJavaScriptでは、「*.vue」ファイルをそのまま読み込むことができません。
Vueの便利な機能の1つであるSFCが使えないのは、とても残念です。
ところが、「vue3-sfc-loader」というライブラリを使えば、ブラウザ環境でも「*.vue」ファイルを直接読み込んで、SFCの仕組みを活用することができます。
Vue3/Vue2 Single File Component loader.
Load .vue files dynamically at runtime from your html/js. No node.js environment, no (webpack) build step needed.
上記「vue3-sfc-loader」の概要にも書いてあるように、"No node.js environment, no (webpack) build step needed."、つまり、「Node.js」も「webpack」も無いブラウザ環境で、VueのSFCを使えるようになります。
ブラウザ環境で、SFCがサクッと使えるようになると、WordPressサイトのような「Node.js」の無い環境で、Vueの便利さと簡便さが最大限発揮できると思います。
「vue3-sfc-loader」のオプションを工夫すると、読み込んだ「*.vue」ファイルから、別の「*.vue」ファイルを読み込んだり、外部サイトのJavaScriptライブラリをインポートすることもできます。
「vue3-sfc-loader」の使い方
実際に、「vue3-sfc-loader」を使って、SFCを読み込んでみましょう。
どうでしょうか?
赤い文字で「Hello World!」と表示されましたか?
「Hello World!」と表示されている部分には、WordPressのブロックエディタで「カスタム HTML」ブロックを配置しています。
「カスタム HTML」ブロックには、以下の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: {
"hello-world": Vue.defineAsyncComponent(() =>
loadModule(
"../wp-content/themes/cocoon-child-master/vue-components/hello_world.vue",
vue3_sfc_loader_options
)
),
},
template: `<hello-world />`,
});
app.mount("#app");
</script>
コードの解説
では、コードの中身を解説します。
<script src="https://cdn.jsdelivr.net/npm/vue@3.2.31/dist/vue.global.js"></script>
VueをCDNサイト「https://cdn.jsdelivr.net」からインポートします。
"vue@3.2.31"なので、メジャーバージョンが「3」です。
なので、Vue3を読み込んでいます。
投稿やページの最初に1回インポートすれば、それ以降、Vueのメソッド(関数)は、"Vue.createApp();"のように「Vue.func()」で利用できます。
<div id="app"></div>
Vueのアプリケーションインスタンスをマウントする<div>タグを"app"というidで配置します。
この<div>要素が、この後に読み込むSFC、"hello_world.vue"で置き換えられます。
<script type="module">
…
<script>
<script type="module">~</script>が、SFCを読み込むJavaScriptになります。
JavaScriptでimport文を使うので、「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」をCDNサイト「https://cdn.jsdelivr.net」からインポートします。
ファイル名が"vue3-sfc-loader.esm.js"になっていて、"esm"という文字列が入っています。
これは、import文でインポートできる「ESモジュール」であることを示しています。
////////////////////////////////////////////////////////////////////////////////
// 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);
},
};
"vue3_sfc_loader_options"は、「vue3-sfc-loader」でSFCを読み込むときのオプションです。
読み込んだSFCファイルから外部のモジュールをimportできるオプションになっています。
////////////////////////////////////////////////////////////////////////////////
// Vue.js アプリケーションインスタンス
////////////////////////////////////////////////////////////////////////////////
const app = Vue.createApp({
components: {
"hello-world": Vue.defineAsyncComponent(() =>
loadModule(
"../wp-content/themes/cocoon-child-master/vue-components/hello_world.vue",
vue3_sfc_loader_options
)
),
},
template: `<hello-world />`,
});
app.mount("#app");
"Vue.createApp"で、Vueのアプリケーションインスタンスを作成した後、"app.mount("#app");"で、最初に作成した<div>タグに、作成したアプリケーションインスタンスをマウントしています。
loadModule(
"../wp-content/themes/cocoon-child-master/vue-components/hello_world.vue",
vue3_sfc_loader_options
)
「vue3-sfc-loader」の"loadModule"関数で、SFCファイルを読み込みます。
今回は、"hello_world.vue"という名前のSFCファイルを"../wp-content/themes/cocoon-child-master/vue-components/"フォルダの下に置いています。
「ちょいプラ素材」のブログは、WordPressのテーマに「Cocoon」を使っています。
なので、「Cocoon」の子テーマ「cocoon-child-master」の下に"vue-components"というフォルダを作りました。
components: {
"hello-world": Vue.defineAsyncComponent(() =>
読み込んだSFCは、"hello-world"という名前のコンポーネントになります。
template: `<hello-world />`,
"hello-world"コンポーネントを<hello-world>タグでHTML要素として配置します。
"hello_world.vue"の中身
"hello_world.vue"の中身は、Vueの公式ガイド「単一ファイルコンポーネント」で紹介されている単純なテンプレート構文の例のSFCです。
<script>
export default {
data() {
return {
greeting: 'Hello World!'
}
}
}
</script>
<template>
<p class="greeting">{{ greeting }}</p>
</template>
<style>
.greeting {
color: red;
font-weight: bold;
}
</style>
"greeting"というテンプレートを"color: red;"と"font-weight: bold;"のスタイルで表示するというものです。
"greeting"というテンプレートの文字列は、"Hello World!"です。
まとめ
「vue3-sfc-loader」ライブラリを使えば、WordPressの「カスタム HTML」ブロックから、VueのSFCを読み込むことができます。
「カスタム HTML」ブロックには、SFCのロード処理だけを書いて、実際にやりたい表示や処理は、SFC(1つの「*.vue」ファイル)にまとめることができます。
さらに凝った表示や処理をさせたい場合は、適宜、いくつかのSFCに分割すれば良いでしょう。
この方法で、WordPressサイトに簡単にVueを導入し、WordPressサイトのページ中に、複雑な表示や処理を実装することができます。
次は、もう少し面白いSFCの例として、WordPressの投稿に「Chart.js」のチャート(グラフ)を表示してみましょう。
コメント