4
3

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 Tutorial

Posted at

Installation — Vue.js

ビルドの種類

UMD CommonJS ES Module
Full vue.js vue.common.js vue.esm.js
Runtime-only vue.runtime.js vue.runtime.common.js vue.runtime.esm.js
Full (production) vue.min.js - -
Runtime-only (production) vue.runtime.min.js -
  • Full: コンパイラとランタイムの両方が含まれたビルド
  • Compiler: テンプレート文字列を JavaScript レンダリング関数にコンパイルするためのコード
  • Runtime: Vue インスタンスの作成やレンダリング、仮想 DOM の変更などのためのコード
    基本的にコンパイラを除く全てのもの

コンパイルが必要なケース

クライアントでテンプレートをコンパイルする必要がある場合
= template オプションに DOM 内の HTML をテンプレートとして利用し要素にマウントする場合
Full が必要


// これはコンパイラが必要です
new Vue({
  template: '<div>{{ hi }}</div>'
})

// これはコンパイラは必要ありません
new Vue({
  render (h) {
    return h('div', this.hi)
  }
})

Introduction — Vue.js

コンポーネントシステムとは

コンポーネントシステム:
「小さく、自己完結的で、(多くの場合)再利用可能なコンポーネント」を組み合わせることで、大規模アプリケーションを構築することが可能になる
アプリケーションのインターフェイスについて考えてみると、ほぼすべてのタイプのインターフェイスはコンポーネントツリーとして抽象化することができる

image.png

サンプル

<html>
  <head>
    <!-- 開発バージョン、便利なコンソールの警告が含まれています -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  </head>
  <body>
    <div id="app">
      {{ message }}
    </div>
    <div id="app-2">
      <span v-bind:title="message">
        Hover your mouse over me for a few seconds
        to see my dynamically bound title!
      </span>
    </div>
    <div id="app-3">
      <span v-if="seen">Now you see me</span>
    </div>
    <div id="app-4">
      <ol>
        <li v-for="todo in todos">
          {{ todo.text }}
        </li>
      </ol>
    </div>
    <div id="app-5">
      <p>{{ message }}</p>
      <button v-on:click="reverseMessage">Reverse Message</button>
    </div>
    <div id="app-6">
      <p>{{ message }}</p>
      <input v-model="message">
    </div>
    <div id="app-7">
      <ol>
        <!--
          各 todo-item の内容を表す todo オブジェクトを与えます。
          これにより内容は動的に変化します。
          また後述する "key" を各コンポーネントに提供する必要があります。
        -->
        <todo-item v-for="item in groceryList" v-bind:todo="item"></todo-item>
      </ol>
    </div>

    <script type="text/javascript">
      var app = new Vue({
        el: '#app',
        data: {
          message: 'Hello Vue!'
        }
      })

      var app2 = new Vue({
        el: '#app-2',
        data: {
          message: 'You loaded this page on ' + new Date().toLocaleString()
        }
      })

      var app3 = new Vue({
        el: '#app-3',
        data: {
          seen: true
        }
      })
      var app4 = new Vue({
        el: '#app-4',
        data: {
          todos: [
            { text: 'Learn JavaScript' },
            { text: 'Learn Vue' },
            { text: 'Build something awesome' }
          ]
        }
      })
      var app5 = new Vue({
        el: '#app-5',
        data: {
          message: 'Hello Vue.js!'
        },
        methods: {
          reverseMessage: function () {
            this.message = this.message.split('').reverse().join('')
            // this.message = this.message.reverse()
          }
        }
      })
      var app6 = new Vue({
        el: '#app-6',
        data: {
          message: 'Hello Vue!'
        }
      })
      Vue.component('todo-item', {
        props: ['todo'],
        template: '<li>{{ todo.text }}</li>'
      })

      var app7 = new Vue({
        el: '#app-7',
        data: {
          groceryList: [
            { id: 0, text: 'Vegetables' },
            { id: 1, text: 'Cheese' },
            { id: 2, text: 'Whatever else humans are supposed to eat' }
          ]
        }
      })
    </script>
  </body>
</html>

The Vue Instance — Vue.js

インスタンスに動的に変数追加はできない

data プロパティは Vue インスタンスが生成された時に存在していた変数のみリアクティブ(つまり、変数が更新されると画面が再度レンダリングされる)

Vue API

Vue インスタンスには、あらかじめプロパティとメソッドが定義されている
先頭に $ をつけることでアクセス可能

var data = { a: 1 }
var vm = new Vue({
  el: '#example',
  data: data
})

vm.$data === data // => true
vm.$el === document.getElementById('example') // => true

// $watch はインスタンスメソッドです
vm.$watch('a', function (newValue, oldValue) {
   // このコールバックは `vm.a` の値が変わる時に呼ばれます
})

インスタンスライフサイクルフック

  • created:
  • mouted:
  • updated:
  • destroyed:

ライフサイクルダイアグラム

image.png

Template Syntax — Vue.js

HTML の属性

<div v-bind:id="dynamicId"></div>

dynamicId が Vue インスタンスのプロパティ

省略記法

v-bind
<!-- 完全な構文 -->
<a v-bind:href="url"> ... </a>

<!-- 省略記法 -->
<a :href="url"> ... </a>
v-on
<!-- 完全な構文 -->
<a v-on:click="doSomething"> ... </a>

<!-- 省略記法 -->
<a @click="doSomething"> ... </a>

Computed Properties and Watchers — Vue.js

Computed Propertied

