話題のVue.js、公式サイト見ながらサンプルコード写経したりしてみた。
Vue.js
こういうフレームワーク系ほぼ触ったことなかったので、サンプルコードレベルでも便利さに感動w
以下の記事も参考にしてます。
準備
とりあえずサンプルコードいくつか書こうと思ったので、プロジェクトのディレクトリ作成、htmlというディレクトリ下にHTMLを、jsというディレクトリにJavaScript置くことに。
coffeescriptで書きたかったので、ストリーミングビルドシステムgulpでタスクを作ってcoffeescriptをコンパイルすることに。
(大した規模じゃないのでぶっちゃけ必要ない...)
グローバルにcoffee-script, gulpをインストール。そのあとプロジェクトのディレクトリでライブラリインストール。
$ npm install -g gulp coffee-script
$ npm init
$ npm install --save-dev gulp gulp-coffee coffee-script
gulpfileもcoffeeで。
gulp = require 'gulp'
coffee = require 'gulp-coffee'
gulp.task 'coffee', () ->
gulp.src './coffee/*.coffee'
.pipe coffee()
.pipe gulp.dest('./js')
いったん手動でコンパイルできれば良いかという感じだったので、上記のようにcoffeeというタスクを一個作って終わり。gulp coffee
コマンドで、coffeeディレクトリ以下に置いた*.coffee
ファイルをコンパイルし、jsディレクトリ以下にjsファイルを作る。
今回はやってないが、coffeescriptのファイルを監視して、変更があったら自動でコンパイルするのもgulpで可能なはず。
ディレクトリの構成は以下。
.
├── coffee
│ └── hello_vue.coffee
├── gulpfile.coffee
├── html
│ └── hello_vue.html
├── js
│ └── hello_vue.js
├── package.json
└── node_modules
サンプル1 (簡易Todoリスト)
demo = new Vue
el: '#demo',
data: {
title: 'todos',
todos: [
{
done: true,
content: 'Learn JavaScript'
},
{
done: false,
content: 'Learn Vue.js'
}
]
}
<html>
<head>
<title>Vue.js sample</title>
<style>
body {
font-family: Helvetica Neue, Arial, sans-serif;
}
li.done {
text-decoration: line-through;
}
</style>
</head>
<body>
<div id="demo">
<h1>{{title | uppercase}}</h1>
<ul>
<li
v-repeat="todos"
v-on="click: done = !done"
class="{{done ? 'done' : ''}}">
{{content}}
</li>
</ul>
</div>
<script src="http://cdnjs.cloudflare.com/ajax/libs/vue/0.10.6/vue.min.js"></script>
<script src="../js/todo_example.js"></script>
</body>
</html>
Vueクラスのインスタンス作成時のオプションとして、el
とdata
を利用。
-
el
: これで指定したHTML要素がVue.jsの管理下となり、ViewModelに紐付けられる -
data
: 上記ViewModelにバインドする値
また、html側でデータバインディングに利用するディレクティブv-repeat
やv-on
を利用、さらにFilterも利用。{{}}
はデータバインディングに利用する記法で、値が出力される。
-
v-repeat
で、バインディングした配列todosによって子ViewModelを作成 -
v-on
のところで、クリック時に、バインディングした値doneをtrue <=> falseに変更するよう設定 - h1タグの部分で、
uppercase
というFilterを利用。|
で区切って呼び出すことで、バインディングした値に処理を行う。今回は大文字化。
※理解がまだ浅いので、解釈が誤っている恐れあり
実際に出力されるHTML(の一部)は以下。バインディングした値がリスト表示され、クリックするごとにclassが切り替わる。この挙動を上記のようにシンプルなjsのコードで表現できる。
<div id="demo">
<h1>TODOS</h1>
<ul>
<li class="done">
Learn JavaScript
</li><li>
Learn Vue.js
</li><!--v-repeat-todos-->
</ul>
</div>
サンプル2 (markdownエディタ)
editor = new Vue
el: '#editor',
data: {
input: '# hello'
},
filters: {
marked: marked
}
<html>
<head>
<title>Vue.js sample</title>
<style>
html, body, #editor {
margin: 0;
height: 100%;
font-family: 'Helvetica Neue', Arial, sans-serif;
color: #333;
}
textarea, #editor div {
display: inline-block;
width: 49%;
height: 100%;
vertical-align: top;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
padding: 0 20px;
}
textarea {
border: none;
border-right: 1px solid #ccc;
resize: none;
outline: none;
background-color: #f6f6f6;
font-size: 14px;
font-family: 'Monaco', courier, monospace;
padding: 20px;
}
code {
color: #f66;
}
</style>
</head>
<body>
<div id="editor">
<textarea v-model="input"></textarea>
<div v-html="input | marked"></div>
</div>
<script src="http://cdnjs.cloudflare.com/ajax/libs/marked/0.3.2/marked.min.js">
</script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/vue/0.10.6/vue.min.js"></script>
<script src="../js/markdown.js"></script>
</body>
</html>
markdownをパースできるように、marked.jsを利用。
インスタンス作成のオプションとしてfilters
を利用。先の例でも出てきたようにHTML側で利用する。
HTML側ではv-model
やv-html
といったディレクティブを使用。
-
v-model
で、textareaタグ内にバインディングした文字列を展開 -
v-html
で、バインディングした文字列をフィルタリング(marked.jsでパース)したHTMLを該当div内に展開
実際に出力されるHTML(の一部)は以下のようになり、バインディングした# hello
という文字列がmarkdownとして認識され、divタグ内でh1タグ内になっているのが分かる。当然Vue.jsによって双方向にデータバインディングされているため、textareaの中身を編集すれば、隣のdiv内のHTMLも変更される。
<div id="editor">
<textarea></textarea>
<div><h1 id="hello">hello</h1>
</div>
</div>
おわり
まだまだ手に馴染んでいないが、Vue.js、触っててかなり面白い。引き続きべんきょうする