From 36e07e8ebe9a18bda7868c8864ece74f5560cc05 Mon Sep 17 00:00:00 2001 From: INOUE Takuya Date: Fri, 16 Jun 2017 07:23:22 +0900 Subject: [PATCH 1/4] Translate head.md via GitLocalize --- ja/head.md | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 ja/head.md diff --git a/ja/head.md b/ja/head.md new file mode 100644 index 00000000..795bd9dc --- /dev/null +++ b/ja/head.md @@ -0,0 +1,100 @@ +# ヘッドの管理 + +アセットの挿入と同様に、ヘッドの管理も同じ考えに追従しています。つまり、コンポーネントのライフサイクルのレンダリング `context` に動的にデータを付随させ、そして `template` 内にデータを挿入できるという考えです。 + +そうするためには、ネストしたコンポーネントの内側で SSR コンテキストへアクセスできる必要があります。単純に `context` を `createApp()` へ渡し、これをルートインスタンスの `$options` で露出させることができます。 + +```js +// app.js +export function createApp (ssrContext) { + // ... + const app = new Vue({ + router, + store, + // this.$root.$options.ssrContext というように、すべての子コンポーネントは this にアクセスできます + ssrContext, + render: h => h(App) + }) + // ... +} +``` + +これと同様のことが `provide/inject` 経由でも可能ですが、そうすると context が `$root` 上に存在することになるため、インジェクションを解決するコストを避けたほうが良いでしょう。 + +インジェクトされた context を用いて、タイトルを管理する単純な mixin を書くことができます: + +```js +// title-mixin.js +function getTitle (vm) { + // components can simply provide a `title` option + // which can be either a string or a function + const { title } = vm.$options + if (title) { + return typeof title === 'function' + ? title.call(vm) + : title + } +} +const serverTitleMixin = { + created () { + const title = getTitle(this) + if (title) { + this.$root.$options.ssrContext.title = title + } + } +} +const clientTitleMixin = { + mounted () { + const title = getTitle(this) + if (title) { + document.title = title + } + } +} +// VUE_ENV は webpack.DefinePlugin を使って挿入できます +export default process.env.VUE_ENV === 'server' + ? serverTitleMixin + : clientTitleMixin +``` + +このようにすれば、ルートコンポーネントはドキュメントのタイトルをコントロールするために context を利用することができます。 + +```js +// Item.vue +export default { + mixins: [titleMixin], + title () { + return this.item.title + } + asyncData ({ store, route }) { + return store.dispatch('fetchItem', route.params.id) + }, + computed: { + item () { + return this.$store.state.items[this.$route.params.id] + } + } +} +``` + +そしてタイトルは `template` 内でバンドルレンダラーに渡されます: + +```html + + + {{ title }} + + + ... + + +``` + +**メモ:** + +- XSS 攻撃を防ぐために double-mustache(HTML エスケープした挿入)を使うこと。 +- レンダリング中にタイトルをセットするコンポーネントがない場合に備えて、`context` オブジェクトを作成する際にはデフォルトのタイトルをセットするようにすべきです。 + +--- + +同様のやり方で、この mixin を包括的にヘッドを管理するユーティリティに容易に拡張できます。 From b50d122d752ad62487e19605e7ac382974788447 Mon Sep 17 00:00:00 2001 From: Sota Yamashtia Date: Fri, 16 Jun 2017 07:23:23 +0900 Subject: [PATCH 2/4] Translate head.md via GitLocalize From 8e2027bff525f69b2c43e56947cf7c6b23d1ba21 Mon Sep 17 00:00:00 2001 From: INOUE Takuya Date: Fri, 16 Jun 2017 07:43:28 +0900 Subject: [PATCH 3/4] =?UTF-8?q?expose=20=E3=81=AF=E3=83=A2=E3=82=B8?= =?UTF-8?q?=E3=83=A5=E3=83=BC=E3=83=AB=E3=81=A8=E3=81=97=E3=81=A6=E5=85=AC?= =?UTF-8?q?=E9=96=8B=E3=81=99=E3=82=8B=E3=81=A8=E3=81=84=E3=81=86=E6=84=8F?= =?UTF-8?q?=E5=91=B3=E3=81=AA=E3=81=AE=E3=81=A7=E5=85=AC=E9=96=8B=E3=81=A8?= =?UTF-8?q?=E3=81=84=E3=81=86=E8=A8=80=E8=91=89=E3=82=92=E4=BD=BF=E3=81=86?= =?UTF-8?q?=E3=82=88=E3=81=86=E3=81=AB=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ja/head.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ja/head.md b/ja/head.md index 795bd9dc..3fe6b2b8 100644 --- a/ja/head.md +++ b/ja/head.md @@ -2,7 +2,7 @@ アセットの挿入と同様に、ヘッドの管理も同じ考えに追従しています。つまり、コンポーネントのライフサイクルのレンダリング `context` に動的にデータを付随させ、そして `template` 内にデータを挿入できるという考えです。 -そうするためには、ネストしたコンポーネントの内側で SSR コンテキストへアクセスできる必要があります。単純に `context` を `createApp()` へ渡し、これをルートインスタンスの `$options` で露出させることができます。 +そうするためには、ネストしたコンポーネントの内側で SSR コンテキストへアクセスできる必要があります。単純に `context` を `createApp()` へ渡し、これをルートインスタンスの `$options` で公開することができます。 ```js // app.js From cc647e213b5d728b50c6d086309419bd5cd1a01a Mon Sep 17 00:00:00 2001 From: INOUE Takuya Date: Tue, 20 Jun 2017 20:55:54 +0900 Subject: [PATCH 4/4] =?UTF-8?q?=E3=82=B3=E3=83=BC=E3=83=89=E3=81=AE?= =?UTF-8?q?=E3=82=B3=E3=83=A1=E3=83=B3=E3=83=88=E3=81=AE=E7=BF=BB=E8=A8=B3?= =?UTF-8?q?=E3=81=8C=E6=BC=8F=E3=82=8C=E3=81=A6=E3=81=84=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ja/head.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ja/head.md b/ja/head.md index 3fe6b2b8..3bd25eea 100644 --- a/ja/head.md +++ b/ja/head.md @@ -26,8 +26,8 @@ export function createApp (ssrContext) { ```js // title-mixin.js function getTitle (vm) { - // components can simply provide a `title` option - // which can be either a string or a function + // コンポーネントはシンプルに `title` オプションを提供し、 + // これには文字列または関数を入れることができます const { title } = vm.$options if (title) { return typeof title === 'function'