VueCLIでアプリ作成(アドレス帳)①
プロジェクト作成
vue create udemy-sample
プロジェクトフォルダに移動してnpm run serveするとVue.jsのサーバが起動。デフォルトで8080ポートが使われる。
http://localhost:8080/でデフォルトのVue.jsの画面がでてればOK
publicディレクトリ内がドキュメントルートとして公開されます。
アドレスの一覧表示をする単一ファイルコンポーネント作成
src/components/Addresses.vue
<template>
<div>
<h1>マイアドレス帳</h1>
</div>
</template>
<script>
</script>
<style scopedlang="scss">
</style>
まずはこれを表示させます。
表示関係のファイルはsrc/viewsフォルダ
src/views/Home.vueの内容が表示されているので、これを書き換えてローカル登録する。
<template>
<div class="home">
<Addresses></Addresses> //←ここsrc/components/Addresses.vueの内容が表示
</div>
</template>
<script>
// @ is an alias to /src
import Addresses from '@/components/Addresses.vue' //←src/components/Addresses.vue読込
export default {
name: 'Home',
components: {
Addresses //←ローカル登録
}
}
</script>
①Addresses.vueをインポート。コメントにもあるように@が/srcを示しているので。@/components/~と記述すればよい。
②componentsにAddressesを登録
③template内の表示させたいところに<Addresses />タグをいれる
こんな表示になっていればOK
Vue Routerで画面の切り替え
src/main.jsでrouterをimportして、router変数にrouterを渡している。
実際の動きとして記述する方法は、
①src/router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue' //←importで読み込む場合
Vue.use(VueRouter)
const routes = [
{
path: "/",
name: "home",
component: Home,
},
{
path: "/about",
name: "about",
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () =>
import(/* webpackChunkName: "about" */ "../views/About.vue"),
},
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
②src/App.vue
<router-link to="/">Home</router-link> | //←書き方①
<router-link to="/about">About</router-link>
<router-link to="{ name: 'Home' }">Home</router-link> | //←書き方②
<router-link to="{ name: 'About' }">About</router-link>
</div>
<router-view/> //←ここでコンポーネントが書き出される
<!--共通パーツはrouter-viewの外に書く---->
vutify導入
vue add vuetify
npm run serveすると画面変更されていればOK
src/App.vue でホーム画面を整理。
<template>
<v-app>
<v-toolbar app>
<v-toolbar-side-icon></v-toolbar-side-icon> //←メニューアイコン追加
<v-toolbar-title class="headline text-uppercase">
<span>マイドレス帳</span> //←ツールバーのタイトル
</v-toolbar-title>
<v-spacer></v-spacer>
</v-toolbar>
<v-content>
<Addresses/> //←先に作成したAddresses.vueを憑依
</v-content>
</v-app>
</template>
<script>
import Addresses from './components/Addresses.vue' //←Addresses.vueをimport
export default {
name: 'App',
components: {
Addresses //←Addresses.vueを登録
},
data () {
return {
//
}
}
}
</script>
ナビゲーション追加
①src/components/SideNav.vueを作成
<template>
<v-layout wrap style="height: 200px;">
<v-container>
<v-layout justify-center>
<!-- ▼drawerの値の変更 @click.stop="drawer = !drawerでboolの値反転させる -->
<v-btn color="pink" dark @click.stop="drawer = !drawer">Toggle</v-btn>
</v-layout>
</v-container>
<!-- ▼navの開閉 v-model="drawer" dataで初期はdrawer: false,-->
<v-navigation-drawer v-model="drawer" absolute temporary>
<v-list class="pa-1">
<v-list-tile avatar>
<v-list-tile-avatar>
<img src="https://avatars2.githubusercontent.com/u/1363954?s=460&v=4">
</v-list-tile-avatar>
<v-list-tile-content>
<v-list-tile-title>Kazuya Kojima</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
</v-list>
<v-list class="pt-0" dense>
<v-divider></v-divider>
<v-list-tile v-for="item in items" :key="item.title">
<v-list-tile-action>
<!-- ▼マテリアルアイコン dataで{ title: '連絡先一覧', icon: 'list' } リストアイコンを指定 -->
<v-icon>{{ item.icon }}</v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title>{{ item.title }}</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
</v-list>
</v-navigation-drawer>
</v-layout>
</template>
<script>
export default {
data () {
return {
drawer: false,
items: [
{ title: '連絡先一覧', icon: 'list' }
]
}
}
}
</script>
マテリアルアイコンについてはこちら
https://fonts.google.com/icons
②App.vueで登録とタグを挿入
<template>
<v-app>
<v-toolbar app>
<v-toolbar-side-icon></v-toolbar-side-icon>
<v-toolbar-title class="headline text-uppercase">
<span>マイドレス帳</span>
</v-toolbar-title>
<v-spacer></v-spacer>
</v-toolbar>
<SideNav></SideNav> //←タグを挿入
<v-content>
<Addresses/>
</v-content>
</v-app>
</template>
<script>
import Addresses from './components/Addresses.vue'
import SideNav from './components/SideNav.vue' //←import
export default {
name: 'App',
components: {
Addresses,
SideNav //←登録
},
data () {
return {
//
}
}
}
</script>
Vuexとは
①ストアというデータの入れ物を作り、各コンポーネントからアクセスしてデータの出し入れをできるようにする。
②Action,Mutation,State,Getterで構成(stateがデータをいれるところ)
③基本的にはアプリケーションで1つのストアを持つ
コンポーネントはデータを受け取る時はstateから直接取得するか、getterを通じて取得する
Vuexのストア実装
Vue CLIインストール時にVuexもインストールしておく。
src/sotre/index.js
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
drawer: false,
},
mutations: {
toggleSideMenu(state) {
state.drawer = !state.drawer;
},
},
actions: {
toggleSideMenu({ commit }) {
commit("toggleSideMenu");
},
},
modules: {},
});
①toggleSideMenuの引数としてcommitメソッドを受け取る。
(アクションメソッドの引数には自動的にcontextオブジェクトがわたってきます。これはcontext.commitメソッドだけを受け取る記述方法)
actions: {
toggleSideMenu({ commit }) {
commit("toggleSideMenu");
},
},
②commitでmutationのメソッドを指定 commit("toggleSideMenu");
・mutation自動的にstateがわたってくるので、ここでstateの値を更新させる
mutations: {
toggleSideMenu(state) {
state.drawer = !state.drawer;
},
},
ストアの利用
メニューアイコンにトグル機能を実装させる。$storeでアクセスできるようになります。ストアのデータ(ストアのステート)には$store.state.でアクセス。
src/components/SideNav.vueを修正
①トグルボタンを削除(メニューアイコンから開閉するため)
②dataのdrawerは削除(ストアのstateを利用するため)
③v-model="drawer"を変更(ストアのstate.drawerに変更)
//▼削除
<v-container>
<v-layout justify-center>
<v-btn color="pink" dark @click.stop="drawer = !drawer">Toggle</v-btn>
</v-layout>
</v-container>
//▼削除 script data
drawer: false,
//▼v-model="drawer"をv-model="$store.state.drawer"に変更
<v-navigation-drawer v-model="$store.state.drawer" absolute temporary>
これで$store.state.drawerをコントロールできる状態になった。
(SideNav.vueとsrc/App.vueのツールバーアイコンが紐づいていない)
src/App.vueでアイコンにクリックメソッド実装
ストア($store)はdispatchメソッドを保有していて、store/index.jsで設定したtoggleSideMenuアクションを呼び出します。
methods:{
openSideMenu(){
this.$store.dispatch('toggleSideMenu')
}
}
ツールバーアイコンにクリックメソッド実装
<v-toolbar-side-icon @click="openSideMenu"></v-toolbar-side-icon>
<template>
<v-app>
<v-toolbar app>
<v-toolbar-side-icon @click="openSideMenu"></v-toolbar-side-icon>
<v-toolbar-title class="headline text-uppercase">
<span>マイドレス帳</span>
</v-toolbar-title>
<v-spacer></v-spacer>
</v-toolbar>
<SideNav></SideNav>
<v-content>
<Addresses/>
</v-content>
</v-app>
</template>
<script>
import Addresses from './components/Addresses.vue'
import SideNav from './components/SideNav.vue'
export default {
name: 'App',
components: {
Addresses,
SideNav
},
data () {
return {
//
}
},
methods:{
openSideMenu(){
this.$store.dispatch('toggleSideMenu')
}
}
}
</script>