◆修正しました
◆2019/6/23
修正したんだけど、ちょっとまー残念な感じではある。というのも、Vue 3.0になるまでフラグメントが使えない。だから泣く泣くdivで囲う羽目になった。スタイル当てるのも場合によってはちょっと辛いな。2パターン紹介しているから、好きな方を使え。
Vue 3.0が来たらフラグメント使え。
◆したいこと
- APIで画像を表示する。(SVGじゃないやつ)
- APIで画像が取得できなかった時は、指定の画像を表示する。(SVGでもなんでも)
- APIを2回投げたくない。画像が取得できたのならそれをDataURIの形にしてしまおうと思う。
◆おことわり
以下の成分を含みます。
これから説明するんだけど、どっから説明したもんかわからんから適当に説明する。「わかんね」って人はコメントしてくれ。
◆修正版
つかわれるほう。使い方は…なんとなくわかるだろ。良い感じにプロパティに値をバインドしてくれ。
※以下、前バージョン。
◆結論
つかわれるほう
つかうほう
◆勘所
勘所さん!?
「結論」の項のソースを眺めながら確認してくれ。
▼親からURL渡す
今回の例では、「AnyComponent」さんが「ImageComponent」のプロパティ「ImageURL」に向けてURLをバインドしている。
分けてみたけど、無論ひとつのコンポーネントで完結させることもできますね。
あと「v-bind:ImageURL」って書いてるけど「:ImageURL」でいいよ。
▼初期化(mountedメソッド)
- とりあえずスピナーを表示
- 読み込めるか確認
- 読み込めたらその画像
- 読み込めなかったらダミー画像
って流れをたどるので、mountedのライフサイクルフックでスピナー画像を設定しておく。
ロード中画像を持ってない人はloading.ioでSVGスピナーを生成しよう。べつにgifでもいいけど。また、loading.ioのスピナーは詰めが甘いから暇な人は容量最適化して遊ぼう。
この例ではwebpackのresolve.aliasでパス指定している。’@’がそれだな。
▼読み込み(getImageUriメソッド)
プロパティ「ImageURL」にURLを受け取った「ImageComponent」くんは、画像をAPI取得する。取得にはaxiosを利用している。
このメソッドはPromiseであるため処理が待たれない。だからロード中画像を表示することが出来る。
APIで画像が取得できた時、responseを加工してDataURIに加工する。取得に失敗したとき、つまりcatchに於いて、差し替えのための画像を読み込む。
(この記事の)旧バージョンでは
btoa(String.fromCharCode(...new Uint8Array(response.data)))
でbase64にしてたんだけど、クソデカ画像くんだとArrayこわれるんでreduceでアレした。
あと、今思ったんだけどSVG取得したらこれbase64にしちゃうから駄目だね!ごめんね!
▼読み込み失敗
二枚目の画像の読み込みが失敗するので、指定した画像が表示される。
読み込み失敗する理由は、CORSによるものだ。
つまり、「https://steadiness-law.jp/」ドメイン以外からの使用を許可していないのだ。詳しくはググろう。
404でもちゃんと動くよ。
動確はしたつもりだけど、動かなかったら教えてくれ。
◆おとくなけいじばん
Vueのバインディングってやつは結構ヤバくて、コンポーネントのプロパティに(ほぼ)直でjsonをバインディングできたりする。
- フィールドにany型を定義して
- JSON.parse([jsonな文字列]) を代入して
- そのまま v-bind=”[フィールド変数]“ することができる。
anyの配列を定義してそこにjson配列をぶち込み、v-forでまわしながらv-bindなんてことも可能だ。型が不安定なのが難点だけど、利便性と天秤にかけた時に利便性が勝っちまう気がする。
コメントを残す