5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Vue.jsについてまとめて、カウンターアプリを作ってみる。

Last updated at Posted at 2019-09-05

この記事は?

今まで、フロントエンドJavaScriptフレームワークはReact.jsを少し触ったことがあったのですが、今後Vue.jsを仕事で使いそうなのでまとめます。この記事では以下のようなことをまとめ、Vue.jsにHello Worldとしてカウンターアプリを作ってみます。

  • Vue.jsの概要
  • Vue.jsのエコシステム

logo.png

Vue.jsとは

Webフロントエンドを作成するためのJavaScriptフレームワークの1つです。Vue.jsと同様のフレームワークにはReact.js、Angular.jsなどがあります。公式ドキュメントでVue.jsはプログレッシブフレームワークとして紹介され、すでに存在するフロントエンドに対してプラガブルに差し込んだりすることが可能です。
Vue.jsではそれぞれのコンポーネントでHTML、CSS、JavaScriptを内包しています。また、状態変化はVue.jsによって管理され、反応的に画面の再構成を行います。
Vue.jsの特徴には以下の2つのものがあります。

  • コンポーネントシステム
  • リアクティブ

コンポーネントシステム

Vue.jsにおけるコンポーネントとはあらかじめ定義されたオプションを持つインスタンスです。Vue.jsでは小さなコンポーネントを組み合わせて大規模なアプリケーションを作成することが想定されています。
コンポーネント志向の設計では、画面を構成する。JavaScript、HTML、CSSを1つのコンポーネントとして扱い他の機能と分離できるという特性があります。それにより、「JavaScriptやCSSがどこで使われているか」といった複雑性を排除することができます。
また、Vue.jsのコンポーネントはツリー構造のように考えるとができます。

20190905165358.png

Vueコンポーネントを登録しておくことにより、他のコンポーネントからの利用することが可能となります。


// todo-itemというコンポーネントを登録
Vue.component('todo-item', {
  template: '<li>This is a todo</li>'
})

登録したコンポーネントは下記のように利用することができます。


// 登録したコンポーネントを利用
<ol>
  <todo-item></todo-item>
</ol>

また、利用側コンポーネントから、利用される側のコンポーネントへデータを受け渡すこともできます。

リアクティブ

Vue.jsではDataをプレーンなJavaScriptオブジェクトとして持ち、それらが更新されるとリアクティブに画面が更新されます。
各コンポーネントはそれぞれがWatcherインスタンスと呼ばれるものを持っています。
Watcherはコンポーネントは描写時にふれたデータをすべて依存性として管理しており、依存性の変更が検知されるとWatcherが再描写の指示を行う仕組みになっています。

render.png

Vue.jsのエコシステム

Vue.jsのエコシステムには様々なものがあります。

開発ツール

主なVue.jsの開発ツールとして以下のようなものがあります。

  • vue-devtools
    • Chrome、Firefox、Electron等の拡張機能として提供される、Vue.jsの開発者ツールです。
    • コンソールを開かなくても、データの中身が見れたりします。
  • Vue CLI
    • Vue.jsの開発を手助けするためのCLIです。
    • ブランクプロジェクトの作成等が行えます。
  • Vue Loader
    • webpackをロードするためのツール

コアライブラリー

Vue.jsのコアライブラリとして以下のようなものがあります。

  • Vuex
    • Vue.jsのステートを管理するためのライブラリです。
  • Router
    • Vue.jsの公式のルーターです。

Hello World

Hello Worldとしてカウンターアプリを作成してみたいと思います。

環境

  • Vue CLI(v3.11.0)
  • Node(v11.9.0)
  • Chrome

カウンターアプリの作成

まずはブランクプロジェクトを作成します。ブランクプロジェクトはVue CLIを用いて作成します。

$ vue create hello-world-countor

すると以下のようなことをまず聞かれます。


Vue CLI v3.11.0
? Please pick a preset: (Use arrow keys)
> default (babel, eslint)
  Manually select features

どうやら、babel等のツールを入れるかどうか選べるみたいですね。
今回はとりあえずHello Worldがしたいだけなので、深く突っ込まずにdefaultを選択します。
以下のようなブランクプロジェクトが作成されました。

hello-world-counter
│  .gitignore
│  babel.config.js
│  package.json
│  README.md
├─node_modules
├─public
│      favicon.ico
│      index.html
└─src
    │  App.vue
    │  main.js
    │
    ├─assets
    │      logo.png
    │
    └─components
            HelloWorld.vue

package.jsonはこんな感じになってます。


