webpack を使わずに SFC が使いたい! webpack を導入するのは怖いし影響範囲が分からない!
こういう場合に、PHP の include
と JavaScript の innerHTML
を使って SFC のように書き換えてみます。ポイントとしては以下の2箇所になります。
<?php include "components/my-component.php" ?>
import ... from "...";
の代わりに PHP の include
や blade の @include
などを使い、コンポーネントが記述された別の PHP ファイルを読み込みます。
const MyComponent = {
template: document.querySelector('#my-component-template').innerHTML,
...
}
また、 document.querySelector(...).innerHTML
を使って生の HTML からテンプレートを取得することで、テンプレートにシンタックスハイライトが有効になるようにしています。
具体例
例えば以下のような PHP ファイルがあったとします。
<html>
<head>
<title>PHP + Vue Demo</title>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
</head>
<body>
<div id="app">
<h1>PHP + Vue Demo</h1>
<my-component my-fruit="Apple"></my-component>
<my-component my-fruit="Orange"></my-component>
<my-component my-fruit="Strawberry"></my-component>
</div>
<style>
h1 {
color: #FF9900;
}
.fancy-border {
border: red 3px solid;
}
</style>
<script>
const MyComponent = {
props: ['myFruit'],
data() {
return {
myText: '300 yen',
}
},
template: `
<div>
<input type='text' v-model="myText" />
<p class='fancy-border'>
The price of {{myFruit}} is {{myText}}.
</p>
</div>
`
};
const {
createApp
} = Vue
createApp({
components: {
'my-component': MyComponent,
}
}).mount('#app')
</script>
</body>
</html>
問題点
まず問題点として、1つのファイルにコンポーネントが複数あり、1ファイルが長くなってしまうというものが挙げられます。これは PHP の include
や blade の @include
などを使って対処できます。
また、template が文字列となっていてシンタックスハイライトが使えないという問題に関しては、生の HTML にテンプレートを書いておき、 document.querySelector(...).innerHTML
で取得することで解決します。SFC と同じように template タグ を使用できますが、<div style='display:none'>
のように書いても問題ありません。
(なお、Vue では template: ...
の代わりに el: '#app'
のように書くことも出来ますが、この場合はコンポーネントを複数個マウントすることができないので今回は使用できません。)
上記を踏まえてコードを書き換えると以下のようになります。
<template id="my-component-template">
<div>
<input type='text' v-model="myText" />
<p class='fancy-border'>
The price of {{myFruit}} is {{myText}}.
</p>
</div>
</template>
<style>
.fancy-border {
border: red 3px solid;
}
</style>
<script>
const MyComponent = {
props: ['myFruit'],
template: document.querySelector('#my-component-template').innerHTML,
data() {
return {
myText: '300 yen',
}
},
};
</script>
<html>
<head>
<title>PHP + Vue Demo</title>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
</head>
<body>
<?php include "components/my-component.php" ?>
<div id="app">
<h1>PHP + Vue Demo</h1>
<my-component my-fruit="Apple"></my-component>
<my-component my-fruit="Orange"></my-component>
<my-component my-fruit="Strawberry"></my-component>
</div>
<style>
h1 {
color: #FF9900;
}
</style>
<script>
const {
createApp
} = Vue
createApp({
components: {
'my-component': MyComponent,
}
}).mount('#app')
</script>
</body>
</html>
おまけ:CodeSandbox のデモ
今回使ったファイルです。
おわりに
この方法の欠点を挙げると多すぎて書ききれなくなってしまうのでここには書きません。なるべく可能なら .vue
ファイルを使える環境を構築した方がいいと思います。