- 投稿日:2020-02-06T23:46:16+09:00
vue.jsの下準備とimportについて
Vue.jsの開発を始めるまでの下準備と、Vue.jsで必ず必要になるimportについて、正確に理解したいと思います。
WebCLIとは
WebCLIとは、Vue.jsで作成するアプリの骨格を作ってくれるコマンドラインツールのことです。
Vue.jsを学習する中で、最初はCDN経由でVue.jsを呼び出して使っている方も多くいると思います。
CDNとはコンテンツを配布するためのネットワークのことです。
WebCLIを使うと、プロジェクトを作成するのもターミナル経由で行うことができるようになります。vue create プロジェクト名でプロジェクトの作成をすることができます。
プロジェクトの骨格
CLI経由で作成されたプロジェクトは多くのファイルから構成されていますが、主に使うのはsrc(ソースコード)に入っているファイルになります。
components
コンポーネント。細かく使い回す部品を管理するフォルダ
views
ページに関するvueファイルを入れるフォルダ。
App.vue
アプリ共通で管理するコンポーネントが集まったファイル。ヘッダーやフッターなどが入っている。
main.js
最初に読み込まれるファイル。この中に、最初に読み込ませたいファイル、やるべき処理を入れておく。
main.jsには以下のようなコードがある。new Vue({ router, render: function (h) { return h(App) } }).$mount('#app')まず、
new Vue
は新しくVueインスタンスを作成するということです。
その中にはオプションオブジェクトが入っており、これはこのようなコードに変換されます。new Vue({ el: '#app', components: { App }, template: '<App />' })つまり、アプリを開始したときにAppエレメントがインスタンスとして作成されるということです。
- 投稿日:2020-02-06T21:46:58+09:00
Vue.js v3 をつくって学ぶ リアクティブシステム
本記事では、Vue.js v3 のコア部分であるリアクティブシステムを実装し、その仕組みを学びます。
今回実装するリアクティブシステムを用いれば、以下のような簡単なアプリケーションが作れます。
最終的なコードはGitHubにあります。
https://github.com/hareku/simple-vue-reactivityリアクティブとは
「リアクティブである」とは、「その値が監視され、変更が検知される状態のこと」を指します。
Vue.jsやReactでは、コンポーネントが保持している状態を変更すれば、その変更が検知されてHTMLに反映されます。それらを実現するためには、値の変更を検知可能な状態にするリアクティブシステムが必要です。
Vue.js v3 におけるリアクティブシステム
Vue.js のリアクティブシステムは、主に以下の3つで構成されます。
- ref
- effect
- computed
まずは
ref
とeffect
を使ったサンプルコードを見てみましょう。ref-effect-example.tsconst counter = ref(0) // 0 は object になり、valueプロパティでアクセスできる // counter.value が変更されたら、effectの引数に渡した関数が自動で再実行される let double = 0 effect(() => { double = counter.value * 2 }) console.log(double) // 0 counter.value = 5 console.log(double) // 10 <- Changed!このように
ref
でリアクティブにした値をeffect
に渡した関数内で参照すれば、変更を検知して自動で関数を再実行してくれます。これは一見すると魔法のようですが、単純な仕組みがあります。
それでは、これらのリアクティブシステムを実装していきましょう。リアクティブシステムの実装
※Vue.js はオブジェクトもリアクティブにできるのですが、今回は簡略化のためオブジェクトには対応しません。数値や文字列などのオブジェクトではない値のみ、リアクティブにします。
Ref の実装
ref
関数は、引数で渡した値をリアクティブにします。
ref
に渡した値が value をキーとしたオブジェクトに変換される理由は、getter/setter によるフック処理を行うためです。ref.tsexport function ref(value: any) { return { get value() { // TODO: track return value }, set value(newVal) { value = newVal // TODO: trigger } } }JavaScript では、object のプロパティ名に get/set を付けることで getter/setter を実装できます。
TODO の通り、getter に「値が使われていることを知らせる処理 (track)」と、setter に「値が変更されたことを知らせる処理 (trigger)」が必要です。これらの処理は、次に解説する
effect
関数に依存しているため、そちらで実装します。Effect の実装
それでは
effect
関数を実装します。これはとてもシンプルです。effect.tslet activeEffect: Function | null = null export function effect(fn: Function) { activeEffect = fn fn() }
effect
内では、引数に渡された関数をactiveEffect
という変数に格納しています。この変数は次のトラッキング処理で用います。トラッキング処理(track)
次は
ref
の getter で必要なトラッキング処理であるtrack
を実装します。ref.tsconst ref = { get value() { track(ref) // これを実装する return value }, set value(newVal) { value = newVal // TODO: trigger } }
track
は、どのeffect
がどういったref
に依存しているかという依存関係を管理します。
一度track
のコードを見てみましょう。effect.ts// Set はユニークな値のみを格納できる配列 // https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Set type Deps = Set<Function> // WeakMap は Object をキーにできるオブジェクト // targetMap では ref をキーとして、参照している effect のリストを格納する const targetMap = new WeakMap<object, Deps>() export function track(target: object) { // target (ref) に依存している関数リスト (deps) を取得する let deps = targetMap.get(target) // deps がなければ初期化する if (deps === undefined) { deps = new Set() targetMap.set(target, deps) } // 現在実行中の effect 関数を依存関係 (deps) に追加する if (activeEffect && !deps.has(activeEffect)) { deps.add(activeEffect) } }複雑に見えますが、やっていることは WeakMap で
ref
に依存しているeffect
リストを管理しているだけです。これらの依存関係をもとに、次のトリガー処理で、特定の
ref
に依存しているeffect
をすべて再実行できます。トリガー処理(trigger)
ref
の setter 時の処理であるトリガーを実装します。ref.tsconst ref = { get value() { track(ref) return value }, set value(newVal) { value = newVal trigger(ref) // これを実装する } }effect.tsexport function trigger(target: object) { // target に依存している effect リストを取得する const deps = targetMap.get(target) if (deps === undefined) { return } // target に依存している effect を全て再度実行する deps.forEach(effect => { effect() }) }これにより、
ref
の value が更新されるたびに、依存関係にあるeffect
を全て再実行することができます。これが Vue.js におけるリアクティブシステムの仕組みです。computed
先ほど実装した
ref
とeffect
を組み合わせれば、Vue.js のcomputed
を実装できます。まずは
computed
の仕様の確認のため、jest でテストを書いてみます。computed.test.tsdescribe('reactivity/computed', () => { it('should observe ref', () => { const counter = ref(0) const double = computed(() => counter.value * 2) expect(double.value).toBe(0) counter.value = 5 expect(double.value).toBe(10) }) })
computed
を実装すれば、わざわざeffect
の外に定義していたlet double
のような変数を省略することができます。computed
はこのように実装します。computed.tsexport function computed<T = any>(getter: () => T): { value: T } { let value: T effect(() => { value = getter() }) return { get value() { return value } } }アプリケーションの実装
それでは実装したリアクティブシステムを用いて、冒頭のサンプルアプリケーションを実装してみましょう。
HTML
JavaScript 側で操作するために、各タグに適当な id を付与しておきます。
app.html<div> <span id="count"></span> * 2 = <span id="multiplied"></span> </div> <div> <button id="increment">Increment ++</button> <button id="decrement">Decrement --</button> </div>JavaScript
まずは、 count とそれを2倍した値である multiplied をリアクティブな値として作ってみます。
app.tsconst count = ref(0) const multiplied = computed(() => count.value * 2)そして、
effect
関数内で HTML の操作を行います。app.tsconst countElement = document.getElementById('count') const multipliedElement = document.getElementById('multiplied') effect(() => { countElement.innerText = String(count.value) multipliedElement.innerText = String(multiplied.value) })次に値を増減させるため、ボタンにクリックイベントを登録します。
app.tsconst incrementButton = document.getElementById('increment') const decrementButton = document.getElementById('decrement') incrementButton.addEventListener('click', () => { count.value++ }) decrementButton.addEventListener('click', () => { count.value-- })
addEventListener
に渡した関数内でcount.value
を変更しているので、変更する度にeffect
内の HTML 操作が実行され、Viewが更新されます。これでアプリケーションの完成です。
最終的なアプリケーションコード
app.tsimport { ref } from '../ref' import { effect } from '../effect' import { computed } from '../computed' const countElement = document.getElementById('count') const multipliedElement = document.getElementById('multiplied') const incrementButton = document.getElementById('increment') const decrementButton = document.getElementById('decrement') if(countElement && multipliedElement && incrementButton && decrementButton) { const count = ref(0) const multiplied = computed(() => count.value * 2) incrementButton.addEventListener('click', () => { count.value++ }) decrementButton.addEventListener('click', () => { count.value-- }) effect(() => { countElement.innerText = String(count.value) multipliedElement.innerText = String(multiplied.value) }) }次なるステップ
本記事の解説は以上になります。
さらに理解を深めるためのステップとしては、オブジェクトのリアクティブ化があります。対応方法として、依存関係を管理していた WeakMap をさらに深くし、オブジェクトの各キーごとの
effect
を管理する手法があります。
また他にできることとして、プロパティの追加や削除への対応や、監視を浅く (shallowに) してパフォーマンスを改善することなどがあります。実装したい方は Vue.js v3 のソースコード (@vue/reactivity) が参考になります。
https://github.com/vuejs/vue-next/tree/master/packages/reactivity
- 投稿日:2020-02-06T21:21:27+09:00
Vue.js ネコ本チュートリアルのToDoリストを少しアレンジしてみた
はじめに
最近Vue.jsの学習を始めたので、アウトプットがてらToDoリストを作成してみました。
※プログラミングの勉強を始めて3か月ほどなので突っ込みどころありましたらご教授いただけますと幸いです。自作したToDoリスト
以下が、自作したToDoリストです。
自作ToDoリスト
勉強がてらデザインにはBootstrapを使用してみました。参考
参考にさせていただいたのは以下のチュートリアルです。
ToDoリストを作りながら学習しよう!個人的にはVue.jsを学ぶ上で大変お世話になっている本(通称ネコ本)です。
Let's アレンジ
アレンジがカタカナになってるのは見栄えです。(センス・・・)
本チュートリアルでは、状態が完了と着手中の2パターンの切り替えになってるところを、
アレンジ精神で3パターンの切り替えにしたいなと思い保留を追加してみました。具体的に変更したところは2点。
①使用するデータを追記
変更前
main.jsdata: { todos: [], current: -1, options: [ { value: -1, label: 'すべて' }, { value: 0, label: '作業中' }, { value: 1, label: '完了' } ] },⇓⇓⇓
変更後
main.jsdata: { todos: [], current: -1, options: [ { value: -1, label: 'すべて'}, { value: 0, label: '着手'}, { value: 1, label: '完了'}, { value: 2, label: '保留'} ] },※個人的に扱いやすいように数字を変更してます。
②メソッドを変更する
main.jsdoChangeState: function (item) { item.state = !item.state ? 1 : 0 },⇓⇓⇓
変更後
main.jsdoChangeState: function(item){ if(2 > item.state){ item.state = item.state + 1 } else { item.state = 0 } },三項演算子から条件分岐に変更しました。
JavaScript初心者なので、三項演算子だとわかるまでめちゃくちゃ理解に苦しみました。
(もう少し基礎を学んだほうがいいのは間違いない・・・)補足
三項演算子は以下の形で条件式がtrueなら式1をfalseなら式2を返します。
条件式 ? 式1 : 式2まとめ
Laravelを学んでいく中でフロントサイドでVue.jsを使ってみたくなり学び始めました。
両FWともに様々なチュートリアルがありますが、アレンジ~自作ポートフォリオ完成までには、
しっかり1つ1つのスクリプトの意味を理解していかなければいけないと痛感しました。引き続きアウトプットしながら学習をしていきたいと思います。
拙いアウトプットですがどなたかの参考になりましたら幸いです。追記
PWA化してみました。
iPhoneですとSafariで以下にアクセスしてホーム画面に追加していただくと機内モードでも利用できます。
[自作ToDoリスト※PWA化]https://asobi.fun/index.html
- 投稿日:2020-02-06T18:12:13+09:00
Vueとaxiosを使って外部APIからデータを取得する
new Vue({ el: '#fetchUsers', data: { users: [] }, mounted() { axios.get('/users') .then(response => (this.users = response.data)) } });<div id="fetchUsers"> {{users}} </div>結果
{userId: 1, userName: sato}, {userId: 2, userName: tanala}
- 投稿日:2020-02-06T17:03:19+09:00
Vuetify2系で SortableJS つかって v-simple-table を ドラッグ&ドロップさせる
■ 参考
drag-n-drop in Vuetify — Part II - Vuetify - Medium
https://medium.com/vuetify/drag-n-drop-in-vuetify-part-ii-2b07b4b27684
SortableJS/Sortable
https://github.com/SortableJS/Sortable
Vuetify Simple tables
https://vuetifyjs.com/ja/components/simple-tables■ 完成品
See the Pen Vuetify 2.x v-simple-table drag and drop by mykysyk (@mykysyk) on CodePen.
- 投稿日:2020-02-06T15:49:37+09:00
Nuxtのページ表示速度が遅かったので、色々改善方法のメモ
はじめに
Nuxt, TypeScriptで速度とかを深く考えず実装を進めていったら、
ページ表示速度が著しく遅かったので色々と勉強したメモ。前提
Nuxt 2.11.0
TypeScript導入済み
Nuxt generateして運用速度改善
どこが遅いのか、とかを色々しらべると
- 画像が多い画面なので画像の読み込みに時間がかかる。
- node moduleが重い
- componentsのimportが無駄なものがあったり、importの仕方がまずい
とかが原因と思われました。
ちなみに改善する前のGoogle のpagespeed insights で測ったら真っ赤っかでした。画像の読み込み改善
画像の遅延読み込みの実装
vue-lazyloadを使います。
yarn add vue-lazyload
nuxtで使えるようにしていきます。
~/plugins/vue-lazyload.tsimport Vue from 'vue' import VueLazyload from 'vue-lazyload' Vue.use(VueLazyload, { preLoad: 1.1, attempt: 1, observer: true, observerOptions: { rootMargin: '0px', threshold: 0.1 } })オプションは、vue-lazyloadのドキュメントを読んでください。たぶん、このまま使って大丈夫です。
pluginをnuxt.config.tsで読み込みます。nuxt.config.tsplugins: [ { src: '~plugins/vue-lazyload', ssr: false } ]vue用に作られたmodulesをnuxtで使う場合pluginを書いて、configで読み込んだらだいたい使える気がします。
これでlazyloadの準備ができました。実際componentsなどで使う場合
hoge.vue<template lang="pug"> div img(v-lazy='hoge.jpg', alt='') </template>とう感じに、
src
の代わりにv-lazy
を使ってください。
これでlazyloadが実装できました。
これだけで画像関連は十分ですが、せっかくなのでwebpも使える様にします。Webpと通常の画像の出し分け
lazyloadの実装に使ったvue-lazyloadを使ったらいい感じにwebpの出し分けも実装できました。
pluginを書き直しましょう。~/plugins/vue-lazyload.tsimport Vue from 'vue' import VueLazyload from 'vue-lazyload' Vue.use(VueLazyload, { preLoad: 1.1, attempt: 1, observer: true, observerOptions: { rootMargin: '0px', threshold: 0.1 }, filter: { webp(listener: any, options: any) { if (!options.supportWebp) return listener.src = 'hoge.webp' } } })
filter
を追加します。
ここで、ブラウザがwebpに対応していればwebpのパスを返す処理を追加しています。
もしくはパスの最後にパラメータを追加すると、変換して返してくれるような機能があればこんな感じで。
これはcontentfulです。~/plugins/vue-lazyload.tsfilter: { webp(listener: any, options: any) { if (!options.supportWebp) return listener.src += '?fm=webp' } }以上で、画像はlazyloadとwebpが実装できました。
ここまでやったら、多分だいたいOKなんじゃないかと思いますが、次へ。
componentsのdynamic import
Nuxt,vueでcomponentをimportする場合
import fuga from '~/components/fuga.vue'だいたい、こうしますが。
const fuga = () => import('~/components/fuga.vue')こうすると、dynamic importになってbundleサイズが軽くなって速度が改善されます。
これをしてエラーが出ないcomponentならこうやったほうがいいですが、
たまにエラーが出るので、その場合は臨機応変に、従来通りのimportするかエラーを直すか。webpackのbundleの設定
nuxt でwebpackのbundleを分割するように設定します。
nuxt.config.tsconst nuxtConfig = { splitChunks: { layouts: true, pages: true, commons: { test: /[\\/]node_modules[\\/]/, name: 'vendor', chunks: 'initial' } }spliChunksの部分の設定をしてやると、よかったです。
おわり。おわり
おわり
参考
https://webpack.js.org/guides/lazy-loading/
https://crieit.net/posts/Nuxt-Vue-dynamic-import-sed
- 投稿日:2020-02-06T02:30:18+09:00
vue.js初心者がaxiosを利用しAPIを叩きデータを表示させるまで
はじめに
Vue.js は学習コストが低いと言われていますが初学者の方からしたら、
理解するのになかなか時間がかかってしまうと思います。
私も深く理解できているわけではありませんが、
これから紹介する書き方のみで
フロントのコーディングやアプリケーションを作る速さが格段にアップしたので、
この記事でVue.jsのコツを掴んでいただけたら幸いです。Vue CLIのダウンロード
$ npm install -g @vue/cliプロジェクトを作る
まずは以下のコマンドで vue のファイルを作ります。
$ vue create new-project※この場合 new-project というディレクトリが作成されます。
ファイルの内容をデフォルトで作るか自分でカスタマイズするか聞かれます。
今回は Router、 Vuex という機能を使うので
Manually select features
を選択します。
spaceキー
でRouter
とVuex
を選択しEnterキー
を押します。
以後も質問形式で設定を聞かれますが特にこだわりがなければ全てEnterキー
で構いません。$ cd new-project $ npm run serve
http://localhost:8080/
このようなurlが出てきたら、
ブラウザからアクセスし以下のような画面が出れば準備完了です。
Hello Worldを赤色で表示
早速Vueをいじっていきます。
Vue は単一ファイルコンポーネントでコードを記述するのが基本です。
以下のような形式を単一ファイルコンポーネントと言います。<template></template> <script></script> <style></style>見てわかるように
<template>
には HTML
<script>
には JavaScript
<style>
には css
を記述していきます。Home.vueの
<template>
<script>
<style>
の中身を全て削除し以下のコードを書きます。
・template
のhomeクラスタグのみ残しておいてください。
・スタイルタグは追加してください。<template> <div class="home"> <h1>Hello World</h1> </div> </template> <script></script> <style scoped> .home{ color: red; } </style>マスタッシュ記法
ここからスクリプトタグを使っていきます。
データバインディングという操作を行います。
以下のようなコードを書きます<template> <div class="home"> <h1>{{hoge}}</h1> </div> </template> <script> export default{ data(){ return{ hoge: "ハローワールド" } } } </script>h1タグの中身が
ハローワールド
に変わったのが確認できたと思います。マスタッシュ リスト表示方法
<template> <div class="home"> <p>{{Vegetable.name}}</p> <p>{{Vegetable.price}}</p> </div> </template> <script> export default{ data(){ return{ Vegetable: { name: "にんじん", price: 3000000 } } } } </script>
Vegetable
リストの中のname
、price
というように取り出します。v-bind スタイル付与
h1タグを青色にします。
<template> <div class="home"> <h1 v-bind:style="vStyle">{{hoge}}</h1> </div> </template> <script> export default{ data(){ return{ hoge: "ハローワールド", vStyle: { color: "blue" } } } } </script>filter 小数点をつける
高級なにんじんの値段に小数点をつけます。
<template> <div class="home"> <p>{{Vegetables.price | filter}}</p> </div> </template> <script> export default{ data(){ return{ Vegetables: { price: 3000000 } } }, filters: { filter(val) { return val.toLocaleString(); } } } </script>数字以外に、文字にも適用できるfilterがあります。
v-if else 表示 非表示の切り替え
<template> <div class="home"> <p v-if="false">on</p> <p v-else>off</p> </div> </template>v-if の条件が
・true であれば on
・false であれば off
が表示されますv-model inputタグと同期
input に入力した内容を pタグに表示させます。
<template> <div class="home"> <input v-model="text" type="text"> <p>{{text}}</p> </div> </template> <script> export default{ data(){ return{ text: "", } } } </script>inputに入力されたデータを入れるために空のデータを用意してあげます。
textデータから値、テキストを取得して描画されます。v-on clickイベント
<template> <div class="home"> <div @click="push()">click me!!</div> </div> </template> <script> export default{ methods:{ push(){ console.log("click year!!!!") } } } </script>検証画面のコンソールから確認してください。
click イベント以外にもイベントはあります。v-for 配列でタグの複製
<template> <div class="home"> <div v-for="data in Vegetables" :key="data.key"> <p>{{data.name}}</p> <p>{{data.price}}</p> </div> </div> </template> <script> export default{ data(){ return{ Vegetables:[ {name: "じゃがいも", price: 300, key: "imo"}, {name: "イチゴ", price: 400, key: "strawberry"}, {name: "カボチャ", price: 500, key: "pumpkin"}, ] } } } </script>
Vegetables配列
の中のデータと同じ数タグを複製しそれぞれ該当するマスタッシュ記法で書かれたタグにデータ(name、price、key)が格納されます。イメージ図
Vegetables配列/
├ data/
│ ├ name/ じゃがいも
│ ├ price/ 300
│ └ key/ imo
├ data/
│ ├ name/ イチゴ
│ ├ price/ 400
│ └ key/ strawberry
└ data/
├ name/ カボチャ
├ price/ 500
└ key/ pumpkincomponent の使い方 一例
components ディレクトリの中の HelloWorld.vue のそれぞれ
<template>
<script>
<style>
の中身を消して以下のコードを記述します。
※helloクラスタグのみ残してください。HelloWorld.vue
<template> <div class="hello"> <h2>僕は子コンポーネント</h2> </div> </template> <script> </script> <style scoped> h2{ font-size: 50px; } </style>Home.vue
<template> <div class="home"> <HelloWorld></HelloWorld> </div> </template> <script> import HelloWorld from "../components/HelloWorld" export default{ components: { HelloWorld } } </script>・
import
でcomponents
の中のHelloWorld.vue
を呼び出します。
※HelloWorld.vue を呼び出す際拡張子の.vue
をつける必要はありません。
・components プロパティに登録します。
・登録したものは template タグ内で使用できるようになるのでコードを記述します。components ディレクトリにファイルを作り上記の方法をたどると同じようにコンポーネントを作ることができます。
props 親から子コンポーネントにデータを渡す
この記事では、Home.vue の中にある HelloWorld.vue が子コンポーネントにあたります。
Home.vue
<template> <div class="home"> <HelloWorld v-bind:parentText="sendChild"></HelloWorld> </div> </template> <script> import HelloWorld from "../components/HelloWorld" export default{ data(){ return{ sendChild: "親のコンポーネントからテキストを受けっとたよ!" } } components: { HelloWorld } } </script>・子に渡すデータに名前をつけて(parenText)親のデータ(sendChild)をバインディングします。
HelloWorld.vue
<template> <div class="hello"> <p>{{parentText}}</p> </div> </template> <script> export default { props: ['parentText'], } </script>props プロパティで値を受け取った物は data として扱うことができるのでマスタッシュ記法で表示します。
Router Link(Vue Router) ページ遷移
views ディレクトリの中に RouterLink.vue ファイルを作成します。
以下のように記述します。<template> <div class="router"> <p>Router Link の使用ができました!!</p> </div> </template>Router Link を使用するために router ディレクトリの中の index.js に
RouterLink.vue を登録します。
以下のようなコードを記述します。import Vue from 'vue' import VueRouter from 'vue-router' import Home from '../views/Home.vue' import RouterLink from '../views/RouterLink.vue' Vue.use(VueRouter) const routes = [ { path: '/', name: 'home', component: Home }, { path: '/routerlink', name: 'routerlink', component: RouterLink }, ] const router = new VueRouter({ mode: 'history', base: process.env.BASE_URL, routes }) export default router最後にリンクを使いたいファイルに以下のようなコードを記述していきます。
ここでは Home.vue に記述します。<template> <div class="home"> <router-link to="/routerlink">router-link</router-link> </div> </template>to でページのリンク先を指定します
router-link をクリックすることでページ遷移をすることができます。
webページのリンクの方を見てもらうとhttp://localhost:8080/routerlink
このようにリンクの末尾が変わっていることが確認できると思います。ぐるなびAPI お店のデータを取得から表示
axios を用いてレストラン検索APIを叩き Vuex の store という機能を使って表示まで行います。
まずは axios のインストールから行います。
以下のコマンドを順に実行していってください。$ npm install --save axios$ npm install --save次に、ぐるなびAPIを使用するためにこちらのサイトで会員登録をします。
登録することができたら以下のような画面に行き、
仕様書ページ、レストラン検索APIを参考にパラメータと値を入れていきます。
・左側にパラメータ(例 keyid)
・右側に値この記事では、
・表示件数
・wifiの有無
を条件に絞ります。入力ができたら
クエリを送信
ボタンを押し URL を、コピーします。
store ディレクトリの中の index.js ファイルに、以下のようなコードを入力し
コピーした URL をここに挿入
とういう部分にペーストしてください。store / index.js
import Vue from 'vue' import Vuex from 'vuex' import axios from 'axios' Vue.use(Vuex) export default new Vuex.Store({ state: { dataSet: [] }, mutations: { mutateDataSet(state, payload) { state.dataset = payload } }, actions: { commitDataSet(store) { return axios.get("ここに挿入") .then(response => { store.commit('mutateDataSet', response.data.rest) }) .catch((reason) => { console.log(reason.message) }) } } })importでaxiosを使えるようにします。
表示させたいページ(RouterLink.vue)に以下のコードを記述します。RouterLink.vue
<template> <div class="about"> <ul v-for="(value, index) in shopName" :key="index"> <li>{{value}}</li> </ul> </div> </template> <script> export default { data() { return { shopName: "" }; }, created() { this.$store.dispatch('commitDataSet') }, mounted() { var list = []; this.$store.state.dataSet.forEach(function(value) { list.push(value.name); }); this.shopName = list; } }; </script>・created 内で store にアクセスして dispatch メソッドで action 内の関数を実行します。
・store の action メソッドが実行され値が取得されます。
・commit で mutations にアクセスし、データを入れます。
・mutations から state にアクセスし dataSetにデータが入ります。
・mounted で state 内のデータにアクセスし、forEach メソッドでデータが一個ずつ配列として list に入ります。
・list を shopName に代入することで RouterLink.vue 内で data として扱うことができるようになります。
・配列 shopName を v-for で表示させれば実装完了です。いろいろ条件を変えて遊んでみてください。
イメージ
RouterLink.vue store / index.js
└ created ーー> action(commitDataSet)実行
↓
mutation
↓
mounted <ーー state
↓
描画
- 投稿日:2020-02-06T02:30:18+09:00
Vue.js初心者がaxiosを利用しAPIを叩きデータを表示させるまで
はじめに
Vue.js は学習コストが低いと言われていますが初学者の方からしたら、
理解するのになかなか時間がかかってしまうと思います。
私も深く理解できているわけではありませんが、
これから紹介する書き方のみで
フロントのコーディングやアプリケーションを作る速さが格段にアップしたので、
この記事でVue.jsのコツを掴んでいただけたら幸いです。Vue CLIのダウンロード
$ npm install -g @vue/cliプロジェクトを作る
まずは以下のコマンドで vue のファイルを作ります。
$ vue create new-project※この場合 new-project というディレクトリが作成されます。
ファイルの内容をデフォルトで作るか自分でカスタマイズするか聞かれます。
今回は Router、 Vuex という機能を使うので
Manually select features
を選択します。
spaceキー
でRouter
とVuex
を選択しEnterキー
を押します。
以後も質問形式で設定を聞かれますが特にこだわりがなければ全てEnterキー
で構いません。$ cd new-project $ npm run serve
http://localhost:8080/
このようなurlが出てきたら、
ブラウザからアクセスし以下のような画面が出れば準備完了です。
Hello Worldを赤色で表示
早速Vueをいじっていきます。
Vue は単一ファイルコンポーネントでコードを記述するのが基本です。
以下のような形式を単一ファイルコンポーネントと言います。<template></template> <script></script> <style></style>見てわかるように
<template>
には HTML
<script>
には JavaScript
<style>
には css
を記述していきます。Home.vueの
<template>
<script>
<style>
の中身を全て削除し以下のコードを書きます。
・template
のhomeクラスタグのみ残しておいてください。
・スタイルタグは追加してください。<template> <div class="home"> <h1>Hello World</h1> </div> </template> <script></script> <style scoped> .home{ color: red; } </style>マスタッシュ記法
ここからスクリプトタグを使っていきます。
データバインディングという操作を行います。
以下のようなコードを書きます<template> <div class="home"> <h1>{{hoge}}</h1> </div> </template> <script> export default{ data(){ return{ hoge: "ハローワールド" } } } </script>h1タグの中身が
ハローワールド
に変わったのが確認できたと思います。マスタッシュ リスト表示方法
<template> <div class="home"> <p>{{Vegetable.name}}</p> <p>{{Vegetable.price}}</p> </div> </template> <script> export default{ data(){ return{ Vegetable: { name: "にんじん", price: 3000000 } } } } </script>
Vegetable
リストの中のname
、price
というように取り出します。v-bind スタイル付与
h1タグを青色にします。
<template> <div class="home"> <h1 v-bind:style="vStyle">{{hoge}}</h1> </div> </template> <script> export default{ data(){ return{ hoge: "ハローワールド", vStyle: { color: "blue" } } } } </script>filter 小数点をつける
高級なにんじんの値段に小数点をつけます。
<template> <div class="home"> <p>{{Vegetables.price | filter}}</p> </div> </template> <script> export default{ data(){ return{ Vegetables: { price: 3000000 } } }, filters: { filter(val) { return val.toLocaleString(); } } } </script>数字以外に、文字にも適用できるfilterがあります。
v-if else 表示 非表示の切り替え
<template> <div class="home"> <p v-if="false">on</p> <p v-else>off</p> </div> </template>v-if の条件が
・true であれば on
・false であれば off
が表示されますv-model inputタグと同期
input に入力した内容を pタグに表示させます。
<template> <div class="home"> <input v-model="text" type="text"> <p>{{text}}</p> </div> </template> <script> export default{ data(){ return{ text: "", } } } </script>inputに入力されたデータを入れるために空のデータを用意してあげます。
textデータから値、テキストを取得して描画されます。v-on clickイベント
<template> <div class="home"> <div @click="push()">click me!!</div> </div> </template> <script> export default{ methods:{ push(){ console.log("click year!!!!") } } } </script>検証画面のコンソールから確認してください。
click イベント以外にもイベントはあります。v-for 配列でタグの複製
<template> <div class="home"> <div v-for="data in Vegetables" :key="data.key"> <p>{{data.name}}</p> <p>{{data.price}}</p> </div> </div> </template> <script> export default{ data(){ return{ Vegetables:[ {name: "じゃがいも", price: 300, key: "imo"}, {name: "イチゴ", price: 400, key: "strawberry"}, {name: "カボチャ", price: 500, key: "pumpkin"}, ] } } } </script>
Vegetables配列
の中のデータと同じ数タグを複製しそれぞれ該当するマスタッシュ記法で書かれたタグにデータ(name、price、key)が格納されます。イメージ図
Vegetables配列/
├ data/
│ ├ name/ じゃがいも
│ ├ price/ 300
│ └ key/ imo
├ data/
│ ├ name/ イチゴ
│ ├ price/ 400
│ └ key/ strawberry
└ data/
├ name/ カボチャ
├ price/ 500
└ key/ pumpkincomponent の使い方 一例
components ディレクトリの中の HelloWorld.vue のそれぞれ
<template>
<script>
<style>
の中身を消して以下のコードを記述します。
※helloクラスタグのみ残してください。HelloWorld.vue
<template> <div class="hello"> <h2>僕は子コンポーネント</h2> </div> </template> <script> </script> <style scoped> h2{ font-size: 50px; } </style>Home.vue
<template> <div class="home"> <HelloWorld></HelloWorld> </div> </template> <script> import HelloWorld from "../components/HelloWorld" export default{ components: { HelloWorld } } </script>・
import
でcomponents
の中のHelloWorld.vue
を呼び出します。
※HelloWorld.vue を呼び出す際拡張子の.vue
をつける必要はありません。
・components プロパティに登録します。
・登録したものは template タグ内で使用できるようになるのでコードを記述します。components ディレクトリにファイルを作り上記の方法をたどると同じようにコンポーネントを作ることができます。
props 親から子コンポーネントにデータを渡す
この記事では、Home.vue の中にある HelloWorld.vue が子コンポーネントにあたります。
Home.vue
<template> <div class="home"> <HelloWorld v-bind:parentText="sendChild"></HelloWorld> </div> </template> <script> import HelloWorld from "../components/HelloWorld" export default{ data(){ return{ sendChild: "親のコンポーネントからテキストを受けっとたよ!" } }, components: { HelloWorld } } </script>・子に渡すデータに名前をつけて(parenText)親のデータ(sendChild)をバインディングします。
HelloWorld.vue
<template> <div class="hello"> <p>{{parentText}}</p> </div> </template> <script> export default { props: ['parentText'], } </script>props プロパティで値を受け取った物は data として扱うことができるのでマスタッシュ記法で表示します。
Router Link(Vue Router) ページ遷移
views ディレクトリの中に RouterLink.vue ファイルを作成します。
以下のように記述します。<template> <div class="router"> <p>Router Link の使用ができました!!</p> </div> </template>Router Link を使用するために router ディレクトリの中の index.js に
RouterLink.vue を登録します。
以下のようなコードを記述します。import Vue from 'vue' import VueRouter from 'vue-router' import Home from '../views/Home.vue' import RouterLink from '../views/RouterLink.vue' Vue.use(VueRouter) const routes = [ { path: '/', name: 'home', component: Home }, { path: '/routerlink', name: 'routerlink', component: RouterLink }, ] const router = new VueRouter({ mode: 'history', base: process.env.BASE_URL, routes }) export default router最後にリンクを使いたいファイルに以下のようなコードを記述していきます。
ここでは Home.vue に記述します。<template> <div class="home"> <router-link to="/routerlink">router-link</router-link> </div> </template>to でページのリンク先を指定します
router-link をクリックすることでページ遷移をすることができます。
webページのリンクの方を見てもらうとhttp://localhost:8080/routerlink
このようにリンクの末尾が変わっていることが確認できると思います。ぐるなびAPI お店のデータを取得から表示
axios を用いてレストラン検索APIを叩き Vuex の store という機能を使って表示まで行います。
まずは axios のインストールから行います。
以下のコマンドを順に実行していってください。$ npm install --save axios$ npm install --save次に、ぐるなびAPIを使用するためにこちらのサイトで会員登録をします。
登録することができたら以下のような画面に行き、
仕様書ページ、レストラン検索APIを参考にパラメータと値を入れていきます。
・左側にパラメータ(例 keyid)
・右側に値この記事では、
・表示件数
・wifiの有無
を条件に絞ります。入力ができたら
クエリを送信
ボタンを押し URL を、コピーします。
store ディレクトリの中の index.js ファイルに、以下のようなコードを入力し
コピーした URL をここに挿入
とういう部分にペーストしてください。store / index.js
import Vue from 'vue' import Vuex from 'vuex' import axios from 'axios' Vue.use(Vuex) export default new Vuex.Store({ state: { dataSet: [] }, mutations: { mutateDataSet(state, payload) { state.dataSet = payload } }, actions: { commitDataSet(store) { return axios.get("ここに挿入") .then(response => { store.commit('mutateDataSet', response.data.rest) }) .catch((reason) => { console.log(reason.message) }) } } })importでaxiosを使えるようにします。
表示させたいページ(RouterLink.vue)に以下のコードを記述します。RouterLink.vue
<template> <div class="about"> <ul v-for="(value, index) in shopName" :key="index"> <li>{{value}}</li> </ul> </div> </template> <script> export default { data() { return { shopName: "" }; }, created() { this.$store.dispatch('commitDataSet') }, mounted() { var list = []; this.$store.state.dataSet.forEach(function(value) { list.push(value.name); }); this.shopName = list; } }; </script>・created 内で store にアクセスして dispatch メソッドで action 内の関数を実行します。
・store の action メソッドが実行され値が取得されます。
・commit で mutations にアクセスし、データを入れます。
・mutations から state にアクセスし dataSetにデータが入ります。
・mounted で state 内のデータにアクセスし、forEach メソッドでデータが一個ずつ配列として list に入ります。
・list を shopName に代入することで RouterLink.vue 内で data として扱うことができるようになります。
・配列 shopName を v-for で表示させれば実装完了です。いろいろ条件を変えて遊んでみてください。
イメージ
RouterLink.vue store / index.js
└ created ーー> action(commitDataSet)実行
↓
mutation
↓
mounted <ーー state
↓
描画