【Vue】基本模板語法

初階應用介紹

【Vue】基本模板語法

初階應用介紹


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元素。

  • #app裡不能再建立#app。

  • 若有多個.app只會綁定一個。

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

  • 使用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-ifv-show的差異 :

名稱 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

  • 使用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()取得正整數

vue 

其他相關