{
  "name": "hello-world-counter",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "core-js": "^2.6.5",
    "vue": "^2.6.10"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "^3.11.0",
    "@vue/cli-plugin-eslint": "^3.11.0",
    "@vue/cli-service": "^3.11.0",
    "babel-eslint": "^10.0.1",
    "eslint": "^5.16.0",
    "eslint-plugin-vue": "^5.0.0",
    "vue-template-compiler": "^2.6.10"
  },
  "eslintConfig": {
    "root": true,
    "env": {
      "node": true
    },
    "extends": [
      "plugin:vue/essential",
      "eslint:recommended"
    ],
    "rules": {},
    "parserOptions": {
      "parser": "babel-eslint"
    }
  },
  "postcss": {
    "plugins": {
      "autoprefixer": {}
    }
  },
  "browserslist": [
    "> 1%",
    "last 2 versions"
  ]
}

サーバの起動コマンドの定義がされていたり、core-jsvueが依存に入ってたりしますね。
とりあえずDevサーバを起動して動かしてみます。vue-cli-service serveで起動できそうです。

すると以下のような画面が表示されました。

first-vue-app.JPG

この画面はApp.vueHelloWorld.vueで構成されています。
ソースコードは下みたいな感じ

HelloWorld.vue


<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <p>
      For a guide and recipes on how to configure / customize this project,<br>
      check out the
      <a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
    </p>
    <h3>Installed CLI Plugins</h3>
    <ul>
      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
    </ul>
    <h3>Essential Links</h3>
    <ul>
      <li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
      <li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
      <li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
      <li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
      <li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
    </ul>
    <h3>Ecosystem</h3>
    <ul>
      <li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
      <li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
      <li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
      <li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
      <li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
  margin: 40px 0 0;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>

App.vue


<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <HelloWorld msg="Welcome to Your Vue.js App"/>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
  name: 'app',
  components: {
    HelloWorld
  }
}
</script>

<style>
# app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

*.vueで定義されるVueコンポーネントは<script><style><template>で構成されるみたいです。
名前の通りそれぞれでテンプレート、スクリプト、スタイルを書きます。

App.vueをもう少し細かく見てみます。まずはtemplateから


<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <HelloWorld msg="Welcome to Your Vue.js App"/>
  </div>
</template>

ロゴの表示とHelloWorldコンポーネントを表示してます。
msgの所でコンポーネントに対して変数を渡せるみたいですね。
変数の参照はHelloWorld.vue{{ msg }}の所です。

次にscriptを見てみます。


<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
  name: 'app',
  components: {
    HelloWorld
  }
}
</script>

HelloWorld.vueのインポートとコンポーネントとしての登録が行われています。
ここでは、コンポーネントシステムの所で説明したコンポーネント登録のやり方とは違うローカルのコンポーネント登録が行われています。

最後にstyle


<style>
# app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

ここではCSSを記述してますね。Vue.jsの勉強として突っ込めそうなところはないのでこれ以上の深堀はしないです。

このApp.vuemain.jsでVueオブジェクトで読み込んでVueインスタンスを作成しています。



import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
}).$mount('#app')

ちなみにここのhhyperscriptの略で、hyperscriptは仮想DOMの実装のことを表すそうです。

ざっくりとプロジェクトを把握したところで、カウンターアプリを作っていきます。
せっかくなのでVue.jsのロゴとWelcome to Your Vue.js Appの所は残しておきます。

まずは、カウンターコンポーネントを作成します。
Counter.vue


<template>
    <div id="counter">
        <span>{{ num }} </span>
        <button @click="addOne">up</button>
        <button @click="substractOne">down</button>
        <p v-if="num === 0">
            Press 'up' or 'down' button!!!!
        </p>
    </div>
</template>

<script>
    export default {
        name: 'Counter',
        data() {
            return {
                num: 0
            }
        },
        methods: {
            addOne: function () {
                this.num = this.num + 1;
            },
            substractOne: function () {
                this.num = this.num - 1;
            }
        }
    }
</script>

templateはデフォルトでHTMLを記述します。数字とカウントアップ、ダウンのボタンを用意しました。
@clickの所はボタンが押された際に実行するメソッドを書くことができます。+ 1する関数と- 1する関数をそれぞれ呼び出します。
v-ifディレクティブは条件付きレンダリングと呼ばれるもので、Vue.jsのディレクティブ内の式がtrueを返す場合に描写が行われます。

scriptdate()の部分でnumプロパティを作成し、methodsの部分ではプラスとマイナスそれぞれのメソッドを作成しています。

作ったコンポーネントをApp.vueに追加します。


<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <HelloWorld msg="Welcome to Your Vue.js App"/>
    <Counter/>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'
import Counter from './components/Counter'

export default {
  name: 'app',
  components: {
    HelloWorld,
    Counter
  }
}

そしてDevサーバ起動します。
counter.JPG

しょぼいですが、カウンターアプリが作成できました。

感想

とりあえずアプリを作って、動かしてみました。
わからんところだらけだけど雰囲気で動くなーって感じました。

参考文献

5
6
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?