こんにちはぱるこです。
X-HACKの勉強会で習った「ぐるなびAPI」を使用してグルメ検索サイトを作成してみました。
まだ、不具合が多々ありますが、一旦終了します。バグは就職活動始めるまでに修正していきたいと思います
完成品

作品名:『Vue.jsでグルメ検索』
作成の流れ
制作にかかった時間(TOTAL:約24h)
まず、制作にかかった時間です。
1.ワイヤーフレーム | 15m |
2.デザイン(spのみ) | 1h |
3.コーディング(html/cssのみ) | 1.5h |
4.APIをVueで使うための方法を調べる(axios) | 2h |
5.Vue-cliでの実装作業 | 18h |
6.イラストを描く | 1h |
7.サーバーアップ作業 | 30m |
完成デザイン




イラストを表示させます
作品の仕様
・ぐるなびAPIを使用(今回必要なAPIのデータは、【ID・店名・画像1枚・場所】)
・検索フォームに「フリーワード」を入力をすると初めは12件表示される、検索する度に追加される
・検索前やお気に入りがない時はイラストを表示させる
・お気に入りの登録・解除
・お気に入りにするとお気に入りリストに登録される
・お気に入りのページでリロードすると、バグが起きる
…TODOリストと同様ハッシュタグでリンクを取得しているのでそれが原因だと思われる
・再度検索を押すと、表示されるお店が入れ替わると同時に、お気に入りリストからも消える
→再度検索し直しても、お気入りリストは保持される
・同じものを検索すると重複してしまう
・ローカルストレージを保存方法として使用しているので、同じブラウザであればデータが保持できる
本来したかった仕様
・お気に入りリストに追加したお店は、他を検索しても、お気に入りリストには保存されたままにする
お気に入りのリストに保存するために試したこと
shops[]・・・APIから取得したデータを格納する配列(今回は12件のみ)
myFavoriteShops[]・・・お気に入りに登録したお店のデータを格納する配列
APIデータが格納されている配列(shops[])と別に、お気に入りリストの配列(myFavoriteShops[])を作り、その配列にお気に入りに追加したお店データ(ID・店名・画像1枚・場所)を追加していく。
・もう一度同じジャンルの検索し同じものを登録した時にダブって登録されてしまう。
・すでにお気に入りに登録済みのIDと同じIDを保存させないようにすることはできるが、TOPページとお気に入りリストの連動はできない。TOPページでどれがお気に入りなのか判断できない。
→結果、最初の仕様は諦めた。
コンポーネント分け
App.vue
[componetns]
-ShopSearch.vue(検索機能)
-ShopList.vue(リスト全体)
-ShopItem.vue(リストの1つ1つの部分)
苦戦した箇所
最初の仕様がそもそもまずかった。今の私のレベルでは作れなかった。
実装可能かどうかの判断が必要だと感じた。
(簡単にできると思っていた・・・)
もしいい方法があれば教えてくださいm(_ _)m
axiosを使用して、APIを持ってくる方法
ちなみに、APIからデータを持ってくること自体は、axiosを使用すれば案外簡単だった。



