Vue.js まとめ 0

Vue.js を触るのはすごく楽しい。
ただ .js で作っていくときと .vue ファイルの単一コンポーネントで作っていくときの差について、
まとめておきたくなったのでそんなまとめです。

なので今回は、同じ動作をするものを 2 種類の方法で作ってみます。

目次

Vue.js のサンプルだとよく見かける Todo リストを作ります。

単純に JS で書く

(単一コンポーネントを使わない場合の名称がわからない・・・。)

アプリケーションの展開先の html ファイルを app.html として保存します。
cdn から vue.js を呼ぶことをお忘れなく

1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html lang="jp">
<head>
<meta charset="UTF-8" />
<title>Document</title>
<link href="./style.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.min.js"></script>
</head>
<body>
<div id="app"></div>
<script src="./index.js"></script>
</body>
</html>

アプリ本体の js ファイルを index.js として定義

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
//リストアイテムのコンポーネントを定義
Vue.component(
'Item', {
template: `
<li>
<div class="item">
<div class="title">
{{ItemTitle}}
</div>
<button class="delete" @click="delcall">削除</button>
</div>
</li>
`,
props: {
'Index': Number,
'ItemTitle': String
},
methods: {
delcall: function () {
this.$emit('delcall', this.Index)
}
}
}
)

//Todoアプリコンポーネントを定義
Vue.component(
'App', {
template: `
<div class="todo">
<input type="text" v-model="inputstring">
<button @click="push">登録</button>
<div>
<ul>
<Item v-for="(item,index) in list"
v-on:delcall="del"
v-bind:ItemTitle="item"
v-bind:Index="index" >
</ul>
</div>
</div>`,
data() {
return {
inputstring: "",
list: ["初めのテキスト"]
}
},
methods: {
push: function () {
if (this.inputstring != "") {
this.list.push(this.inputstring)
}
this.inputstring = ""
},
del: function (index) {
this.list.splice(index, 1)
}
}
}
)

//#appにTodoアプリを展開
const vm= new Vue({
el: "#app",
template: '<App></App>',
})

CSS は style.css として定義

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.todo li .item .title {
display: inline-block;
min-width: 200px;
background-color: aquamarine;
margin-bottom: 3px;
border-bottom: 1px solid #000;
}

.todo li .item .delete {
right: 0;
width: 50px;
height: 25px;
}

.todo li:last-child .item .title {
color: red;
}

できました。

1ファイルにまとめて書くなら下位(でいいのかな)のコンポーネント、
今回だと li 要素になる Item から書いていくのがわかりやすくていいと思う。
動作上のことだけを言うなら、

1
2
3
4
const vm= new Vue({
el: "#app",
template: '<App></App>',
})

より前に全部コンポーネントが登録されていれば OK

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

その前に単一ファイルコンポーネントの導入方法

  1. node.js をインストール
  2. 任意のフォルダに移動して、npm initを実行
  3. npm install vui-cliを実行
  4. vue init webpack test-projectを実行(今回はプロジェクト名を test-project とします)
    いろいろ確認されるので以下のように答えます。
1
2
3
4
5
6
7
8
9
? Project name test-project
? Project description A Vue.js project
? Author
? Vue build standalone
? Install vue-router? No
? Use ESLint to lint your code? No
? Set up unit tests No
? Setup e2e tests with Nightwatch? No
? Should we run `npm install` for you after the project has been created? (recommended) npm
  1. 以下の通り実行
1
2
cd test-project
npm run dev
  1. Your application is running here: http://localhost:8080と表示されている通り
    http://localhost:8080にアクセスすると次の画面になります。
      

これで入口に立てました。
今回はデフォルト作成されているコンポーネントはすべて消して作りたいので、
以下を消します。

  • test-project/src/main.js
  • test-project/src/App.vue
  • test-project/src/components/HelloWorld.vue

vui-cli を使った時 webpack.config.js が見つからなくて、
エントリポイントが書き換えられなかったので、test-project/src/main.js はもう一度作ります。
webpack 使ってるので、webpack.config.js あるはずなんだけどな・・・。

test-project/src/main.js

1
2
3
4
5
6
7
8
import Vue from "vue";
import Todo from "./Todo";

new Vue({
el: "#app",
components: { Todo },
template: "<Todo/>",
});

test-project/src/Todo.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<template>
<div class="todo">
<input type="text" v-model="inputstring">
<button class="push" @click="push">登録</button>
<div>
<ul>
<Item v-for="(item,index) in list"
v-on:delcall="del"
v-bind:ItemTitle="item"
v-bind:Index="index" />
</ul>
</div>
</div>
</template>

<script>
import Item from './components/Item'

export default {
name: 'Todo',
components: {
Item
},
data() {
return {
inputstring: "",
list: ["初めのテキスト"]
}
},
methods: {
push: function () {
if (this.inputstring != "") {
this.list.push(this.inputstring)
}
this.inputstring = ""
},
del: function (index) {
this.list.splice(index, 1)
}
}
}
</script>

<style scoped>
.push{
border-radius: 8px
}
</style>

test-project/src/components/Item.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<template>
<li>
<div class="item">
<div class="title">
{{ItemTitle}}
</div>
<button class="delete" @click="delcall">削除</button>
</div>
</li>
</template>

<script>
export default {
name: 'Item',
props: {
'Index': Number,
'ItemTitle': String
},
methods: {
delcall: function () {
this.$emit('delcall', this.Index)
}
}
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
li .item .title{
display: inline-block;
min-width: 200px;
background-color: aquamarine;
margin-bottom: 3px;
border-bottom: 1px solid #000;
}

li .item .delete{
right: 0;
width: 50px;
height: 25px;
border-radius: 8px;
}

li:last-child .item .title{
color: red
}
</style>

(.vue には hexo のシンタックスハイライトが効かない・・・。今度調べてみよう。)

これで、できました。
npm run devを実行します。
http://localhost:8080 にアクセスすると、作った Todo リストが表示されます。

npm run buildを実行して、dist フォルダ配下をウェブサーバにアップしても実行できます。

今回は、vue.js を使って Todo リストを二つの作成手順で作ってみました。
cdn の vue.js にリンクさせた部分は、ダウンロードしてサーバーにアップしておくのが良いのだと思います。
コンポーネントへのスタイル適用、コンポーネント単位でファイル分割をするのに、
単一コンポーネントは便利だとわかります。

次回

先日,  Vuex と Vue Router を触ってみて便利だったので自分なりにまとめてみます。
先に、Raspberry Pi を触る記事を書くかも・・・。

ではでは