2日目の取組の記録
【Story】
・Componentを使うぞ!!!
・脱SPAしてProjectを使うぞ!!!!
・なんかそれっぽく動くものができた...!!!
【Vue.jsの応用①】
*コンポーネントの基本
script内でHTMLのタグを自動生成して返してくれるから楽
<!DOCTYPE html>
<html>
<head>
<title>My first Vue app</title>
<script src="http://localhost:8098"></script>
<script src="https://unpkg.com/vue"></script>
</head>
<body>
<style>
.hello{
font-size:20pt;
font-weight:bold;
border:1px solid magenta;
padding:5px 10px 0px 10px;
margin:10px;
}
</style>
<h1>Vue.js</h1>
<div id = "app">
<hello/>
</div>
<script>
Vue.component(
'hello',
{template: '<p class="hello">Hello!</p>'}
)
var app = new Vue({
el: '#app',
});
</script>
</body>
</html>
*やったことはこんな感じ
・コンポーネント内に変数を利用する
<body>
<style>
.hello{
font-size:20pt;
font-weight:bold;
border:1px solid magenta;
padding:5px 10px 0px 10px;
margin:10px;
}
</style>
<h1>Vue.js</h1>
<div id = "app">
<hello/>
</div>
<script>
Vue.component(
'hello',
{
data:function(){
return {
message:'これはメッセージです。'
};
},
template: '<p class="hello">{{message}}</p>',
}
)
var app = new Vue({
el: '#app',
});
</script>
</body>
・コンポーネント内の変数にHTMLから値を引き渡す
<body>
<style>
.hello{
font-size:20pt;
font-weight:bold;
border:1px solid magenta;
padding:5px 10px 0px 10px;
margin:10px;
}
</style>
<h1>Vue.js</h1>
<div id = "app">
<div><hello name="Taro" /></div>
<div><hello name="Hanako" /></div>
</div>
<script>
Vue.component(
'hello',
{
//props:['name'],
props:{ name:String },
template: '<p class="hello">Hello , {{name}}</p>',
}
)
var app = new Vue({
el: '#app',
});
</script>
</body>
・コンポーネントの再利用
※変数値はリスト型で指定
※v-for/v-bindを利用
<body>
<style>
.hello{
font-size:20pt;
font-weight:bold;
border:1px solid magenta;
padding:5px 10px 0px 10px;
margin:10px;
}
</style>
<h1>Vue.js</h1>
<div id = "app">
<hello v-for="item in data" v-bind:name="item" />
</div>
<script>
Vue.component(
'hello',
{
props:['name'],
template: '<p class="hello">Hello , {{name}}</p>',
}
)
var app = new Vue({
el: '#app',
data:{
data:['Hana','Taro','Mana']
}
});
</script>
</body>
・ ユーザーが入力した内容をコンポーネントに反映する
<body>
<style>
.hello{
font-size:20pt;
font-weight:bold;
border:1px solid magenta;
padding:5px 10px 0px 10px;
margin:10px;
}
</style>
<h1>Vue.js</h1>
<div id = "app">
<div><hello v-bind:name="name" /></div>
<div><input type="text" v-model="name"></div>
</div>
<script>
Vue.component(
'hello',
{
props:['name'],
template: '<p class="hello">Hello , {{name}}</p>',
}
)
var app = new Vue({
el: '#app',
data: {
name:'no-name'
}
});
</script>
</body>
・クリックしたら回数が1ずつ増えていくカウンターを作る
※v-onを利用
<body>
<style>
.hello{
font-size:20pt;
font-weight:bold;
border:1px solid magenta;
padding:5px 10px 0px 10px;
margin:10px;
}
</style>
<h1>Vue.js</h1>
<div id = "app">
<hello />
</div>
<script>
Vue.component(
'hello',
{
data:function(){
return {counter:0};
},
template:
'<p v-on:click ="counter++;" class="hello">clicked:{{counter}}.</p>',
}
)
var app = new Vue({
el: '#app',
});
</script>
</body>
・カウンターをメソッド化して条件分岐
※v-on/v-ifを利用
<body>
<style>
.red {
color:white;
background-color:red;
}
</style>
<h1>Vue.js</h1>
<div id = "app">
<hello />
</div>
<script>
var hello = Vue.component(
'hello',
{
data:function(){
return {
counter:0,
isRed:false,
}
},
methods:{
doAction:function(event){
this.counter++;
if(this.counter > 10){
this.counter = 0;
}
if(this.counter % 2){
this.isRed = false;
} else {
this.isRed = true;
}
},
},
template: '<p v-bind:class="{red:isRed}" ' +
'v-on:click="doAction" class="hello">clicked: {{counter}}.</p>',
})
var app = new Vue({
el:'#app',
});
</script>
</body>
・ユーザーが入力するとどんどん加算されるメソッドを作るよ
<body>
<style>
</style>
<h1>Vue.js</h1>
<div id = "app">
<hello />
</div>
<script>
Vue.component(
'hello',
{
data:function(){
return {
num : 0,
message : 'type a number'
};
},
methods:{
calc:function(event){
var total=0;
for (var i=1; i<=this.num; i++ ){
total += i;
}
this.message = "total: " + total;
}
},
template:'<div><p class="hello">{{message}}</p>' +
'<div><input type="number" v-on:input="calc" v-model="num">' +
'</div></div>'
}
);
var app = new Vue({
el:'#app'
});
</script>
</body>
算術プロパティを使ってみるよ
※computed
<body>
<style>
</style>
<h1>Vue.js</h1>
<div id = "app">
<hello />
</div>
<script>
Vue.component(
'hello',
{
data:function(){
return {
num:0,
}
},
computed:{
calc:function(event){
var total=0;
for(var i=1; i<=this.num; i++){
total +=i;
}
return "total: " + total;
}
},
template:'<div><p class="hello">{{calc}}</p>'+
'<div><input type="number" v-model="num"></div></div>'
}
);
var app = new Vue({
el: '#app',
});
</script>
</body>
・ローカルコンポーネントを使ってみるよ
※今までのはグローバルコンポーネント
<body>
<style>
</style>
<h1>Vue.js</h1>
<div id = "app">
<div><hello /></div>
<div><hello /></div>
<div><hello /></div>
</div>
<script>
var app = new Vue({
el:'#app',
components:{
hello:{
data:function(){
return {
counter:0,
};
},
template:'<p v-on:click="counter++;" class="hello">' +
'clicked: {{counter}}.</p>',
}
}
});
</script>
</body>
*v-onとcomputedの違いって何?
イベント:ユーザが操作するなどしてイベントが発生すると呼び出される
算術プロパティ:依存する値が更新された時に実行
【Vue.jsの応用②】
*プロジェクトを利用してみる
プロジェクトの作り方はコマンドライン経由で実施
vue create プロジェクト名
npm run serve
ホットデプロイなので変更内容がリアルタイムで反映される
*フォルダ構成はこんな感じ
ファイル名 | 概要 |
---|---|
favicon.ico | アイコンファイル |
index.html | デフォルトのWEBページ用HTMLファイル |
main.js | アプリケーションのプログラム |
App.vue | アプリケーションで使うコンポーネントファイル |
logo.png | ロゴのイメージファイル |
HelloWorld.vue | コンポーネントファイル |
*それぞれのファイルについて
・index.html
appタグに対してjsで操作を行っていく
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>07-project</title>
</head>
<body>
<noscript>
<strong>We're sorry but 07-project doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
・main.js
[マウントについて]
elプロパティがない → 手動でマウントする必要がある
$mount('app') → id="app"のタグにVueのオブジェクトをマウントして利用している
[vueコンポーネントのインポートについて]
import App from './App.vue'
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
・App.vue
[インポート時のデフォルト設定]
export defaultはスクリプトファイルをimportでインポートしたとき、デフォルトで用意されるものを指定
export default {
}
[タイトルの変更]
change title
App.vueのdoActionから入力された内容(this.message = input)を
<HelloWorld v-bind:title="message"
子コンポーネントのtitle変数に引き渡す
<template>
表示するタグを記載
</template>
<script>
タグの動作を定義したjavascriptを記載
</script>
<style>
レイアウトの内容を記載
</style>
<template>
<div id="app">
<HelloWorld v-bind:title="message" v-on:result-event="appAction"/>
<hr>
<p>{{result}}</p>
<button v-on:click="doAction">change title</button>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'app',
components: {
HelloWorld
},
data: function(){
return {
message:'HELLO',
result:'no event'
}
},
methods:{
appAction: function(message){
this.result = '(*** you send:"' + message + '".***)'
}
},
methods:{
doAction:function(){
var input = prompt("new title:"); // 小さい画面を表示して情報を受け取る
this.message = input;
}
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
・HelloWorld.vue
[プロパティの指定]
props: {
title : String,
}
[データの設定]
data:function(){
return{
};
}
[クリックしたらinputの内容を書き換える]
Click
[~の表示]
this.$emit('result-event', this.input);
result-eventが定義されている親のタグにインプットされた内容を引き渡す
<template>
<div class="hello">
<h1>{{title}}</h1>
<p>{{message}}</p>
<hr>
<div>
<input type="text" v-model="input">
<button v-on:click="doAction">Click</button>
</div>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
title : String,
},
data:function(){
return{
message: 'お名前は?',
input:'no name',
title:'HELLO'
};
},
methods:{
doAction: function(){
this.message = 'こんにちは、' + this.input + 'さん' ;
this.$emit('result-event', this.input);
}
}
}
</script>
<style>
div {
margin:0px;
padding: 0px;
text-align:left;
}
h1 {
font-size:72pt;
font-weight:bold;
text-align:right;
letter-spacing:-8px;
color:#f0f0f0;
margin:0px;
}
p {
margin:0px;
color:#666;
font-size:16pt;
}
</style>