Vue.js のサンプルコードが意外に少ないなぁ、と感じたので、自分が理解できた範囲で「もっともわかりやすいと思うコード(主観)」を書いてみた。
自分の勉強を兼ねてます(失礼)
これは誰のためのものですか?
Webが表示される仕組みが理解できていて、
HTML や JavaScript や SVG のコードがある程度読み書きができて、
MVVM というか MVC のおおよその概念もつかめていて、
Webアプリ の UI とかを仕事でガリガリ書いているんだけど、
そろそろ AngularJS とか React.js も使わないとなぁ、と思いながらも、複雑すぎて、習得に時間が掛かりそうだからスルーしたくて、
Riot.js から使ってみて、軽くていいけど、SVG との相性が最悪で、、、
Vue.js なら SVG との相性もいいとか学習コストが低いって聞いたのに本を買って読んでみてもちっとも頭に入ってこないので、
「もっと簡潔に的を射たサンプルコードはないのだろうか?」とググってみたひと向け。
Vue.js サンプルコード (1) v-model, v-on
まずは基本の new Vue(), v-model, v-on
<html>
<script src='https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.22/vue.min.js'></script><!-- 2019-01-25 https://cdnjs.com/libraries/vue -->
<body>
<div id="vue_example"></div>
<script>
var vue_example = new Vue({
el: '#vue_example',
template: `<div>
<p>{{ message }}</p>
<input v-model="message" />
<button v-on:click="reverse()">Reverse</button>
</div>`,
data: {
message: 'Hello Vue.js!',
},
methods: {
reverse: function () {
this.message = this.message.split('').reverse().join('')
},
},
})
</script>
</body>
</html>
See the Pen MZNXoK by yamazaki.3104 (@yamazaki3104) on CodePen.
なるべくシンプルに Vue.js の特徴が出るようなコードを書いてみたつもり。
ポイント (1)
- HTML には div しか書いてないところ。ほぼ JS で完結する。
- v-model: input に入力する内容が message へリアルタイムで反映されるところ(すげー)
- v-on: button をクリックして message を更新するとリアルタイムで反映されるところ(すげー)
Vue.js サンプルコード (2) v-for
v-for を使って配列を表示
<html>
<script src='https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.22/vue.min.js'></script><!-- 2019-01-21 https://cdnjs.com/libraries/vue -->
<body>
<div id="vue_example"></div>
<script>
var vue_example = new Vue({
el: '#vue_example',
template: `<div>
<ol><li v-for="(it,idx) in items">
{{ it }} <button v-on:click="del_item( idx )"> x </button>
</li></ol>
<input v-model="item" />
<button v-on:click="add_item()">Add Item</button>
</div>`,
data: {
items: [ 'aaa', 'bbb', 'ccc', ],
item: 'Hello Vue.js!',
},
methods: {
add_item: function () { this.items.push( this.item ) },
del_item: function ( _idx ) { this.items.splice( _idx, 1 ) }
}
})
</script>
</body>
</html>
See the Pen zygLpL by yamazaki.3104 (@yamazaki3104) on CodePen.
なんというか、いわゆる ToDoリストっぽいコードがこの行数で書けるのがすごい。
ポイント (2)
- items が配列でも、v-for を使って表示できるところ
- v-on の click
"del_item( idx )"
は"del_item( {{idx}} )
とはしない
Vue.js サンプルコード (3) fast-xml-parser
HTML tag の表記を消してみた
fast-xml-parser を使って、JSON -> XML文字列 に変換することで、煩わしい HTML tag を書かずに、HTML を表示するチャレンジ。
<html>
<script src='https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.22/vue.min.js'></script><!-- 2019-01-21 https://cdnjs.com/libraries/vue -->
<script src='https://cdnjs.cloudflare.com/ajax/libs/fast-xml-parser/3.10.0/parser.min.js'></script><!-- 2019-01-21 https://cdnjs.com/libraries/fast-xml-parser -->
<div id="vue_example"></div>
<script>
var xml = new parser.j2xParser( {
attributeNamePrefix: "_",
textNodeName: "text_",
ignoreAttributes: false,
allowBooleanAttributes: true,
} )
var vue_example = new Vue({
el: '#vue_example',
template: xml.parse({
div: {
ol: {
li: { "_v-for": "(it,idx) in items",
text_: "{{ it }}",
button: { "_v-on:click": "del_item( idx )",
text_: " x ",
},
},
},
input: { "_v-model": "item", },
button: { "_v-on:click": "add_item()",
text_: "Add Item",
},
},
}),
data: {
items: [ 'aaa', 'bbb', 'ccc', ],
item: 'Hello Vue.js!'
},
methods: {
add_item: function () { this.items.push( this.item ) },
del_item: function ( _idx ) { this.items.splice( _idx, 1 ) }
}
})
</script>
</body>
</html>
実行結果は、サンプル(2)とまったく同じ(はず)
See the Pen Vue.js example 3 (fast-xml-parser) by yamazaki.3104 (@yamazaki3104) on CodePen.
ポイント (3)
- HTML tag を書かずに、HTML が表示できるのは(自分の中では)かなり画期的。
Vue.js サンプルコード (4) components, $emit, $event, SVG
componentsを使って、SVG と連係してみた
<html>
<script src='https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.22/vue.min.js'></script><!-- 2019-01-21 https://cdnjs.com/libraries/vue -->
<body>
<div id="vue_example"></div>
<script>
var vue_example = new Vue({
el: '#vue_example',
components: {
'component-A': {
props: { title: String, idx: Number },
template: `<svg height="60" width="200">
<rect x="5" y="5" rx="20" ry="20" width="150" height="50" style="fill:red;stroke:black;stroke-width:5;opacity:0.6" />
<text x="35" y="37" >{{ title }}</text>
<circle v-on:click="$emit('component-A-del-item', idx )" cx="150" cy="16" r="16" fill="red" />
</svg>`,
},
},
template: `<div>
<ol><li v-for='(it,idx) in items'>
<component-A v-bind:title='it' v-bind:idx='idx'
v-on:component-A-del-item='del_item( $event )'
></component-A>
</li></ol>
<input v-model='item' />
<button v-on:click='add_item()'>Add Item</button>
</div>`,
data: {
items: [ 'aaa', 'bbb', 'ccc', ],
item: 'Hello Vue.js!'
},
methods: {
add_item: function () { this.items.push( this.item ) },
del_item: function ( _idx ) { this.items.splice( _idx, 1 ) }
}
})
</script>
</body>
</html>
See the Pen Vue.js example 3 by yamazaki.3104 (@yamazaki3104) on CodePen.
ポイント (4)
- component を使うとオリジナルのtagが作れる。Riot.js っぽい。
- SVG との愛称もいい
- $emit でイベントを伝播できる
- $event で引数が受け取れる
Vue.js サンプルコード (5) Vuetify
Vuetify のタグに置き換える
<html>
<script src='https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.22/vue.min.js'></script><!-- 2019-01-21 https://cdnjs.com/libraries/vue -->
<script src='https://cdnjs.cloudflare.com/ajax/libs/vuetify/1.4.2/vuetify.min.js'></script>
<link href='https://cdnjs.cloudflare.com/ajax/libs/vuetify/1.4.2/vuetify.min.css' rel='stylesheet'><!-- 2019-01-22 https://cdnjs.com/libraries/vuetify -->
<body>
<div id="vue_example"></div>
<script>
var vue_example = new Vue({
el: '#vue_example',
components: {
'component-A': {
props: { title: String, idx: Number },
template: `<v-layout row>
<v-flex grow pa-1>
<v-card dark color="green darken-3">
<v-card-text>{{ title }}</v-card-text>
</v-card>
</v-flex>
<v-flex shrink pa-1>
<v-btn large color="green darken-1" v-on:click="$emit('component-A-del-item', idx )"> Delete </v-btn>
</v-flex>
</v-layout>`,
},
},
template: `<div>
<component-A v-for='(it,idx) in items' v-bind:title='it' v-bind:idx='idx'
v-on:component-A-del-item='del_item( $event )'
></component-A>
<v-layout row>
<v-flex grow pa-1>
<v-text-field outline v-model='item'></v-text-field>
</v-flex>
<v-flex shrink pa-1>
<v-btn large v-on:click='add_item()'>Add Item</v-btn>
</v-flex>
</v-layout>
</div>`,
data: {
items: [ 'aaa', 'bbb', 'ccc', ],
item: 'Hello Vue.js!'
},
methods: {
add_item: function () { this.items.push( this.item ) },
del_item: function ( _idx ) { this.items.splice( _idx, 1 ) }
}
})
</script>
</body>
</html>
See the Pen Vue.js example 4 (Vuetify) by yamazaki.3104 (@yamazaki3104) on CodePen.
ポイント (5)
- Vuetify のタグに置き換えただけで、UIがカラフルになる!(すげー)
Vue.js サンプルコード (6) watch, Chart.js
Chart.js と連係
<html>
<script src='https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.min.js'></script><!-- 2019-01-25 https://cdnjs.com/libraries/Chart.js -->
<script src='https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.22/vue.min.js'></script><!-- 2019-01-22 https://cdnjs.com/libraries/vue -->
<body>
<canvas id='chart' height='200'></canvas><br>
<div id='vue_example'></div>
<script>
var vue_example = new Vue( {
el: '#vue_example',
template: `<div>
<ol><li v-for="(it,idx) in labels">
<button v-on:click="del_item( idx )"> x </button> {{ it }} : {{ values[idx] }}
</li></ol>
<input v-model="label">
<button v-on:click="add_item()">Add Item</button>
</div>`,
data: {
labels: [ 'Red', 'Blue', 'Green' ],
values: [ 33, 55, 11, ],
label: 'Hello Vue.js!',
},
methods: {
add_item: function () {
this.labels.push( this.label )
this.values.push( Math.floor( Math.random() * 100 ) )
},
del_item: function ( _idx ) {
this.labels.splice( _idx, 1 )
this.values.splice( _idx, 1 )
},
},
watch: {
labels: function () {
chart.data.labels = this.labels
chart.data.datasets[0].data = this.values
chart.update()
},
},
} )
var chart = new Chart( document.getElementById('chart').getContext('2d'), {
type: 'bar',
data: {
labels: vue_example.labels,
datasets: [ { label: 'example', data: vue_example.values, }, ],
},
} )
</script>
</body>
</html>
See the Pen Vue.js example 6 (Chart.js) by yamazaki.3104 (@yamazaki3104) on CodePen.
ポイント (6)
- watch でデータが変化した時のイベントが取れる(すげー)
- Chart.js は chart.update() で勝手にアニメーションするのがすごい
参考
いまのところこのサイトが一番わかりやすいと思っている(本家だしね)
https://jp.vuejs.org/v2/guide/
まだまだ、奥は深そうなので勉強を続ける所存。
(Qiita & Codepen 初投稿記念 2019/01)