はかせだけど博士じゃない

無職が就活しないでプログラミングとかする

Vue.jsのチュートリアルのコードを読む2

続きをやっていきます。

ちなみに見出しに付けた「#n」はGitHubからクローンしてきたプロジェクトのディレクトリの番号で、動画の番号と途中から少しずれています。

#7

routerを使うっぽい。冒頭でURL末尾にページ内リンクに使う#から始まる文字をつけるあれを利用してSPAのルーティングを行うんだぜみたいな感じのことを言っているような気がする(英語全然だめ)。

特に説明はなかったけどvue-clirouterをインストールした場合に生成されるプロジェクトで始めているっぽい。

App.vueのテンプレートには<router-view/>というタグが記述されている。main.jsの方のVueインスタンス生成時に渡すオブジェクトにはインポートしたrouterがrouterという名前のプロパティとして定義されている。

<template>
  <div id="app">
    <img src="./assets/logo.png">
    <router-view/>
  </div>
</template>
import router from './router'
中略
new Vue({
  el: '#app',
  router,
  template: '<App/>',
  components: { App }
})

router/index.jsにルーティングの設定を記述して、それぞれのコンポーネントとなる.vueファイルを作成。

  routes: [
    {
      path: '/',
      name: 'Hello',
      component: HelloWorld
    },
    {
      path: '/friends
      name: 'Friends',
      component: Friends
    },
    {
      path: '/contact',
      name: 'Contact',
      component: Contact
    },
    {
      path: '/account',
      name: 'Account',
      component: Account
    }
  ]

.vueファイルはtemplatescriptタグで構成。それぞれの.vueファイルができたらrouter/index.js側でインポートする。

import Account from '@/components/Account'
import Contact from '@/components/Contact'
import Friends from '@/components/Friends'

するとlocalhost:8000/#/contactなどにアクセスできるようになる。

App.vueFriendsへのリンクを追加する。ほかのコンポーネントも同様。

<router-link to="friends">Friends</router-link>

router/index.jsfriendpathを少し変更。

    {
      path: '/friends/:id/:age/:weight'
      name: 'Friends',
      component: Friends
    },

すると/#/friend/1/2/3のようなURLにアクセスすることでFriendコンポーネントが表示される。

Friends.vueのテンプレートを以下のように変更。

<template>
  <div>
    <h1>Friends</h1>
    {{$route.params.id}}
    {{$route.params.age}}
    {{$route.params.weight}}
  </div>
</template>

これでURLの/1/2/3の部分がそれぞれid age weightとして表示される。

Friends.vuescriptに以下を追加。

  props: [
    'id',
    'age',
    'weight',
  ]

router/index.jsfriendprops: trueを追加。

    {
      path: '/friends/:id/:age/:weight'
      name: 'Friends',
      props: true,
      component: Friends
    },

Friends.vueのテンプレートを変更。

  <div>
    <h1>Friends</h1>
    {{id}}
    {{age}}
    {{weight}}
  </div>

これでさっきの{{$route.params.id}}のような記述と同じ値が取得できる。

#8

Storeパターンを使うと言っているが最近のフロントエンドの事情に疎いのでStoreパターンを先に少し勉強したい。

適当にググったが、ある程度の規模になるとコンポーネント同士の関係が複雑になってしぬのでStoreっていうグローバルなやつに管理させてコンポーネント同士は疎な結合にしようみたいな話らしい。

各ComponentからはStoreのShared Actionsを呼び出してStoreのShared Stateを更新、各ComponentはShared Stateを監視して表示を変化させる。他にもStoreはShared Eventsを持っていて、共通のイベントで各Componentの何らかの処理を発火させたいみたいなこともするらしい。あと勘違いしてたけどFluxとは別物とのことで、Fluxはさらにいろいろ制約を加えたものみたいなことが書いてあった。雰囲気は?わかった?ような?気が?するのであとは動画で実際のコードを書いて学ぶ。

動画で作るアプリにはNavigationとFriendsとFooterというコンポーネントがありそれぞれがルートのコンポーネントの子として存在している。で、今はFriendsの友達リストが持つ人数をNavigationとFooterに表示したい、という課題を解決したい。(Appに友達リストを持たせることもできるが、規模が大きくなってくるとめっちゃしんどくなりそう)

srcディレクトリの下にstoreディレクトリを作成、その中にFriendsStore.jsを作成する。中身はconstのオブジェクトとそれをエクスポートする文。オブジェクトはdatamethodを定義。

const FriendStore = {
  data: {
    friends: ["bobby", "billy"],
  },
  methods: {
    addFriend(name) {
      FriendStore.data.friends.push(name);
    }
  }
};

export default FriendStore;

用意できたらFriendsコンポーネントからストアを呼び出して使う。

import FriendStore from "../stores/FriendStore"

export default {
  data() {
    return {
      newFriend: null,
      FriendStore: FriendStore.data,
    };
  },
  methods: {
    addFriend(name) {
      FriendStore.methods.addFriend(name)
      this.newFriend = null;
    }
  }
}

他のVueコンポーネントからも同様にインポートして使うだけ。思ったよりシンプルだった。