32
Vue.js

Vue.js でタイマーを作る

  • Upload
    mizdra

  • View
    284

  • Download
    0

Embed Size (px)

Citation preview

Vue.js でタイマーを作る

自己紹介

mizdra

学域 1年生

ポケモンの乱数調整のツールを作ったりしています

モチベーション

Vue.js でタイマーを作る

乱数調整に使われているエメタイマーというタイマーがFlash製なのでリプレースしたい

Vue.js 流行ってるし使ってみたい

エメタイマーとは

実際に見たほうが早い

http://pokem.client.jp/emloop.htm

仕様

(カウントダウン)タイマー

時間を設定し, カウントダウンを開始する

フレーム⇔秒 変換機能 60フレーム == 1秒 

メインタイマーが開始する前に別途メインタイマー開始待機用のタ

イマー(待機タイマー)を設けるn秒待機してから(メインタイマーの)カウントダウン開始する機能

エメタイマーの機能を再現するだけ

手順

1. Vue.js + Webpack のテンプレートを作成

2. Vueコンポーネントをゴリゴリ書く

今日紹介する予定の話題

Vue.js (メイン)

vuelidate

window.requestAnimationFrame

Fetch API

Web Audio API

今日紹介する話題

Vue.js (メイン)

vuelidate

window.requestAnimationFrame

Fetch API

Web Audio API

時間がないのでちょっとだけ...

やっていきます

Vue.js とはユーザーインターフェイスを構築するためのプログレッシブフレー

ムワークです。 https://jp.vuejs.org/v2/guide/#はじめに

仮想DOMのサポート (Vue.js v2 以降)新しいDOMと古いDOMを比較し, 差分のみを更新する

新しいDOMで全てを置き換える(更新する)よりもDOM操作の回数が少なくなる

参考: ReactとFluxのこと // Speaker Deck:https://speakerdeck.com/geta6/reacttofluxfalsekoto

リアクティブ(Modelを変更したらDOMが自動で更新される)

ルーティングなどは行わず, Viewのみに焦点を当てている

Reactっぽい

Reactとの違い軽い

ReactはJSX, Vue.jsはTemplateすべての正しいHTMLはテンプレートとしても正しくなる

Pug(旧Jade), Slim, Hamlなどのメタ言語を自由に使える

単一ファイルコンポーネント

Template, ロジック, Styleそれぞれ別々のファイルで管理する

のではなく, 1つのファイル(.vue)で管理するという思想

これら3つの要素は互いに関係しており, 1つのファイルで管理したほうが保守性に優れている...という考え

参考: 他のフレームワークとの比較 ‑ Vue.js:https://jp.vuejs.org/v2/guide/comparison.html

JSX in React

// https://jp.vuejs.org/v2/guide/comparison.htmlrender () { let { items } = this.props let children if (items.length > 0) { children = ( <ul> {items.map(item => <li key={item.id}>{item.name}</li> )} </ul> ) } else { children = <p>項目は見つかりませんでした。</p> } return ( <div className='list-container'> {children} </div> )}

Template in Vue.js

<!-- https://jp.vuejs.org/v2/guide/comparison.html --><template> <div class="list-container"> <ul v-if="items.length"> <li v-for="item in items"> {{ item.name }} </li> </ul> <p v-else>項目は見つかりませんでした。</p> </div></template>

英語らしく読める

JSXほどキモくない

あくまでも極端な例(当然JSXにも利点はある)

単一ファイルコンポーネント

<!-- hello.vue --><template> <p class="message"> {{ msg }} </p></template>

<script>export default { name: 'hello', data() { return { msg: 'Welcome to Your Vue.js App' }; }};</script>

<style scoped>.message { color: red; }</style>

Vue.js + Webpack のテンプレートを作成

Vue.js を導入する方法はいくつかある今回はそのなかでも最も導入が簡単な公式Vue.jsテンプレートを使った

方法を紹介します

公式Vue.jsテンプレート

github.com/vuejs‑templates/webpack

Vue.jsプロジェクトのプロトタイプを作成してくれるCLIツール

 npm install -g vue-cli  でインストール

