従来は、三重中括弧の mustaches で HTMLタグを表示することができました。
{{{ html }}}
ただ、Vue 2系から三重の中括弧が利用できなくなったようです。
三重中括弧のの代わりに v-html ディレクティブを利用します。
ただし、利用する場合は XSSの脆弱性があるので、信頼できるサイトのみで利用しましょう。
Laravel 環境で Nuxt.js を利用してみたいと思います。
npm など基本的な環境がインストールされていることを前提とします。
基本的な情報は、以下のサイトを参考にすると良いでしょう。
https://ja.nuxtjs.org/guide/installation
$ npm install nuxt@2.11.0
Nuxt.js のデフォルトは、同一ディレクトリに展開するため、Laravel プロジェクトと混在しないように、別途作業ディレクトリを作成します。
今回は「」」ディレクトリを作成します。
$ mkdir client
「nuxt.config.js」ファイルを作成し、「client」を作業ディレクトリに設定します。
module.exports = {
srcDir: 'src/',
}
Nuxt.js プロジェクトを以下設問を答えながら作成します。
$ yarn create nuxt-app client ./client
create-nuxt-app v2.14.0
✨ Generating Nuxt.js project in client
? Project name client
? Project description My top-notch Nuxt.js project
? Author name Yohei Yoshikawa
? Choose the package manager Yarn
? Choose UI framework Vuetify.js
? Choose custom server framework None (Recommended)
? Choose Nuxt.js modules Axios
? Choose linting tools ESLint, Prettier
? Choose test framework None
? Choose rendering mode Universal (SSR)
? Choose development tools jsconfig.json (Recommended for VS Code)
...
プロジェクトが作成されると、ディレクトリも自動的に作成されます。
各ディレクトリは以下のようなファイルを配置します。
nuxt コマンドでサーバを起動できます。
$ nuxt
nuxt のパスは「./node_modules/.bin/nuxt」です。
デフォルトで「3000」ポートで起動確認できます。
index.vue に記載されたテンプレート「Hello World」が表示されることを確認します。
routes/api.php に今回のテスト用の API (/api/test)を追加します。
Route::get('test', function() {
return 'Lalavel Api Test';
});
ブラウザで「Lalavel Api Test」が表示されるか確認します。
http://localhost/larablog/api/test
Nuxt.js で通信するために Axios モジュールを利用します。
Next.js のプロジェクト作成でインストールしていますが、個別でインストールすることもできます。
$ npm i @nuxtjs/axios
//または
$ yarn add @nuxtjs/axios
Docker 環境で Nuxt.js + axios を利用するとポートの関係で通信ができません。 よって、Proxy を利用して通信ポートを設定します。
$ npm i @nuxtjs/proxy
//または
$ yarn add @nuxtjs/proxy
nuxt.config.js に 「axios」「proxy」モジュールを設定します。
module.exports = {
srcDir: 'src/',
modules: [
'@nuxtjs/axios',
'@nuxtjs/proxy'
],
axios: {
baseURL: 'http://localhost:3000'
},
proxy: {
'/api': 'http://localhost/',
},
}
Docker 環境で動作させると「http://localhost/」のリクエストがリジェクトされるため、プロキシを設定が必要です。
ERROR connect ECONNREFUSED 127.0.0.1:8000
上記では、axios のベースURLを「http://localhost:3000」(Nuxt.jsサーバのデフォルト)を設定します。
そして、proxy は /api を検出したら「http://localhost/」(ポート80)にアクセスできるようにします。
まず、template タグのデータ部分を vue変数に修正します。
templateタグの下に、script タグで以下を追記します。
export default {
async asyncData({app}) {
const url = 'http://localhost/api/test' //Laravel の API URI
const message = await app.$axios.$get(url)
return {
url,
message
};
}
}
$ nuxt
Nuxt サーバを起動して、http://localhost:3000 にアクセスしてみます。
index.vue で設定した API URL 「http://localhost/api/test」でリクエスト、Laravel API の「Lalavel Api Test」がレスポンスされれば成功です。
IE11以下では closest() を利用できません。 *最も近い親要素の取得 MDNによると、Elementにプロトタイプすることで対策できるとしている。 MDN: closest#Polyfill
if (!Element.prototype.matches) {
Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
}
if (!Element.prototype.closest) {
Element.prototype.closest = function(value) {
var element = this;
do {
if (element.matches(value)) return element;
element = element.parentelementement || element.parentNode;
} while (element !== null && element.nodeType === 1);
return null;
};
}
親のVue にコンポーネントを登録することで、子のイベントを管理できる
var コンポーネント変数 = Vue.extend({
template: 'HTML', //methods で登録したメソッドを実行可能
data: function () { return { データ名 : 値 } }, //コンポーネント内で利用できる変数を登録
methods: { コンポーネント内のメソッド } //template 内で利用可能
)}
親に登録しない場合は、Vue.component() でもよい
var コンポーネント変数 = Vue.component('counter-button', {
template: 'HTML',
data: function () { return { データ名 : 値 } },
methods: { コンポーネント内のメソッド }
})
new Vue({
el: "#id",
components : { 'HTMLタグ名' : コンポーネント変数 }, //タグ名はケバブケース(kebab-case)
data: { オブジェクト } //Element内のオブジェクト
methods: { メソッド } //Element内のメソッド
}
{{fruit.name}}
:
//v-on:increment カスタムイベント設定し、他のメソッドを実行
Total: {{total}}
var counterButton = Vue.extend({
template: '{{counter}} amounts ',
data: function () {
return {
counter: 0
}
},
methods: {
addToCart: function () {
this.counter += 1
this.$emit('increment') //add custom event
}
}
})
new Vue({
el: '#fruits-counter',
components: {
'counter-button': counterButton
},
data: {
total: 0,
fruits: [
{ name: 'Pear'},
{ name: 'Strawbery'}
]
},
methods: {
incrementCartStatus: function() {
this.total += 1
}
}
});