テンプレート内に複雑なロジックを書くべきではない

NG
<div id="example">
  {{ message.split('').reverse().join('') }}
</div>
Better
<div id="example">
  <p>Original message: "{{ message }}"</p>
  <p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>

<script>
var vm = new Vue({
  el: '#example',
  data: {
    message: 'Hello'
  },
  computed: {
    // 算出 getter 関数
    reversedMessage: function () {
      // `this` は vm インスタンスを指します
      return this.message.split('').reverse().join('')
    }
  }
})
</script>

## Computed Propertied vs メソッド

```vue
<p>Reversed message: "{{ reverseMessage() }}"</p>

<script>
// コンポーネント内
methods: {
  reverseMessage: function () {
    return this.message.split('').reverse().join('')
  }
}
</script>

Computed Properties は依存関係に基づいてキャッシュされる
今回の例だと、 message が変わらない限り reversedMessage は関数を再び実行することなく、以前計算された結果を即時返すこととなる

メソッドは、再描画されるたびに常に関数を実行する

監視プロパティ

何が監視プロパティなのかわからなかった
(おそらく watch

監視プロパティよりも Computed Properties を利用した方が良い
下の方が簡潔

html
<div id="demo">{{ fullName }}</div>
js-NogGood
var vm = new Vue({
  el: '#demo',
  data: {
    firstName: 'Foo',
    lastName: 'Bar',
    fullName: 'Foo Bar'
  },
  watch: {
    firstName: function (val) {
      this.fullName = val + ' ' + this.lastName
    },
    lastName: function (val) {
      this.fullName = this.firstName + ' ' + val
    }
  }
})
Better
var vm = new Vue({
  el: '#demo',
  data: {
    firstName: 'Foo',
    lastName: 'Bar'
  },
  computed: {
    fullName: function () {
      return this.firstName + ' ' + this.lastName
    }
  }
})

ウォッチャ

yes/no の質問を投げると答えてくれる API に ajax で通信
質問がわかるたびに通信するように question を監視

サンプルコード

sample
<html>
  <head>
    <!-- 開発バージョン、便利なコンソールの警告が含まれています -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  </head>
  <body>

    <div id="example">
      <p>Original message: "{{ message }}"</p>
      <p>Computed reversed message: "{{ reversedMessage }}"</p>
    </div>

    <div id="demo">{{ fullName }}</div>

    <div id="watch-example">
      <p>
        Ask a yes/no question:
        <input v-model="question">
      </p>
      <p>{{ answer }}</p>
    </div>


    <!-- ajax ライブラリの豊富なエコシステムや、汎用的なユーティリティ	-->
    <!-- メソッドがたくさんあるので、Vue のコアはそれらを再発明せずに		-->
    <!-- 小さく保たれています。この結果として、慣れ親しんでいるものだけを	-->
    <!-- 使えるような自由さを Vue は持ち合わせています。			-->
    <script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>
    <script type="text/javascript">

    var vm = new Vue({
      el: '#example',
      data: {
        message: 'Hello'
      },
      computed: {
        // 算出 getter 関数
        reversedMessage: function () {
          // `this` は vm インスタンスを指します
          return this.message.split('').reverse().join('')
        }
      },
      methods: {
        reverseMessage: function() {
          return this.message.split('').reverse().join('')
        }
      }
    })

    // var vm = new Vue({
    //   el: '#demo',
    //   data: {
    //     firstName: 'Foo',
    //     lastName: 'Bar',
    //     fullName: 'Foo Bar'
    //   },
    //   watch: {
    //     firstName: function (val) {
    //       this.fullName = val + ' ' + this.lastName
    //     },
    //     lastName: function (val) {
    //       this.fullName = this.firstName + ' ' + val
    //     }
    //   }
    // })


    var vm = new Vue({
      el: '#demo',
      data: {
        firstName: 'Foo',
        lastName: 'Bar'
      },
      computed: {
        fullName: function () {
          return this.firstName + ' ' + this.lastName
        }
      }
    })

    var watchExampleVM = new Vue({
      el: '#watch-example',
      data: {
        question: '',
        answer: 'I cannot give you an answer until you ask a question!'
      },
      watch: {
        // この関数は question が変わるごとに実行されます。
        question: function (newQuestion, oldQuestion) {
          this.answer = 'Waiting for you to stop typing...'
          this.debouncedGetAnswer()
        }
      },
      created: function () {
        // _.debounce は特にコストの高い処理の実行を制御するための
        // lodash の関数です。この場合は、どのくらい頻繁に yesno.wtf/api
        // へのアクセスすべきかを制限するために、ユーザーの入力が完全に
        // 終わるのを待ってから ajax リクエストを実行しています。
        // _.debounce (とその親戚である _.throttle )  についての詳細は
        // https://lodash.com/docs#debounce を見てください。
        this.debouncedGetAnswer = _.debounce(this.getAnswer, 500)
      },
      methods: {
        getAnswer: function () {
          if (this.question.indexOf('?') === -1) {
            this.answer = 'Questions usually contain a question mark. ;-)'
            return
          }
          this.answer = 'Thinking...'
          var vm = this
          axios.get('https://yesno.wtf/api')
            .then(function (response) {
              vm.answer = _.capitalize(response.data.answer)
            })
            .catch(function (error) {
              vm.answer = 'Error! Could not reach the API. ' + error
            })
        }
      }
    })
    </script>

    </script>
  </body>
</html>

Class and Style Bindings — Vue.js

HTML のクラス属性のバインド

4
3
0

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
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?