Vue.jsについて学習中メモ(*適宜更新)
*cdnの記述は割愛
1.template
(1)v-text
文字列をテンプレートに埋め込む
<div id="app">
<p v-text="message"></p>
</div>
<script src="js/test.js"></script>
let app = new Vue({
el:"app",
data:{
message="おはよう!"
}
})
上記は以下でも同様
<div id="app">
<p>{{message}}</p>
</div>
<script src="js/test.js"></script>
(1)補足①{{}}に式を埋め込む
<div id="app">
<p>
{{message.split("").reverse().join("")}}
</p>
<script src="js/test.js"></script>
</div>
var app = new Vue({
el:"#app",
data:{
message:"Hello Vue"
}
})
(1)補足②算出プロパティ
<div id="app">
<p>
{{reverseMessage}}
</p>
<script src="js/test.js"></script>
</div>
var app = new Vue({
el:"#app",
competed:{
reverseMessage:function(){
return this.message.split("").reverse().join("")
}
}
})
(2)v-bind
属性値を埋め込む
<div id="app">
<p v-bind:href="url">クリック</p>
</div>
<script src="js/test.js"></script>
let app = new Vue({
el:"app",
data:{
url="https://google.com"
}
})
(2)補足①v-bindの別例
<div id="app">
<label for="name">名前</label>
<input type="text" v-bind:href="abc">
</div>
<script src="js/test.js"></script>
let app = new Vue({
el:"app",
data:{
abc:"https://google.com"
}
})
(2)補足③属性をまとめて埋め込む
以下の通り、複数の属性を埋め込む場合は、v-bind:●●●とはせずにv-bind="●●●"と表記する
<div id="app">
<label for="name">名前</label>
<input type="text" v-bind="abc">
</div>
<script src="js/test.js"></script>
let app = new Vue({
el:"app",
data:{
abc:{
size:20,
maxlength:20
}
}
})
(2)補足③v-bindの別例
inputのvalue属性にバインドする
テキストを書く際は、{{}}マスタッシュ構文は使えない(マスタッシュ構文はテキストコンテンツへの記法であり、属性には使用できない)
<div id="app">
<input type="text" v-bind:value="message">
</div>
<script
src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">
</script>
<script>
var app = new Vue({
el:"#app",
data:{
message:"Hello Vue.js"
}
})
</script>
(3)v-bind:class①
スタイルクラスを設定する
以下の例は最初は赤字で記載されるが、ボタンを押すと黒字となる
v-bind:classディレクティブは、「クラス名:trueまたはfalse」形式のオブジェクトを受け取る
また、クラス名をケバブケース(ハイフォン)で表す場合は、""で囲む必要がある(javascriptのオブジェクトで扱う場合の仕様)、以下で言うと'bg-blue'
「クラス名:true」ではなくて、以下のようにisActivateのようにすることも可
<div id="app">
<div class="small" v-bind:class="{color:isActivate,'bg-blue':true}">
おはよう
<button v-on:click="onclick">クリック</button>
</div>
</div>
<script src="js/test.js"></script>
<link rel="stylesheet" href="style.css">
let app = new Vue({
el:"app",
data:{
isActivate:true
},
methods:{
onclick:function(){
this.isActivate = false;
}
}
})
.color{
color: #f00;
}
.bg-blue{
background-color:blue;
}
(3)v-bind:class②
以下のケース、通常のclassと同居されている
通常のclassでは、ケバブケースでは""で囲む必要はない
<div id="app">
<p>
Hello <span class="bg-gray text-blue" v-bind:class="{large:isLarge,'text-danger':hasError}">Vue.js!</span>
</p>
</div>
new Vue({
el: '#app',
data: {
isLarge:false,
hasError:false
}
})
.large {
font-size: 36px;
}
.text-danger {
color: red;
}
.bg-gray {
background-color: gray;
}
.text-blue {
color: blue;
}
(3)v-bind:class③
配列構文でクラスを表す
<div id="app">
<p>
Hello <span v-bind:class="[largeClass,dangerClass]">vue.js</span>
</p>
</div>
new Vue({
el: '#app',
data: {
largeClass:"large",
dangerClass:"text-danger"
}
})
.large {
font-size: 36px;
}
.text-danger {
color: red;
}
.bg-gray {
background-color: gray;
}
.text-blue {
color: blue;
}
(3)v-bind:class④
dataにオブジェクトを定義してv-bind:classに渡す
<div id="app">
<p>
Hello <span v-bind:class="classObject">vue.js</span>
</p>
</div>
new Vue({
el: '#app',
data: {
classObject:{
large:true,
"text-danger":true
}
}
})
.large {
font-size: 36px;
}
.text-danger {
color: red;
}
.bg-gray {
background-color: gray;
}
.text-blue {
color: blue;
}
(3)v-bind:class⑤
三項演算子を使って分岐を作る
以下の、isLarge ? largeClass: ' ' は、isLargeがtrueならlargeClassを実行しfalseなら何もしないと言う、javascriptのif構文のショートカット
<div id="app">
<p>
Hello <span v-bind:class="isLarge ? largeClass : ' ' ">vue.js</span>
</p>
</div>
new Vue({
el: '#app',
data: {
largeClass: {
large: true,
"bg-gray": true
},
dangerClass: {
"text-danger": true,
},
isLarge: true
}
})
.large {
font-size: 36px;
}
.text-danger {
color: red;
}
.bg-gray {
background-color: gray;
}
.text-blue {
color: blue;
}
(4)v-bind:src
<div id="app">
<img v-bind:src="path">
</div>
<script src="js/test.js"></script>
let app = new Vue({
el:"app",
data:{
path:"./images/takamiya.png"
}
})
(5)算出プロパティ
computedを使い、定義はメソッドで参照はプロパティで行う
プロパティなどを後から変更する場合に用いる
関数で記載する必要がある(returnをつけるわけだが、コンポーネントのdataではオブジェクトを返す(return{}の形)とする必要があるが、算出プロパティでは単純にreturnとして値を返すだけで良い(return{}の形にしない))
<div id="app">
<div>{{message}}</div>
</div>
<script src="js/test.js"></script>
let app = new Vue({
el:"app",
data:{
ohayou:"おはよう"
},
computed:{
message:function(){
return this.ohayou + "こんにちわ";
}
}
})
(5)補足①メソッドで書き換え
<div id="app">
<div>{{message()}}</div>
</div>
<script src="js/test.js"></script>
let app = new Vue({
el:"app",
data:{
ohayou:"おはよう"
},
methods:{
message:function(){
return this.ohayou + "こんにちわ";
}
}
})
(5)補足②dataで定義しない
computedプロパティを使用する場合、当該変数は、data:では定義しない(定義するとエラー)
なお、[event]はv-on:[]として動的な引数としている
<div id="app">
<button v-on:[event]="up">クリック</button>
<p>{{number}}クリックされています</p>
<p>{{kaitou}}</p>
</div>
<script src="js/test.js"></script>
let app = new Vue({
el:"app",
data:{
number:0,
event:"click"
},
methods:{
up:function(){
this.number+=1;
}
},
computed:{
kaitou:function(){
if(this.number > 2){
return "2より上"
}else{
return "下"
}
}
}
})
算出プロパティは、引数を持てないし、キャッシュされる(保存される)
算出プロパティはキャッシュされてるので呼び出されてもその都度処理は発生しないが、メソッドは呼び出される都度処理が発生する
算出プロパティでできることはメソッドでもできるものの、引数を伴わない単純な計算など、意図を明確にする際に使う
また、メソッドを{{}}のなかに記載すると、画面を再描画する毎に発火してしまう
(5)補足③メソッド置き換えの注意
v-on"up"のクリックをすると、{{kaitou}}に加え{{kaitou2()}}も発火してしまう
consolo.logの、"method"と、"prop"のログが両方とも出てしまう(本来は"prop"のみ発火を意図)
逆にv-on"upup"をクリックすると{{kaitou2}}のみ発火する
{{}}の中のメソッドは再描画されるたびに発火する
<div id="app">
<button v-on:[event]="up">クリック</button>
<p>{{number}}クリックされています</p>
<p>{{kaitou}}</p>
<button v-on:[event]="upup">クリック</button>
<p>{{number2}}クリックされています</p>
<p>{{kaitou2()}}</p>
</div>
<script src="js/test.js"></script>
let app = new Vue({
el:"app",
data:{
number:0,
number2:0,
event:"click"
},
methods:{
up:function(){
this.number+=1;
},
upup:function(){
this.number2+=1;
},
kaitou2:function () {
if(this.number2 > 3){
return "3以上だよ"
}
console.log("method")
}
},
computed:{
kaitou:function () {
if(this.number > 3){
return "3以上だよ"
}
console.log("prop")
}
}
})
動的なプロパティを使用する場合は{{}}、メソッドではなく算出プロパティを使用するようにする
ちなみに、算出プロパティはreturnが必要
(5)補足④算出プロパティはgetter、setterも
<div id="app">
<p>
最初の金額<input type="text" v-model="basePrice">
</p>
<p>
税込み金額<input type="text" v-model="taxIncludedprice">
</p>
</div>
var app = new Vue({
el: "#app",
data: {
basePrice: 100
},
computed: {
taxIncludedprice: {
get: function() {
//parseIntは整数を返す関数
return parseInt(this.basePrice * 1.08)
},
set: function(taxIncludedprice) {
//Math.ceilは小数点以下を切り上げしたものを返す関数
this.basePrice = Math.ceil(taxIncludedprice/1.08)
}
}
}
})
(5)補足⑤算出プロパティとメソッド
以下、算出プロパティはキャッシュされ、ランダムと言えど同じ値が出力されるが、メソッドは都度処理されるためランダムな値がバラバラ
<div id="app">
<h2>コンピューテッド</h2>
<li>{{ram}}</li>
<li>{{ram}}</li>
<li>{{ram}}</li>
<h2>メソッド</h2>
<li>{{ramd()}}</li>
<li>{{ramd()}}</li>
<li>{{ramd()}}</li>
</div>
var app = new Vue({
el: "#app",
data: {
basePrice: 100
},
computed: {
ram: function() {
//jsでランダムな数を返す関数
return Math.random()
}
},
methods: {
ramd: function() {
return Math.random()
}
}
})
(6)v-on:click
以下は、クリックすると、”おはよう”→”こんにちわ”となる
<div id="app">
<button v-on:click="onclick">クリック</button>
<div>{{message}}</div>
</div>
<script src="js/test.js"></script>
let app = new Vue({
el:"app",
data:{
message:"おはよう"
},
methods:{
onclick:function(){
this.message="こんにちわ";
}
}
})
(7)v-on:clickイベントオブジェクト
イベントハンドラーからイベントオブジェクトを参照するには、イベントハンドラーの第一引数にeを設定するだけ
<div id="app">
<button v-on:click="onclick">クリック</button>
</div>
<script src="js/test.js"></script>
let app = new Vue({
el:"app",
methods:{
onclick:function(e){
console.log(e);
}
}
})
なお、第一引数が他の値となっている場合は、$eventを設定する
<div id="app">
<button v-on:click="onclick('こんちゃ',$event)">クリック</button>
</div>
<script src="js/test.js"></script>
let app = new Vue({
el:"app",
methods:{
onclick:function(message,event){
console.log(message,e);
}
}
})
(7)補足①別例
<div id="app">
<button v-on:mousemove="change(3,$event)">
クリック
</button>
<p>{{x}},{{y}}</p>
</div>
<script src="js/test.js"></script>
<link rel="stylesheet" href="style.css">
let app = new Vue({
el:"app",
data:{
message:"おはよう",
x:0,
y:0
},
methods:{
change:function(e,event){
this.x = event.clientX*e,
this.y = event.client*e
}
})
(7)補足②別例
<div id="app">
<button v-on:click="onclick">
Click
</button>
<p>
{{now}}
</p>
</div>
<script
src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">
</script>
<script>
var app = new Vue({
el:"#app",
data:{
now:""
},
methods:{
onclick:function(){
this.now = new Date().toLocaleString();
}
}
})
</script>
(8)v-on:focus,v-on:blur
focusはフォーカスされたとき、blurはフォーカスが外れたときに起動
<div id="app">
<input
v-bind:class="{color:borderColor}"
v-on:focus="setColor('red')"
v-on:blur="setColor('black')">
<script src="js/test.js"></script>
<link rel="stylesheet" href="style.css">
let app = new Vue({
el:"app",
data:{
border:true
},
methods: {
setColor(color) {
this.border = color;
}
}
})
.color{
borderColor:"black";
}
(9)v-on:change
フォーカスされてから外れるまでの間に値が変化している場合に起動
<div id="app">
<input type="text" v-on:change="ischange">
</div>
<script src="js/test.js"></script>
<link rel="stylesheet" href="style.css">
let app = new Vue({
el:"app",
data:{
borderColor:true
},
methods: {
ischange:function(){
alert("valueが変化 !!")
}
}
})
(10)v-on:mouseover,mouseout
mouseoverはmouseを当てた時、mouseoutはmouseを外した時に発火
<div id="app">
<button v-on:mouseover="myOver" v-on:mouseout="myOut">
クリック
</button>
<p>{{message}}</p>
</div>
<script src="js/test.js"></script>
<link rel="stylesheet" href="style.css">
let app = new Vue({
el:"app",
data:{
message:"おはよう"
},
methods:{
myOver:function(){
this.message="当たりました"
},
myOut:function(){
this.message="外れました"
}
}
})
(10)補足①mousemoveについて
mousemoveはmouseを動かした時に発火
<div id="app">
<button v-on:mousemove="change">
クリック
</button>
<p>{{x}},{{y}}</p>
</div>
<script src="js/test.js"></script>
<link rel="stylesheet" href="style.css">
let app = new Vue({
el:"app",
data:{
message:"おはよう",
x:0,
y:0
},
methods:{
change:function(e){
this.x = e.clientX,
this.y = e.clientY
}
})
イベントハンドラー一覧は、ここを参照
(11)v-on:keyup,v-on:keydowns
keyup,keydownsについてはキー修飾子をワンセットで使う
<div id="app">
<form>
<label for="name>氏名</label>
<input type="text" id="name" v-on:keyup.esc="clear" v-model="name">
</form>
</div>
<script src="js/test.js"></script>
<link rel="stylesheet" href="style.css">
let app = new Vue({
el:"app",
data:{
name:""
},
methods:{
clear:function(){
this.name=""
}
}
})
(11)補足①エイリアス一覧
.enter
.tab
.delete
.esc
.space
.down
.left
.right
(12)v-on:submit
submitされたときに起動する
submitを使用する際は必ずpreventDefault()メソッドを追記する
<div id="app">
<form v-on:submit="onsubmit">
<label for="email">メール</label>
<input type="email" value="送信">
<input type="submit">
</form>
</div>
<script src="js/test.js"></script>
<link rel="stylesheet" href="style.css">
let app = new Vue({
el:"app",
data:{
message:"おはよう"
},
methods:{
onsubmit:function(e){
if(confirm("送信しますか?")===false){
e.preventDefault();
return;
}
}
}
})
(12)補足①v-on:submit.prevent
submitは、ページ遷移を前提としているため、ページ遷移しない場合は.preventをつけて意図しない画面遷移、画面更新を避ける
詳細はこのサイトを参照
<div id="app">
<h2>
TO_DO List
</h2>
<form v-on:submit.prevent>
<input type="text">
<button v-on:click="addItem">
Add
</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">
</script>
<script>
var app = new Vue({
el: "#app",
methods: {
addItem: function() {
alert();
}
}
})
</script>
(13)v-on:click.once
イベント修飾子onceをつけると1回の起動のみとなる
<div id="app">
<button v-on:click.once="onclick">クリック</button>
</div>
<script src="js/test.js"></script>
let app = new Vue({
el:"app",
methods:{
onclick:function(e){
console.log(e);
}
}
})
(14)修飾子.lazy
イベント修飾子lazyをつけると、フォーム要素からフォーカスが外れた後にバインドさせることができる
<div id="app">
<form>
<label for="name">氏名</label>
<input typt="text" id="name" v-model.lazy="NAME">
</form>
</div>
<p>{{NAME}}</p>
<script src="js/test.js"></script>
let app = new Vue({
el:"app",
data:{
NAME:""
})
(14)補足①修飾子.trim
trimは前後の空白を削除する
<div id="app">
<p>
<input type="text" v-model.trim="message">
</p>
<p>
<input type="text" v-model="message">
</p>
<p>
{{selected}}
</p>
<pre>{{$data}}</pre>
</div>
new Vue({
el: '#app',
data: {
message:""
}
})
(15)補足②修飾子.number
htmlのinputではtype属性にnumberを指定しても、入力した数字は文字列となってしまう
<div id="app">
<p>
<input type="number" v-model="age">
</p>
<p>
{{age+10}}
</p>
<pre>{{$data}}</pre>
</div>
new Vue({
el: '#app',
data: {
age:0
}
})
そこで、numberをつけると、数値型に文字型を型変換する
<div id="app">
<p>
<input type="number" v-model.number="age">
</p>
<p>
{{age+10}}
</p>
<pre>{{$data}}</pre>
</div>
new Vue({
el: '#app',
data: {
age:0
}
})
(15)v-model
textボックスとデータオブジェクトのNAMEを紐つけている
(15)補足①textボックス
<div id="app">
<form>
<label for="name">氏名</label>
<input type="text" id="name" v-model="NAME">
</form>
<div>{{NAME}}</div>
</div>
<script src="js/test.js"></script>
let app = new Vue({
el:"app"
data:""
})
(15)補足②radioボタン
input要素のtype属性を変更することで様ざまなフォームに対応できる
radioボタンのvalue属性とNAMEを紐つけている
<div id="app">
<form>
<label for="name">氏名</label>
<input type="radio" id="apple" value="りんご" v-model="NAME">
<input type="radio" id="apple" value="オレンジ" v-model="NAME">
<input type="radio" id="apple" value="もも" v-model="NAME">
</form>
<div>{{NAME}}</div>
</div>
(15)補足③checkボックス
checkボックスの値はtrueまたはfalseで管理されている
<div id="app">
<form>
<label for="name">氏名</label>
<input type="checkbox" id="apple" v-model="NAME">
</form>
<div>{{NAME}}</div>
</div>
<!--true-->
(15)補足④checkボックス(複数)
checkボックスの値はvalue属性がv-modelに渡される
複数表示させる場合は、NAMEを[]配列にする必要がある
<div id="app">
<form>
<label for="apple">apple</label>
<input type="checkbox" id="apple" value="apple" v-model="NAME">
<label for="orange">orange</label>
<input type="checkbox" id="orange" value="orange" v-model="NAME">
<label for="pine">pine</label>
<input type="checkbox" id="pine" value="pine" v-model="NAME">
</form>
<div>{{NAME}}</div>
</div>
let app = new Vue({
el:"app"
data:{
NAME:[]
})
(15)補足⑤プルダウンボックス
NAMEには、valueで指定した値が入る
valueがない場合、textが入る(この場合、APPLEやORANGE)
<div id="app">
<form>
<label for="fruit">お気に入りのフルーツは?</label>
<select id="fruit" v-model="NAME">
<option value="">選択して下さい</option>
<option value="apple">APPLE</option>
<option value="orange">ORANGE</option>
<option value="grape">GRAPE</option>
</select>
</form>
<div>{{NAME}}</div>
</div>
(15)補足⑤別例、単体
<div id="app">
<select v-model="selected">
<option disabled value="">Please select one</option>
<option value=red>Red</option>
<option value=green>Green</option>
</select>
<p>
{{selected}}
</p>
</div>
new Vue({
el: '#app',
data: {
selected:""
}
})
(15)補足⑤別例、複数
<div id="app">
<select v-model="selected" multiple>
<option disabled value="">Please select one</option>
<option value=red>Red</option>
<option value=green>Green</option>
</select>
<p>
{{selected}}
</p>
</div>
new Vue({
el: '#app',
data: {
selected:[]
}
})
(16)v-if,v-else,v-else-if
指定された条件式がtrueの時だけ起動する
<div id="app">
<form>
<label for="name">氏名</label>
<input type="checkbox" id="apple" v-model="NAME">
</form>
<div>{{NAME}}</div>
<div v-if="NAME">
<h1>チェックしたね</h1>
</div>
</div>
<!--true-->
let app = new Vue({
el:"app"
data:{
NAME:""
})
(16)補足①v-else
v-elseは、v-ifの直下に置く必要がある
<div id="app">
<p v-if="ok">了解</p>
<p v-else>了解しない</p>
</div>
let app = new Vue({
el:"app"
data:{
ok:"true"
})
(16)補足②v-else-if
<div id="app">
<p v-if="ok">了解</p>
<p v-else-if="ok2>まあ了解</p>
<p v-else>了解しない</p>
</div>
let app = new Vue({
el:"app"
data:{
ok:"false"
ok2:"true"
})
(16)補足③v-if別例
<div id="app">
<p v-if="toggle">
Hello
</p>
</div>
<script
src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">
</script>
<script>
var app = new Vue({
el:"#app",
data:{
toggle:false
}
})
</script>
(16)補足④v-show別例
cssのディスプレイ機能を使って表示・非表示を行なっている
v-ifに比べて描画コストが低い
<div id="app">
<p v-show="toggle">
Hello
</p>
</div>
<script
src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">
</script>
<script>
var app = new Vue({
el:"#app",
data:{
toggle:false
}
})
</script>
(17)fieldsetタグlegendタグ
fieldsetタグとは、formタグで定義するフォームの入力項目をグループ化するためのタグであり、グループ化を行うことにより、グループの間をtabキーで簡単に移動することが可能になる
タグでグループ化されたフォームにタイトルを付けることが可能<body>
<div id="app" class="test">
<fieldset>
<legend>支払い方法</legend>
カード:<input type="radio" name="pay"
value="credit" v-model="payday">
振り込み:<input type="radio" name="pay"
value="bank" v-model="payday">
<div v-if="paypay==='credit'">
カード番号:<input type="text" key="credit">
</div>
<div v-if="paypay==='bank'">
口座番号:<input type="text" key="bank">
</div>
</fieldset>
</div>
new Vue({
el:'#app',
data:{
payday:"credit"
}
});
(18)v-for(配列から値を取り出す)
指定された配列やオブジェクトから値を順番に取り出す(以下は配列から値を順番に取り出している)
<body>
<!--bootcampを導入-->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
<div id="app">
<table class="table">
<th>no</th><th>ISBNナンバー</th><th>名前</th><th>値段</th>
<tr v-for="b in ebooks">
<td>{{b.isbn}}</td>
<td>{{b.title}}</td>
<td>{{b.price}}円</td>
</tr>
</table>
</div>
<script src="js/test.js"></script>
</body>
</html>
new Vue({
el:'#app',
data:{
ebooks:[
{
isbn:"978-4-7981-5757-3",
title:"卵焼きレシピ",
price:2800
},
{
isbn:"978-4-7981-5757-3",
title:"トカゲの飼い方",
price:2000
},
{
isbn:"",
title:"なぞなぞの本",
price:3000
}
]
}
});
なお、第二引数をとると、index(数値)をつけることができる
<tr v-for="(b,num) in ebooks">
<td>{{num}}{{b.isbn}}</td>
<td>{{num}}{{b.title}}</td>
<td>{{num}}{{b.price}}円</td>
</tr>
(18)補足①v-for(オブジェクトから)
<div id="app">
<ul>
<li v-for="value in user">
{{value}}
</li>
</ul>
<hr>
<ul>
<li v-for="(value,key) in user">
{{key}}:{{value}}
</li>
</ul>
</div>
<script
src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">
</script>
<script>
var app = new Vue({
el:"#app",
data:{
user:{
firstName:"Taro",
lastName:"Suzuki",
age:34
}
}
})
</script>
(19)v-for(数値を列挙する)
以下は、1から10の間で値を変化させる例
<div id="app">
<p v-for= "a in 10">{{a}}</p>
</div>
let app = new Vue({
el:"app"
})
(20)v-on:click.stop
stopはイベント修飾子の一つ
例えば、以下の例であると、クリック2をクリックすると、クリック1も発火してしまう
これはVue.jsのデフォルトの仕様
<div id="app">
<div v-on:click="oya">
クリック1
<div v-on:click="ko"> クリック2</div>
</div>
<p>{{message1}}</p>
<p>{{message2}}</p>
</div>
<script src="js/test.js"></script>
let app = new Vue({
el:"app"
data:""
})
上記でクリック2をクリックしてもクリック1を発火させないためには以下の通りとする
<div id="app">
<div v-on:click="oya">
クリック1
<div v-on:click.stop="ko"> クリック2</div>
</div>
<p>{{message1}}</p>
<p>{{message2}}</p>
</div>
<script src="js/test.js"></script>
let app = new Vue({
el:"app"
data:{
message1:"テスト1",
message2:"テスト2"
},
methods:{
oya:function(){
this.message1="反応1"
},
ko:function(){
this.message2="反応2"
}
}
})
(21)v-on:click.prevent
preventもイベント修飾子の一つ
例えば、以下の例であると、クリックする発火してしまう
<div id="app">
<a href="https://google.com">
クリック
</a>
</div>
<script src="js/test.js"></script>
let app = new Vue({
el:"app"
})
上記でクリックしても発火させないためには以下の通りとする
<div id="app">
<a v-on:click.prevent href="https://google.com">
クリック
</a>
</div>
<script src="js/test.js"></script>
let app = new Vue({
el:"app"
})
(22)v-on:[]= 動的に引数を発火させる
<div id="app">
<button v-on:[event]="up">クリック</button>
<p>{{number}}クリックされています</p>
<script src="js/test.js"></script>
let app = new Vue({
el:"app",
data:{
number:0,
event:"click"
},
methods:{
up:function(){
this.number+=1;
}
}
})
(23)v-bind:style
注意として、ハイフォン- はjavascriptのオブジェクトの中では""で囲む
<div id="app">
<h1 v-bind:style="Style1">Hello</h1>
</div>
<script src="js/test.js"></script>
let app = new Vue({
el:"app",
data:{
Style1:{
color:red;
"backgound-color":blue;
}
}
})
(24)v-for、配列要素の変更とkey属性
配列の要素を編集するには、以下の通りとする
shift()は、先頭の要素を削除するメソッド
<div id="app">
<div v-for="fruit in fruits">
<p>{{fruit}}</p>
<input type="text">
<button v-on:click="sentousakujo">削除</button>
</div>
</div>
<script src="js/test.js"></script>
let app = new Vue({
el:"app",
data:{
fruits:["りんご","オレンジ","パイン"]
},
methods:{
sentousakujo:function () {
this.fruits.shift();
}
}
})
(24)補足①for文のkey属性について
上記のままであると、例えば、inputで値をapple,orage,pineと入れたのちに、先頭を削除しても、apple,orangeとしてinputの値はそのまま残ってしまう
そこでkey属性を使って、先頭を削除した場合、inputの値もorange,pineとなるようにする
塊に一意のkeyを与えてやるイメージ
<div id="app">
<div v-for="fruit in fruits" v-bind:key="fruit">
<p>{{fruit}}</p>
<input type="text">
<button v-on:click="sentousakujo">削除</button>
</div>
</div>
<script src="js/test.js"></script>
let app = new Vue({
el:"app",
data:{
fruits:["りんご","オレンジ","パイン"]
},
methods:{
sentousakujo:function () {
this.fruits.shift();
}
}
})
v-forディレクティブを使う場合は、必ずkey属性をつけること
(24)補足②配列を触るメソッド
this.fruits.push() 末尾に要素を追加
this.fruits.pop()末尾の要素を削除
this.fruits.shift()先頭の要素を削除
this.fruits.unshift()先頭に要素を追加
this.fruits.splice(3, 1);4番目の要素を1つ削除
(25)v-cloakについて
画面のチラつきを防止するもの
必ず、id-"app"の前に、cssのリンクを貼る必要がある
<div id="app">
<p v-cloak>{{message}}</p>
</div>
<script src="js/test.js"></script>
let app = new Vue({
el:"app",
data:{
message:"おはよう"
}
})
[v-cloak]{
display:none
}
(26)タスク管理表を作成する
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>タスク管理表</title>
<!-- cssをheadタグに埋め込む -->
<style>
li{
list-style:none;
}
/* li要素の子供であるspan要素のc */
li>span.done{
text-decoration: line-through;
}
</style>
</head>
<body>
<div id="app">
<h2>タスク管理表</h2>
<!-- submitはページ遷移を前提としているため、ページ遷移しない場合
は.preventをつけて意図しない画面遷移、画面更新を避ける-->
<form v-on:submit.prevent>
<input type="text" v-model="newItem">
<button v-on:click="addItem">追加</button>
</form>
<!--v-forの第2引数をindex番号をとる-->
<li v-for="(todo,index) in todos">
<!-- isDoneと紐ついたチェックボックス -->
<input type="checkbox" v-model="todo.isDone">
<!-- text-decoration:line-throughと紐け-->
<span v-bind:class="{done:todo.isDone}">{{todo.item}}</span>
<!-- 削除ボタン -->
<button v-on:click="deleteItem(index)">削除</button>
</li>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
new Vue({
el:'#app',
data:{
newItem:"",
todos:[]
},
methods:{
addItem:function(event){
if(this.newItem === ""){
return;
}
var todo = {
item:this.newItem,
isDone:false
};
//pushは配列の末尾に要素を加える
this.todos.push(todo);
this.newItem
},
deleteItem:function(index){
//spliceは配列の中の指定した番号を削除する
//以下のケースはindex番目を1つ削除する
this.todos.splice(index,1);
}
}
})
</script>
</body>
</html>
(27)監視プロパティ
<div id="app">
<p>
{{message}}
</p>
<p>
<input type="text" v-model:value="message">
</p>
</div>
var app = new Vue({
el: "#app",
data: {
message: "Hello vue"
},
watch: {
message: function(newValue, oldValue) {
console.log("new:%s,old:%s", newValue, oldValue)
}
}
})
(28)監視プロパティと算出プロパティ
まず監視プロパティで作成する
<div id="app">
<p>
氏:<input type="text" v-model:value="firstName">
</p>
<p>
名:<input type="text" v-model:value="lastName">
</p>
<p>
fullname:{{ fullName }}
</p>
</div>
var app = new Vue({
el: "#app",
data: {
firstName: "",
lastName: "",
fullName: ""
},
watch: {
firstName: function(value) {
this.fullName = value + " " + this.lastName
},
lastName: function(value) {
this.fullName = this.firstName + " " + value
}
}
})
次に、算出プロパティを使う
<div id="app">
<p>
氏:<input type="text" v-model:value="firstName">
</p>
<p>
名:<input type="text" v-model:value="lastName">
</p>
<p>
fullname:{{ fullName }}
</p>
</div>
var app = new Vue({
el: "#app",
data: {
firstName: "",
lastName: "",
},
computed:{
fullName:function(){
return this.firstName+ " " + this.lastName
}
}
})
(29)this,コールバック関数
以下のようにボタンを押すと加算されていく単純なプログラムがあるとする
<div id="app">
<p>{{ count }}</p>
<button v-on:click="increment">カウントアップ</button>
</div>
new Vue({
el: '#app',
data: {
count: 0
},
methods: {
increment: function() {
this.count += 1
}
}
})
これをコールバック関数を使うと、コールバック関数内のthisはうまく機能しないため、以下のように、あらかじめthisを別の変数に代入しておく
<div id="app">
<p>{{ count }}</p>
<button v-on:click="increment">カウントアップ</button>
</div>
new Vue({
el: '#app',
data: {
count: 0
},
methods: {
increment: function() {
var me = this
setTimeout(function() {
me.count += 1
})
}
}
})
またはbindを使う
<div id="app">
<p>{{ count }}</p>
<button v-on:click="increment">カウントアップ</button>
</div>
new Vue({
el: '#app',
data: {
count: 0
},
methods: {
increment: function() {
setTimeout(function() {
this.count += 1
}.bind(this))
}
}
})
詳しくはここを参照
bindについてはここの(43)コールバック関数、(44)setTimeoutを参照
(30)axiosでjsonデータを読み込む
<div id="app">
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/axios@0.18.0/dist/axios.min.js"></script>
new Vue({
el: '#app',
data: {
count: 0
},
mounted: function() {
axios.get('https://jsonplaceholder.typicode.com/todos')
.then(function(response) {
console.log(response)
})
}
})
(31)axiosでデータを取得、格納
HTTPクライアントであるaxiosモジュールを利用して、Vue.jsにおいてJSONデータを取得する
JSONのモックデータを提供するサービスであるJSONPlaceholderを利用する
(https://jsonplaceholder.typicode.com/todos)
<div id="app">
<p>
{{message}}
</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/axios@0.18.0/dist/axios.min.js"></script>
new Vue({
el: '#app',
data: {
message: ""
},
mounted: function() {
axios.get('https://jsonplaceholder.typicode.com/todos')
.then(function(response) {
console.log(response.data[0])
this.message = response.data[0]
}.bind(this))
}
})
(31)補足①catchでエラー捕捉
axiosで通信エラーを捕捉する場合、catchを使う
new Vue({
el: '#app',
data: {
bpi: null
},
mounted: function() {
axios.get('https://api.coindesk.com/v1/bpi/currentprice.json')
.then(function(response) {
this.bpi = response.data.bpi
}.bind(this))
.catch(function(error){
console.log(error)
})
}
})
(31)補足②bitcoin価格を取得
v-forを使ってオブジェクトを順に取得しているが、v-forは、”値”、”キー名”の順に取得となる点に注意が必要
<div id="app">
<li v-for="(rate,currency) in bpi">{{currency}}:{{rate.rate_float}}</li>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/axios@0.18.0/dist/axios.min.js"></script>
new Vue({
el: '#app',
data: {
bpi: null
},
mounted: function() {
this.appear()
},
methods: {
appear: function() {
axios.get('https://api.coindesk.com/v1/bpi/currentprice.json')
.then(function(response) {
this.bpi = response.data.bpi
console.log(response.data.bpi)
}.bind(this))
.catch(function(error) {
console.log(error)
})
}
}
2.コンポーネント
(1)dataオブジェクトは関数
コンポーネントにおいては、dataオブジェクトは関数としてreturn{}が必要
コンポーネントは、第一引数にコンポーネント名を設定し、第二引数にオブジェクトを設定するVue.component("●●",{data,methodなど})とする
また、コンポーネントでは、文字列templateとして、htmlそのものを返すことができるものを用いることができる
<div id="app">
<my-com></my-com>
<my-com></my-com>
<my-com></my-com>
</div>
<script src="js/test.js"></script>
Vue.component("my-com",{
data:function () {
return{
number:12
}
},
template:"<p>いいね{{number}}
<button v-on:click='add'>ボタン</button></p>",
methods:{
add:function(){
this.number++;
}
}
})
let app = new Vue({
el:"#app",
});
(2)グローバル、ローカル
グローバルにコンポーネントを登録すると、異なるVueのインスタンスで使用できる
<div id="app">
<my-com></my-com>
<my-com></my-com>
<my-com></my-com>
</div>
<div id="app2">
<my-com></my-com>
<my-com></my-com>
<my-com></my-com>
</div>
<script src="js/test.js"></script>
Vue.component:("comp",{
data:function () {
return{
number:12
}
},
template:"<p>いいね{{number}}
<button v-on:click='add'>ボタン</button></p>",
methods:{
add:function(){
this.number++;
}
}
});
let app = new Vue({
el:"#app",
});
let app2 = new Vue({
el:"#ap2p",
});
一方で、以下のようにローカルでコンポーネントを登録できる
<div id="app">
<my-com></my-com>
<my-com></my-com>
<my-com></my-com>
</div>
<script src="js/test.js"></script>
var component = {
data:function () {
return{
number:12
}
},
template:"<p>いいね{{number}}
<button v-on:click='add'>ボタン</button></p>",
methods:{
add:function(){
this.number++;
}
}
}
let app = new Vue({
el:"#app",
component:{
"comp":component
}
});
let app2 = new Vue({
el:"#ap2p",
});
グローバルコンポーネントは全てのVueインスタンスで使えるが、ローカルは特定のインスタンスでしか使えない
グローバルコンポーネントのケース
<div id="app">
<hello-component></hello-component>
</div>
Vue.component("hello-component", {
template:"<p>Hello</p>"
})
new Vue({
el: '#app',
})
ローカルコンポーネントのケー
<div id="app">
<hello-component></hello-component>
</div>
var helloComponent = {
template:"<p>Hello</p>"
}
new Vue({
el: '#app',
components:{
"hello-component":helloComponent
}
})
(3)コンポーネント名の注意
ハイフォンで区切ったものをケバブケース
大文字で1文字目を始めるものをパスカルケース
どちらかに統一する方がい
コンポーネントの名前は、ケバブケースとしなくてはいけない(ハイフォン)
すでに存在するhtmlの要素と今後定義されるhtml要素との衝突を防止するためが理由
(4)コンポーネントの記載例
Vue.componentは、new Vueよりも前に記載する
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Vue.js</title>
</head>
<body>
<div id="app">
<hello-world></hello-world>
</div>
<script src="https://cdn.jsdelivr.net/
npm/vue/dist/vue.js"></script>
<script>
Vue.component("hello-world",{
template:"<h1>HELLO WORLD</h1>"
})
new Vue({
el:"#app",
data:{
}
})
</script>
</body>
</html>
(5)コンポーネントの再利用
コンポーネントは再利用できる
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Vue.js</title>
</head>
<body>
<div id="app">
<hello-world></hello-world>
<hello-world></hello-world>
<hello-world></hello-world>
<hello-world></hello-world>
</div>
<script src="https://cdn.jsdelivr.net/
npm/vue/dist/vue.js"></script>
<script>
Vue.component("hello-world",{
template:"<h1>HELLO WORLD</h1>"
})
new Vue({
el:"#app",
data:{
}
})
</script>
</body>
</html>
(5)補足①コンポーネントまとめ
<div id="app">
<button-counter></button-counter>
<button-counter></button-counter>
<button-counter></button-counter>
</div>
Vue.component("button-counter", {
data: function() {
return {
count: 0
}
},
template:"<button v-on:click='count++'>{{count}}</button>"
})
new Vue({
el: '#app'
})
(6)templateに複数のタグ
template内に複数のタグがある場合はdivタグなどで1つにしなくてはいけない
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Vue.js</title>
</head>
<body>
<div id="app">
<hello-world></hello-world>
</div>
<script src="https://cdn.jsdelivr.net/
npm/vue/dist/vue.js"></script>
<script>
Vue.component("hello-world",{
template:"<div><h1>HELLO WORLD</h1><p>{{message}}</p></div>",
})
new Vue({
el:"#app",
data:{
return {
message:"Hello Vue"
}
}
})
</script>
</body>
</html>
(7)コンポーネント内でメソッド
<script>
Vue.component("hello-world",{
template:"<p>カウント{{count}}<button v-on:click='countUp'>Up</button><button v-on:click='countDown'>Down</button></p>",
data:function(){
return{
count:0
}
},
methods:{
countUp:function(){
this.count++
},
countDown:function(){
this.count--
}
}
})
new Vue({
el:"#app",
})
</script>
(8)template内の改行
componentのtemplate内で改行するにはバッククオート`を使う
(9)親から子へ(属性使用)
親であるが、Vueインスタンスが親となり、Vue.componentが子となる
親コンポーネントは、message属性として値を渡す
子コンポーネント側はpropsを配列として置いておく
<div id="app">
<hello-world message="Hello vue"></hello-world>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component("hello-world",{
template:
`<h1>
Hello World {{message}}
</h1>`,
props:["message"]
})
new Vue({
el:"#app",
})
</script>
(10)親から子へ(v-bind使用)
message属性に対して、v-bindを使ってdataプロパティから値を渡す
<div id="app">
<hello-world v-bind:message="inputT"></hello-world>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component("hello-world",{
template:
`<h1>
Hello World {{message}}
</h1>`,
props:["message"]
})
new Vue({
el:"#app",
data:{
inputT:"helloVue"
}
})
</script>
(11)子が親から受け取ったデータ更新
子コンポーネントがpropsで受け取った値をそのまま更新するのは望ましくない(可能であるが警告が出る)
いったんデータオブジェクトに退避させてから更新するようにする
<script>
Vue.component("hello-world",{
props:["num"],
template:`
<div>
値は{{current}}です
<input type="button" v-on:click="onclick">
</div>`,
methods:{
onclick:function(){
this.current++;
}
},
data:function(){
return {
current:this.num
}
}
})
new Vue({
el:"#app",
})
</script>
(12)子から親へ(イベント発火)
子コンポーネントにある、this.$emit("child")はイベントの発生を意味し、親コンポーネントにある、v-on:child="aleart"は、イベントの監視を行なっている
子コンポーネントのthis.$emitはカスタムイベントであり、カスタムイベントを関するのはv-onディレクティブとなる
<div id="app">
<hello-world v-on:child="aleart"></hello-world>
</div>
<script>
Vue.component("hello-world",{
template:'<button v-on:click="onclick">ボタン</button>',
methods:{
onclick:function(){
this.$emit("child");
}
}
})
new Vue({
el:"#app",
methods:{
aleart:function(){
alert("受け取りました")
}
}
})
</script>
(13)子から親へ(データ渡す)
まず、Vue.componentにstepのデータを親から渡している
その後、$emitを使って子から親へ引数stepともに、データをplusへ渡している
その後、addメソッドを親側で定義、実行しているが、引数があるため、引数をeで受け取り、(親の)currentで表示している
<div id="app">
<hello-world step="1" v-on:plus="add"></hello-world>
<hello-world step="2" v-on:plus="add"></hello-world>
<hello-world step="-1" v-on:plus="add"></hello-world>
{{current}}
</div>
<script src="https://cdn.jsdelivr.net/
npm/vue/dist/vue.js"></script>
<script>
Vue.component("hello-world",{
props:["step"],
template:`<button type="button" v-on:click="onclick">
{{step}}</button>`,
methods:{
onclick:function(){
this.$emit("plus",Number(this.step));
}
}
}),
new Vue({
el:"#app",
data:{
current:0
},
methods:{
add:function(e){
this.current+=e;
}
}
})
</script>
(13)補足①別例
<div id="app">
<p>{{message}}</p>
<hello-world v-on:tochild="receivemessage"></hello-world>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">
</script>
<script>
Vue.component("hello-world",{
template:`<div>
<input type="test" v-model="inputText">
<button v-on:click="onclick">送信ボタン</button>
</div>`,
data:function(){
return{
inputText:""
}
},
methods:{
onclick:function(){
this.$emit("tochild",this.inputText)
}
}
})
new Vue({
el:"#app",
data:{
message:""
},
methods:{
receivemessage:function(e){
this.message = e;
}
}
});
</script>
(14)スロット
スロットとは、コンポーネントの呼び出し元で指定したコンテンツをテンプレートに埋め込むことができる
例えば、以下の例であるが、message属性としてHello vueを子コンポーネントに渡している
<div id="app">
<hello-world message="Hello vue"></hello-world>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component("hello-world",{
template:
`<h1>
Hello World {{message}}
</h1>`,
props:["message"]
})
new Vue({
el:"#app",
})
</script>
slotを使うと、そのまま属性を埋め込むことができる
なお、pre Hello vueは、呼び出し元からデータが渡されなかった場合に表示される
<div id="app">
<hello-world>"Hello vue"</hello-world>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component("hello-world",{
template:
`<h1>
Hello World <slot>pre Hello vue</slot>
</h1>`,
props:["message"]
})
new Vue({
el:"#app",
})
</script>
(15)複数のslot
子コンポーネント側では、name属性をつけて分離する
親コンポーネント側では、タグにslot属性を追加する
<div id="app">
<hello-world>
<div slot="no1">"Hello vue"</div>
<div slot="no2">"Hello vue2"</div>
</hello-world>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/
dist/vue.js"></script>
<script>
Vue.component("hello-world",{
template:
`<h1>
Hello World <slot>pre Hello vue</slot>
<slot name="no1">pre Hello vue</slot>
<slot name="no2">pre Hello vue</slot>
</h1>`,
props:["message"]
})
new Vue({
el:"#app",
})
</script>
上記でも良いが、親側のh1の中にdivタグが見えてしまうため、templateタグを用いることが一般的
<div id="app">
<hello-world>
<template slot="no1">"Hello vue"</template>
<template slot="no2">"Hello vue2"</template>
</hello-world>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/
dist/vue.js"></script>
<script>
Vue.component("hello-world",{
template:
`<h1>
Hello World <slot>pre Hello vue</slot>
<slot name="no1">pre Hello vue</slot>
<slot name="no2">pre Hello vue</slot>
</h1>`,
props:["message"]
})
new Vue({
el:"#app",
})
</script>
さらにv-slotディレクティブを使っても良い
<div id="app">
<hello-world>
<template v-slot:no1>"Hello vue"</template>
<template v-slot=no2>"Hello vue2"</template>
</hello-world>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/
dist/vue.js"></script>
<script>
Vue.component("hello-world",{
template:
`<h1>
Hello World <slot>pre Hello vue</slot>
<slot name="no1">pre Hello vue</slot>
<slot name="no2">pre Hello vue</slot>
</h1>`,
props:["message"]
})
new Vue({
el:"#app",
})
</script>
(16)v-slot省略構文
v-slot:headerは、#でも表記できる
以下は双方同じ意味
<template v-slot:no1>"Hello vue"</template>
<template #no1>"Hello vue"</template>
3.トランジション
transitionでアニメーションしたいタグを囲むと、自動的にv-enter-active、v-enterクラスと、v-leave-active、v-leave-toが設定される
表示は、v-enter-active,v-enter、非表示はv-leave-active,v-leave-toとなる
<div id="app">
<button v-on:click="show=!show">
Change
</button>
<transition>
<p v-show="show">
Hello
</p>
</transition>
</div>
var vm = new Vue({
el: '#app',
data: {
show: false
}
})
.v-enter-active,
.v-leave-active{
transition: opacity 5s;
}
.v-enter,
.v-leave-to{
opacity: 0;
}