Vue.js是以資料狀態操作畫面,偏向MVVM軟體設計模式。
MVVM(Model View Viewmodel)
英文 |
Model |
View |
Viewmodel |
中文 |
模型 |
視圖 |
資料聯繫器 |
MVC(Model View Controller)
英文 |
Model |
View |
Controller |
Database |
中文 |
模型 |
視圖 |
控制器 |
資料庫 |
- [視圖]→發送請求→[控制器]→[模型]→[資料庫]→回傳資料→[模型]→[控制器]→渲染→[視圖]
生命週期
英文 |
中文 |
說明 |
|
開始創建 |
|
beforeCreate |
準備載入資料 |
|
|
數據觀測建立 |
|
created |
載入資料 |
要載入ajax要在這階段之後 |
|
編譯模板 |
|
beforeMount |
準備繪製元件 |
|
|
模板建立完成 |
|
mounted |
繪製元件 |
要操作DOM元素要在這階段之後 |
|
資料變動 |
|
updated |
更新資料時觸發 |
|
activated |
|
有<keep-alive>時才會觸發 |
deactivated |
|
有<keep-alive>時才會觸發 |
beforeDestroy |
準備移除資料 |
|
|
移除觀測、子元件、監聽事件 |
|
destroyed |
移除資料 |
|
開始使用Vue.js
- 使用 element (簡化:el)綁定HTML上的DOM元素。
1
2
3
|
const app = new Vue({
el: "#app"
});
|
v-text
- 使用
v-text
可將資料裡的"文字"帶入<標籤>。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
<!--第一種寫法-->
<div id="app">
<p>{{apple}}</p>
<p>{{banana[0]}}</p>
<p>{{banana[1]}}</p>
<p>{{banana[2]}}</p>
<p>{{pineapple.kaohsiung}}</p>
<p>{{pineapple.pingtung}}</p>
</div>
<!--第二種寫法-->
<div id="app">
<p v-text="apple"></p>
<p v-text="banana[0]"></p>
<p v-text="banana[1]"></p>
<p v-text="banana[2]"></p>
<p v-text="pineapple.kaohsiung"></p>
<p v-text="pineapple.pingtung"></p>
</div>
|
1
2
3
4
5
6
7
8
9
10
11
|
const app = new Vue({
el: "#app",
data:{
apple: "蘋果",
banana: ["粉蕉","蜜蕉","芭蕉"],
pineapple:{
kaohsiung: "釋迦鳳梨",
pingtung: "金鑽鳳梨"
}
}
});
|
輸出結果:
1
2
3
4
5
6
7
8
|
<div id="app">
<p>蘋果</p>
<p>粉蕉</p>
<p>蜜蕉</p>
<p>芭蕉</p>
<p>釋迦鳳梨</p>
<p>金鑽鳳梨</p>
</div>
|
v-text + substring()截取過長自串
1
2
3
|
<div id="app">
<p>{{success.substring(3,7)}}</p>
</div>
|
1
2
3
4
5
6
|
const app = new Vue({
el: "#app",
data:{
success: "Hello World!!",
}
});
|
輸出結果:
1
2
3
|
<div id="app">
<p>lo W</p>
</div>
|
substring(從第幾個開始擷取自串,截取到從前面數過來第幾個)
v-text + parseInt()正整數 + 價錢處理
1
2
3
|
<div id="app">
<p>優惠價:<span>{{discount*100}}折</span>parseInt(price*discount)元</p>
</div>
|
1
2
3
4
5
6
7
|
const app = new Vue({
el: "#app",
data:{
price: 360,
discount: 0.79,
}
});
|
輸出結果:
1
2
3
|
<div id="app">
<p>優惠價:<span>79折</span>284元</p>
</div>
|
substring(從第幾個開始擷取自串,截取到從前面數過來第幾個)
v-html
- 使用
v-html
可將資料裡的HTML帶入<標籤>。
不建議在網頁上任意使用v-html,因為會容易遭受XSS攻擊,例如:輸入框
1
2
3
4
5
6
7
8
9
|
<!--第一種寫法-->
<div id="app">
{{{box}}}
</div>
<!--第二種寫法-->
<div id="app" v-html="box">
</div>
|
1
2
3
4
5
6
|
const app = new Vue({
el: "#app",
data:{
box:"<div class='box'>箱子</div>"
}
});
|
輸出結果:
1
2
3
|
<div id="app">
<div class='box'>箱子</div>
</div>
|
v-for
1
2
3
4
5
6
7
8
9
10
|
<div id="app">
<ul>
<li v-for="(id,item) in shoplist"> <!--(第一個是序列,第二個是資料)-->
<p>{{id+1}}</p>
<p>名稱:{{item.name}}</p>
<p>價錢:{{item.price}}</p>
<p>生產國家:<span v-for="item in item.produce">{{item}}/</p>
</li>
</ul>
</div>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
const app = new Vue({
el: "#app",
data:{
shoplist: [
{
name: "蘋果",
price: 1000,
produce: ["美國","日本"]
},
{
name: "香蕉",
price: 500,
produce: ["台灣","韓國","菲律賓"]
},
{
name: "鳳梨",
price: 300,
produce: ["泰國","越南"]
}
]
}
});
|
輸出結果:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
<div id="app">
<ul>
<li>
<p>1</p>
<p>名稱:蘋果</p>
<p>價錢:1000</p>
<p>生產國家:<span>美國/日本/</p>
</li>
<li>
<p>2</p>
<p>名稱:香蕉</p>
<p>價錢:500</p>
<p>生產國家:<span>台灣/韓國/菲律賓/</p>
</li>
<li>
<p>3</p>
<p>名稱:鳳梨</p>
<p>價錢:300</p>
<p>生產國家:<span>泰國/越南/</p>
</li>
</ul>
</div>
|
v-for標籤內再使用v-for就會找更內層的資料(item)
v-model 文字綁定
- 使用
v-model
可以產生雙向綁定,在修改值時會同時改變。
1
2
3
4
|
<div id="app">
<input type="text" v-model="apple">
<p>{{apple}}</p>
</div>
|
1
2
3
4
5
6
|
const app = new Vue({
el: "#app",
data:{
apple: "蘋果"
}
});
|
輸出結果:
1
2
3
4
|
<div id="app">
<input type="text" v-model="apple">
<p>蘋果</p>
</div>
|
在<input>裡輸入文字,<p>就會改變內容
v-model 樣式綁定
- 使用
v-model
可以產生雙向綁定,在修改值時會同時改變。
1
2
3
4
|
<div id="app">
<input type="text" v-model="color">
<p style="background-color:{{color}}">控制我的背景顏色</p>
</div>
|
1
2
3
4
5
6
|
const app = new Vue({
el: "#app",
data:{
color: "blue"
}
});
|
輸出結果:
1
2
3
4
|
<div id="app">
<input type="text" v-model="color">
<p style="background-color:blue">控制我的背景顏色</p>
</div>
|
在<input>裡輸入顏色名稱,<p>就會變換背景顏色
v-model + radio按鈕 + 切換style樣式
1
2
3
4
5
6
7
|
<div id="app">
<label>紅色</label>
<input type="radio" v-model="color" value="red">
<label>藍色</label>
<input type="radio" v-model="color" value="blue">
<p style="background-color:{{color}}">控制我的背景顏色</p>
</div>
|
1
2
3
4
5
6
|
const app = new Vue({
el: "#app",
data:{
color: "blue"
}
});
|
利用radio去切換data裡的值,再將這個值直接套用在style上
v-model+v-for 綁定清單
- 使用
v-model
可以產生雙向綁定,在修改值時會同時改變。
1
2
3
4
5
6
7
8
|
<div id="app">
<div v-for="item in name">
<input type="text" v-model="item">
</div>
<ul>
<li v-for="item in name">{{item}}</li>
</ul>
</div>
|
1
2
3
4
5
6
|
const app = new Vue({
el: "#app",
data:{
name:["蘋果","香蕉","鳳梨"]
}
});
|
輸出結果:
1
2
3
4
5
6
7
8
9
10
11
12
|
<div id="app">
<div v-for="item in name">
<input type="text">
<input type="text">
<input type="text">
</div>
<ul>
<li>蘋果</li>
<li>香蕉</li>
<li>鳳梨</li>
</ul>
</div>
|
每個<input>都對應著一個<li>,變更內容時都會同步修改
v-for + audio + data-num + jQuery
1
2
3
4
5
6
7
|
<div id="app">
<div v-for="(item,id) in piano">
<audio controls v-bind:data-num="id">
<source v-bind:src="'audio/'+ item +'.wav'" type="audio/wav">
</audio>
</div>
</div>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
const app = new Vue({
el: "#app",
data: {
piano: [1,1.5,2,2.5,3,3.5,4,4.5,5,5.5,6,6.5,7,8,8.5,9,9.5,10,11,11.5,12,12.5,13,13.5,14,15],
},
methods:{
play: function(id,vol){
$("audio[data-num="+id+"]")[0].volume = vol;
$("audio[data-num="+id+"]")[0].currentTime = 0;
$("audio[data-num="+id+"]")[0].play();
}
}
});
$(document).ready(function(){
$("audio[data-num=3]")[0].play();
});
|
利用data-num標示每個audio,用jQuery抓取出的對象是“陣列”,所以還要再加上[0]
.currentTime()是JS控制音檔的播放起始點
.volumn()是JS控制音檔音量的大小,範圍從0.0(靜音)到1.0(最大音量)
v-if
名稱 |
v-if |
v-show |
效果 |
DOM元素消失 |
display:none |
1
2
3
4
|
<div id="app">
<input type="checkbox" v-model="isShow">
<p v-if="isShow">這段字要出現還是不出現?</p>
</div>
|
1
2
3
4
5
6
|
const app = new Vue({
el: "#app",
data:{
isShow: true
}
});
|
判斷isShow是否為true,如果是true:<p>就存在,如果是false:<p>就不存在
v-if + v-for 判斷是否有折扣,無折購則顯示原價
1
2
3
4
5
6
7
8
9
|
<div id="app">
<ul>
<li v-for="item in shoplist">
<span>名稱:{{item.name}}</span>
<span v-if="item.is_discount">原價:${{item.price}}</span>
<span v-if="!item.is_discount">優惠價:${{item.price*item.discount}}</span>
</li>
</ul>
</div>
|
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
|
const app = new Vue({
el: "#app",
data:{
shoplist: [
{
name: "蘋果",
price: 1000,
discount: 0.85,
is_discount: true
},
{
name: "香蕉",
price: 500,
discount: 0.79,
is_discount: false
},
{
name: "鳳梨",
price: 300,
discount: 0.5,
is_discount: false
}
]
}
});
|
is_discount用來表示有無折扣,v-if會把值是true的顯示,但加上!也會顯示false的值
v-if + {{三元判斷式}} + 判斷是否使用class
名稱 |
v-if |
v-show |
效果 |
DOM元素消失 |
display:none |
1
2
3
4
5
|
<div id="app">
<!--可用checkbox勾選去做判斷-->
<input type="checkbox" v-model="isActive">
<p class="{{isActive?'active':''}}">加上active我的字會變紅色</p>
</div>
|
1
2
3
4
5
6
|
const app = new Vue({
el: "#app",
data:{
isActive: false
}
});
|
判斷isActive是否為true,如果是true:class就出現active存在,如果是false:class就為空
v-on
- 使用
v-on
可增加使用者事件,例如滑鼠點擊、按下鍵盤等。
1
2
3
4
5
|
<div id="app">
<button v-on:click="add">按鈕</button>
<!--簡化寫法@click="add"-->
<p>{{price}}</p>
</div>
|
1
2
3
4
5
6
7
8
9
10
11
|
const app = new Vue({
el:"#app",
data:{
price: 25
},
methods:{
add:function(){
this.price = this.price + 5;
}
}
});
|
一開始顯示25,每次點擊"按鈕"時,25都+5
v-on:click + splice()刪除資料方法
1
2
3
4
5
6
7
|
<div id="app">
<ul>
<li v-for="(id,item) in fruits">{{item}}
<button v-on:click="remove(id)">X</button> <!--使"remove"方法刪除第id項-->
</li>
</ul>
</div>
|
1
2
3
4
5
6
7
8
9
10
11
|
const app = new Vue({
el: "#app",
data:{
fruits:["蘋果","香蕉","鳳梨","蓮霧"]
},
methods:{
remove: function (id,item){
this.fruits.splice(id,1); //this等於data內的資料
}
}
});
|
splice(從第幾個開始刪除,刪除幾項)
v-on:click + push() + splice() + 計算總數
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<div id="app">
<button v-on:click="add('蘋果')">新增蘋果</button>
<button v-on:click="add('香蕉')">新增香蕉</button>
<button v-on:click="add('鳳梨')">新增鳳梨</button>
<button v-on:click="add('蓮霧')">新增蓮霧</button>
<ul>
<li v-for="item in fruits" track-by='$index'>{{item}}
<button v-on:click="remove(id)">X</button>
</li>
</ul>
<p>目前總共:</p>
<p>{{total.蘋果}}個蘋果</p>
<p>{{total.香蕉}}個香蕉</p>
<p>{{total.鳳梨}}個鳳梨</p>
<p>{{total.蓮霧}}個蓮霧</p>
</div>
|
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
|
const app = new Vue({
el: "#app",
data:{
fruits: ["蘋果","香蕉","鳳梨","蓮霧"],
},
methods:{
add: function(item){
this.fruits.push(item);
},
remove: function(id){
this.fruits.splice(id,1);
}
},
computed:{
total: function(){
let total = {
蘋果: 0,
香蕉: 0,
鳳梨: 0,
蓮霧: 0,
}
for(let i=0 ; i<this.fruits.length ; i++){
total[this.fruits[i]]+=1;
}
return total;
}
}
});
|
computed會自動計算數量後直接顯示,不用特別去觸發他
v-on:click + push()資料新增方法
1
2
3
4
5
6
7
8
9
|
<div id="app">
<button v-on:click="add('蘋果')">新增蘋果</button>
<button v-on:click="add('香蕉')">新增香蕉</button>
<button v-on:click="add('鳳梨')">新增鳳梨</button>
<button v-on:click="add('蓮霧')">新增蓮霧</button>
<ul>
<li v-for="item in fruits" track-by='$index'>{{item}}</li>
</ul>
</div>
|
1
2
3
4
5
6
7
8
9
10
11
|
const app = new Vue({
el: "#app",
data:{
fruits: ["蘋果","香蕉","鳳梨","蓮霧"],
},
methods:{
add: function(item){
this.fruits.push(item);
}
}
});
|
記得vue1使用v-for時要在後面加上track-by='$index'作為資料中唯一的標識符
v-bind
1
2
3
|
<div id="app">
<img v-bind:src="a" v-bind:class="b">
</div>
|
1
2
3
4
5
6
7
|
const app = new Vue({
el:"#app",
data:{
a: "images/picture.png",
b: "img-fluid"
}
});
|
輸出結果:
1
2
3
|
<div id="app">
<img src="images/picture.png" class="img-fluid">
</div>
|
v-bind + ajax + background-image
1
2
3
4
5
6
7
|
<div id="app">
<ul>
<li v-for="item in imgUrl">
<div class="img-fluid" v-bind:style="'background-image:url'+{{item.url}}+')'"></div>
</li>
</ul>
</div>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
const app = new Vue({
el: "#app",
data:{
imgUrl:[]
},
ready: function(){
$.ajax({
url: "...",
success: function(item){
app.imgUrl = JSON.parse(item);
}
})
}
});
|
v-class動態切換效果
- 使用
:class
可綁定<標籤>,判斷是否套用css
樣式。
1
2
3
4
|
<div id="app">
<button @click="a=!a" :class="{'red':a}">按鈕</button>
<!--:class="{'css樣式名稱':判斷式}"-->
</div>
|
1
2
3
|
.red{
background-color: red;
}
|
1
2
3
4
5
6
|
const app = new Vue({
el:"#app",
data:{
a: false
}
});
|
當點擊的時候"按鈕"時會變紅色
vue + ajax 載入api資料(一串純文字)
1
2
3
|
<div id="app">
<p>{{text}}</p>
</div>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
const app = new Vue({
el: "#app",
data:{
text: "這是預載入之前的文字"
},
ready: function(){
$.ajax({
url: "https://awiclass.monoame.com/api/command.php?type=get&name=notifydata",
success: function(item){
app.text = item;
}
})
}
});
|
輸出結果:
1
2
3
|
<div id="app">
<p>哈囉!! 這邊是你用AJAX載入的純文字公告!!</p>
</div>
|
vue + ajax 載入api資料(JSON)
1
2
3
4
5
6
|
<div id="app">
<h5 v-if="items.length==0">資料載入中...</h5>
<ul>
<li v-for="item in items">{{item.name}}${{item.price}}</li>
</ul>
</div>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
const app = new Vue({
el: "#app",
data:{
items: []
},
ready: function(){
$.ajax({
url: "https://awiclass.monoame.com/api/command.php?type=get&name=itemdata",
success: function(item){
app.items = JSON.parse(item);
}
})
}
});
|
JSON.parse()是將JSON格式的字串解析為JavaScript物件或陣列
vue + ajax + new Date()日期格式計算
- 若要計算出「倒數剩餘天數」,利用開始時間-結束時間
1
2
3
4
5
|
<div id="app">
<div v-for="item in classDate">
<div>剩{{ remainingDays }}天</div>
</div>
</div>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
const app = new Vue({
el: '#app',
data:{
classDate: [],
},
ready: function(){
$.ajax({
url: "https://awiclass.monoame.com/api/command.php?type=get&name=hahowdata",
success: function(item){
app.classDate = JSON.parse(item);
}
})
},
computed: {
remainingDays: function(){
for (let i=0;i<this.classDate.length;i++){
return parseInt((new Date(this.classDate[i].proposalDueTime) - new Date(this.classDate[i].incubateTime)) / (1000 * 60 * 60 * 24));
}
}
}
});
|
將物件的日期格式使用new Date()即可相減做計算,將得到的值/毫秒(1000)/分鐘(60)/小時(60)/天(24),最後再用parseInt()取得正整數
其他相關