vue.js + vue-router で任意のタイミングでページタイトルを変更する

こちらのページを参考にさせて頂きましたが、私は下記のような改造しました。

  • ページ読み込み直後だけでなく、任意のタイミングでページタイトルを変更できるように変更処理をメソッド化(非同期でバックエンドからデータを取ってきてそれをタイトルに反映するといった処理を想定)
  • document.titleオブジェクトの更新だけではなく、.update-titleクラスNodeListの更新もサンプルとして追加
  • this.$options.titleは変数でもfunctionでも定義できていたが処理をシンプルにするために関数一択

タイトルを管理するmixinを構築する

export default {
data() {
return {
title: ""
};
},
methods: {
// このメソッドを呼べばいつでも更新できmountedも結果的にはこれをコールしているだけ
updateTitle(str) {
document.title = `${str} - brandName`;
document.querySelectorAll(".update-title").forEach((it) => {
it.innerHTML = str;
});
}
},
mounted() {
// 起動時にtitle()が実装されているならコールする
if (this.$options.title !== undefined) {
let title = this.$options.title();
if (title) {
this.updateTitle(title);
}
}
}
};

mixinを読み込む

最も根幹の部分で読み込んでおけば自動的にすべてのコンポーネントで動作するし、特定のページのみで動作させたければ特定のコンポーネントだけで読み込んでも良いが、わかりやすく今回は根幹部分で読み込む。

import Vue from 'vue'
import RootComponent from "./components/root.vue";
import TitleMixin from "./mixin/title"
Vue.mixin(TitleMixin)
let v = new Vue({
router: router,
components: {"root-component": RootComponent }
}).$mount('#app');

各ページで固定タイトルを設定する

予めタイトルが決まっている場合は下記のように定義すると、このコンポーネント起動時のmoutendの処理でタイトルが設定されます。

export default {
title() {
return "ページタイトル";
}
data(): { return {} },
methods: {}
};

各ページで動的にタイトルを設定する

AjaxでJSONとしてページのデータを取ってきて、取得したページタイトルでページのタイトルを更新する場合は、固定タイトルを設定した時のようにtitle()を定義せずに、任意のタイミングで自分でthis.updateTitle()をコールします。

import Ajax from "./ajax.ts";
export default {
data(): { return {} },
methods: {
Ajax.Get('/page.json').then((info) => {
this.updateTitle(info.title);
});
}
};

メモ

  • コードはTypeScriptで管理しています
  • もうちょっとvuejs側で管理してもらう機構があってもいいかなと思いました。

AWSでS3にアクセスする権限があるかどうかのみを確認する方法

awscliというのをインストールしてやれば無駄な開発をしなくていいのでおすすめです。

awscliをインストールする

適当なUbuntuのDockerイメージでも使ってawscliを入れておくと良いと思います。awscliのインストールと検索すればいくらでも出てきますが、私のやりかたはこちらにまとめていますので参考にどうぞ。

アクセスキーを登録する

cliから下記のように登録することができます。

# aws configure
AWS Access Key ID [****************MNYA]:
AWS Secret Access Key [****************OiaY]:
Default region name [None]:
Default output format [None]:

この結果は環境によって違うと思いますが、~/.awsあたりに保存されます。直接設定ファイル編集派の人はそこをいじってもOKです。したがって、下記のようにスクリプトで自動設定することも可能です。

echo -e "[default]\naws_access_key_id = $S3_KEY\naws_secret_access_key = $S3_SECRET" > /root/.aws/credentials

Dockerビルド時に設定しちゃいたかったり、S3へのデータバックアップなどを自動化したい時はこれがおすすめ。と言いたいところでしたが、なんだかうまくいかないケースも存在した。こちらによると環境変数から指定することもできるようなので、スクリプトで自動化するならこれで設定したほうがいいですね。

export AWS_ACCESS_KEY_ID=hoge
export AWS_SECRET_ACCESS_KEY=hoge

権限の確認

権限に問題がなければaws s3 lsとすれば下記のようにバケット一覧を確認することができます。

# aws s3 ls
2018-09-20 11:50:03 hoge

権限がきちんと設定されていないとこれらが表示されません。

# aws s3 ls
An error occurred (AccessDenied) when calling the ListBuckets operation: Access Denied

これはフルアクセス権限がある場合のみの確認方法ですが、権限によっては特定のコマンドでは適切ではない場合があります。基本的にはフルアクセス権限を持っているか持っていないかでしか作業しないと思うので今の所はこれだけ書いておきます。

フルアクセスではない場合

権限を絞られている場合はlsが使えないことがあります。その場合は想像で念じながらaws s3 cp ./hoge.png s3://hoge.pngなどとしてみてみると良いです。

awscliをインストールしたがcommand not foundになる場合の対策

公式に従って下記のようにインストールしてみましたが

pip install awscli --upgrade --user

結果下記のようにそんなコマンドは存在しないと言われた

root@cfecaa5a4d7c:/tmp# aws
bash: aws: command not found

@uasi さんに教えていただいたのですが、--userをつけるとユーザーディレクトリにインストールされているだけらしいのでパスは通らないと。。

でもパスとってほしいので、--ignore-installed sixオプションを付けて再度インストールをする。

pip install awscli --ignore-installed six

すると無事使えるようになりました

root@cfecaa5a4d7c:/tmp# aws
usage: aws [options] <command> <subcommand> [<subcommand> ...] [parameters]
To see help text, you can run:
aws help
aws <command> help
aws <command> <subcommand> help
aws: error: too few arguments

Vue.jsでCSS3のアニメーションを再スタートする

テンプレートがこんな感じで

<div class="animation" v-bind:class="{ start: this.hoge }"></div>

データをこのように用意しておいてfalseではなくtrueになったら.startというclassを付けることでアニメーションを起こさせます。

export default {
data() {
return {
hoge: false,
}
},
methods: {
go() {
this.hoge = true;
}
}
}

あとはthis.go()を実行すればアニメーションが実行されるのですが、このままでは何度ゴーしてもアニメーションが再実行されません。

これを何度もゴーさせるにはこのように一度classを外してから付け直す事で可能です。

export default {
data() {
return {
hoge: false,
}
},
methods: {
go() {
let truenisuru = () => {
this.hoge = true;
};
if (this.hoge) {
this.hoge = false;
window.setTimeout(() => {
truenisuru();
}, 100);
} else {
truenisuru();
}
}
}
}

ポイントが遅延をさせています。そのままストレートにfalseにしてからtrueにしても早すぎてアニメーションが再実行されないためです。

Vue.jsでなければ要素を削除したり(メモリの圧迫を防ぐためにそれぞれのオブジェクトには自分で自分を使われなくなった消すような動作をさせて。。)といった処理も思いつけると思うんですが、コンポーネントの変な使い方になりそうだし、ちょっとオブジェクトの管理についても調べるのが面倒なので、付け直すといった動作で対応するのが無難そうでした。

Apacheの.htaccessでhttpからhttpsへリダイレクトする

下記のようにするとリダイレクトされます。

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R,L]

また、localhost:8080とかで開発している時はhttpsにリダイレクトしてほしくない時は下記のように本番公開用のホストの時にというルールを追加することで実現できます。RewriteCondってのは続けて書くことができて、最後に書いたRuleが適用されるのです。

RewriteEngine On
RewriteCond %{HTTP_HOST} ^example.com$ [NC]
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R,L]

最近Google ChromeがSSL前提の表示に変えてしまって、httpで接続すると「保護されていない通信」と出すんですよね。なのでSSLになると負荷が増すんで必要に応じてーと対応していましたが、全ページに渡りSSL接続のみできるようにしました。