検索ボタンを押した時のメソッドのコード↓
methods: {
shopSearch(value){
const params = {
keyid: 'ぐるなびAPIのKEYをここに入れる',
hit_per_page: 12, ・・・HIT件数
freeword: value, ・・・検索フォーム入力したものを引数にとって入れてる
};
axios.get('https://api.gnavi.co.jp/RestSearchAPI/v3/',{params})
.then(response => {
this.shops = response.data.rest;
for(let i = 0; i < this.shops.length; i++) {
this.$set(this.shops[i], "liked", false); ・・・shops配列に入れる時にお気に入りを追加
}
}).catch( error => { console.log(error); });
}
}
ただし、
shops配列に格納されている店(shop)のオブジェクトに、お気に入りデータを持たせる時に注意が必要だった。
連想配列にはpushが使えない!!
todoリストを作る時は、タスクを追加するときは配列に追加することになるので、pushを使えばよかった。
しかし今回の、連想配列(オブジェクト)にプロパティを追加する場合は、pushは使えないようだ。
なので、次に私がしたのはこれだ。
this.shops = [
{
id:123456,
name: 'カフェA',
area: '東京',
image: 'sampleA.img',
liked; false
},
{
id:546372,
name: 'カフェB',
area: '埼玉',
image: 'sampleB.img',
liked; false
},
{
id:999999,
name: 'カフェC',
area: '神奈川',
image: 'sampleC.img'
}
]
for(let i = 0; i < this.shops.length; i++) {
this.shops[i].liked = false;
}
このようにしても、ちゃんとそれぞれのオブジェクトに「liked」プロパティを追加することはできた。
console.log見ても、likedプロパティの切り替え「true」⇄「false」を確認することもできた。
なのに、なぜか、表示されない。
getとsetがないことが原因だった

console.logでshopsのデータを確認してみると追加した「likedプロパティ」以外は、全てget name、set nameというものがあった。
つまりpushメソッドで追加すると、ゲッター(get)やセッター(set)も勝手に追加されるが、私が行った方法ではされないようだ。
(ウェブカツで習ったのかもしれないが、覚えていない。)

上記のQiita記事を参考にすると、今回は連想配列でpushメソッドは使えないため、$setを使えば良さそうだ。
this.$set(this.shops[i], "liked", false);
こうすることで、追加したlikedプロパティにもgetとsetが追加され、表示の切り替えも行えるようになった。
改めて、アウトプットはいろんな学びがあるな〜と感じました。
追加してもお気に入りが維持できるように修正【追記(11/3)】
前回までは、shops配列に直接、APIから取得してきたデータを入れただけだったので、検索する度に消えてしまっていた。
①一時的にAPIのデータを入れるapidata配列をdataに追加で定義した。
この時、dataでapidata配列を定義しないとゲッターとセッターが追加されない(vue.jsで監視できず表示されない)ので、注意が必要。
②appdata配列に格納されているお店のデータに「お気に入りプロパティ」を追加する。
連想配列にはpushは使えないので、$setを使用。
③shop配列のデータとapidata配列を合体させる。
下記ブログに書かれている「Array.prototype.push.apply」は表示できなかったので、
「concat」を使用した。

④最新のものを上に表示するために、reverseメソッドを使用
data(){
return{
apidata:[] ...apiデータを入れるための一時的な配列データを追記(11/3追記分)
}
},
methods: {
shopSearch(value){
const params = {
keyid: 'ぐるなびAPIのKEYをここに入れる',
hit_per_page: 12, ・・・HIT件数
freeword: value, ・・・検索フォーム入力したものを引数にとって入れてる
};
axios.get('https://api.gnavi.co.jp/RestSearchAPI/v3/',{params})
.then(response => {
this.apidata = response.data.rest;
for(let i = 0; i < this.apidata.length; i++) {
this.$set(this.apidata[i], "liked", false);
}
this.shops = this.shops.concat(this.apidata);
this.shops.reverse();
}).catch( error => { console.log(error); });
}
}
できていない箇所&修正箇所(11/3時点)
⬇︎転職活動始めるまでにこれらのバグを修正します!
・各ブラウザでの確認作業(主要なブラウザくらいで)
・お気に入りでリロードするとTOPのデータになってしまう。
…おそらく現在、URLのハッシュタグで切り替えを行なっているので、それを/(ルートにしたら良さそうな気がする。)
・画像がない店がある。その時はダミーの画像にするようにする
・iPhoneのアドレスバーを含めた高さを取得できていない
・検索するたびにAPIで取得したデータが消えてしまうけど、もうこのような仕様にするしかないのか??
こだわりポイント
・イラストを描いた!!(下手くそなんです。)
↓私のような下手な人間でも、書けそうなサイトを真似て描きました!

まとめ

Vue.jsは「学習効率は非常に高い」です。

え、なんて?