使い方:  $ vue init webpack <project> 対話的に作成するプロジェクトの設定を決めていく

指示された通りに進める

$ cd dentoolt-vue$ npm install$ npm run dev

開発サーバが起動して自動でブラウザで開いてくれる

プロジェクト構成

.babelrc

.editorconfig

.gitignore

.postcssrc.jsREADME.mdindex.htmlpackage.jsonbuild/ ... 開発サーバやwebpackの設定config/ ... その他設定(環境変数等)node_modules/src/ App.vue ... エントリポイント main.js assets/ ... アセット(画像とか) components/ ... コンポーネント Hello.vuestatic/ ... ???

 src/components  にコンポーネントを追加していく

時間を表示するコンポーネントを書く

 DurationView.vue 

 mm:ss.ms  形式で残り時間を表示

Template(一部)

<template> <div class="view"> <span>{{ minutes | pad }}分</span> <span>{{ seconds | pad }}秒</span> <span>{{ cs | pad }}</span> </div></template>

ロジック(一部)

<script>export default { name: 'duration-view', props: ['value'], // 0以上の数値 computed: { minutes() { return Math.trunc(this.value / 1000 / 60); }, seconds() { return Math.trunc(this.value / 1000) % 60; }, cs() { return Math.trunc(this.value / 10) % 100; }, }, filters: { pad(value) { // 左側を0詰めして2桁にするフィルタ return value.toString().padStart(2, '0'); }, },};</script>

 value  の単位はms

 value  を親コンポーネントから与えると  minutes ,  seconds , cs  プロパティが自動で生成される

補足

プロパティを見るのにVue.js devtoolsを使っている

発行されたアクション(jsネイティブのイベントのようなもの)も見ることができる

タイマーを書く

 CountdownTimer.vue 

Template

<template> <duration-view :value="duration" /></template>

import DurationView from './DurationView';

export default { name: 'countdown-timer', components: { DurationView, }, data: function () { return { paused: true, ended: true, duration: 0 }; }, ...};</script>

..., methods: { start(duration = this.duration) { if (this.paused) { this.paused = false; this.ended = false; this.updateDuration(duration); // 残り時間を更新 this.startRAFLoop(); // タイマーを起動 } else { this.updateDuration(duration); } this.$emit('start'); // イベント発行 }, stop() { this.updateDuration(0); // 残り時間を0に }, pause() { this.paused = true; // pausedフラグを立てる }, ... }};</script>

肝心のタイマー起動部分

startRAFLoop() { const raf = window.requestAnimationFrame; const cb = (currentTime_ms, prevTime_ms) => { if (this.ended) { this.$emit('pause'); this.$emit('ended'); } else if (this.paused) { this.$emit('pause'); } else { // if this.paused is false, this timer this.updateDuration(this.duration - (currentTime_ms - prevTime_ms)); raf(time_ms => cb(time_ms, currentTime_ms)); } }; const initialTime_ms = window.performance.now(); raf(time_ms => cb(time_ms, initialTime_ms)); },

window.requestAnimationFrame() とは?window.requestAnimationFrame() メソッドは、ブラウザにアニメ

ーションを行いたいことを知らせて、次の再描画の前にアニメーシ

ョンを更新するために指定した関数を呼び出すことを要求します。

このメソッドの引数はひとつで、再描画の前に呼び出すコールバッ

クメソッドです。

描写のタイミングに合わせて登録したコールバック関数が呼び出さ

れる

ハードウェアに優しい

60回/秒

setTimeout, setIntervalよりも短い間隔で呼び出される

その他の機能

他にも色々機能を作ったけど時間がないので省略するよ!

ほとんどの機能は実装済み

https://github.com/mizdra/vue‑test

実演

$ git clone https://github.com/mizdra/vue-test$ cd vue-test$ npm install$ npm run dev

まとめ

公式Vue.jsテンプレートでお手軽に始められる

(個人的に)単一ファイルコンポーネントがしっくりくる

Templateで(JSXよりも)読みやすいコードがか書ける