1. 程式人生 > >vue入門基礎

vue入門基礎

Vue (讀音 /vjuː/,類似於 view) 是一套用於構建使用者介面的漸進式框架。與其它大型框架不同的是,Vue 被設計為可以自底向上逐層應用。Vue 的核心庫只關注檢視層,不僅易於上手,還便於與第三方庫或既有專案整合。另一方面,當與現代化的工具鏈以及各種支援類庫結合使用時,Vue 也完全能夠為複雜的單頁應用提供驅動。

MVC和MVVM的區別

基本程式碼 MVVM模式

注意:

  1. vue例項不能控制 body 及 div中的那個 id='app' 不能寫到body上
  2. 通過 Vue 提供的指令,很方便的就能把資料渲染到頁面上,程式設計師不再手動操作DOM元素了【前端的Vue之類的框架,不提倡我們去手動操作DOM元素了】
  3. methods裡的方法要使用data裡面的資料,那麼就要使用this

MVVM在vue中的體現:

vue所控制的區域對應 V

vm例項對應的是 VM

data對應的是 M

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <!-- 1. 匯入Vue的包 -->
  <script src="./lib/vue-2.4.0.js"></script>
</head>

<body>
  <!-- 將來 new 的Vue例項,會控制這個 元素中的所有內容 -->
  
  <!-- Vue 例項所控制的這個元素區域,就是我們的 V  -->
  <div id="app">
    <p>{{ msg }}</p>
  </div>

  <script>
    // 2. 建立一個Vue的例項
    // 當我們匯入包之後,在瀏覽器的記憶體中,就多了一個 Vue 建構函式
    
    //  注意:我們 new 出來的這個 vm 物件,就是我們 MVVM中的 VM排程者
    var vm = new Vue({
      el: '#app',  // 表示,當前我們 new 的這個 Vue 例項,要控制頁面上的哪個區域
      
      // 這裡的 data 就是 MVVM中的 M,專門用來儲存 每個頁面的資料的
      data: { // data 屬性中,存放的是 el 中要用到的資料
        
        msg: '歡迎學習Vue' // 通過 Vue 提供的指令,很方便的就能把資料渲染到頁面上,程式設計師不再手動操作DOM元素了【前端的Vue之類的框架,不提倡我們去手動操作DOM元素了】
        
      },
      methods:{//定義方法的地方
        
      }
      
    })
  </script>
</body>

</html>

插值表示式

v-cloak

使用 v-cloak 能夠解決 插值表示式閃爍的問題

<p v-cloak>++++++++ {{ msg }} ----------</p>

v-text

使用 v-cloak 能夠解決 插值表示式閃爍的問題

注意:v-text會覆蓋元素中原本的內容,但是 插值表示式 只會替換自己的這個佔位符,不會把 整個元素的內容清空

<h4 v-text="msg">==================</h4>
結果是 msg的值 那些等號會被覆蓋掉

v-html

v-html能夠解析html標籤

注意:標籤內的內容會被覆蓋掉

<div v-html="msg2">1212112</div>
 msg2的值是 <h1>我是h1</h1>

v-bind(縮寫是:)

v-bind: 是 Vue中,提供的用於繫結屬性的指令

注意:

  1. v-bind: 指令可以被簡寫為 :要繫結的屬性
  2. v-bind 只能實現資料的單向繫結,從 M 自動繫結到 V, 無法實現資料的雙向繫結
  3. v-bind 中,可以寫合法的JS表示式
不簡寫:<input type="button" value="按鈕" v-bind:title="mytitle + '123'"> 
簡寫:<input type="button" value="按鈕" :title="mytitle + '123'">

    mytitle是data中的資料

v-on(縮寫是@)

Vue 中提供了 v-on: 事件繫結機制

<!--show是方法 可以加括號也可以不加括號-->
<input type="button" value="按鈕" v-on:click="show">

show對應的方法是 function(){ alert('hello') }

v-model

使用 v-model 指令,可以實現 表單元素和 Model 中資料的雙向資料繫結

注意: v-model 只能運用在 表單元素中

<input type="text" style="width:100%;" v-model="msg">

v-for

語法:v-for="(item,i) in list"

注意:in 後面我們放過 普通陣列,物件陣列,物件, 還可以放數字

v-for迴圈普通的陣列

item:迴圈的每一項

i:索引值

<body>
  <div id="app">
    <p v-for="(item, i) in list">索引值:{{i}} --- 每一項:{{item}}</p>
  </div>

  <script>
    // 建立 Vue 例項,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        list: [1, 2, 3, 4, 5, 6]
      },
      methods: {}
    });
  </script>
</body>

v-for迴圈物件陣列

item:迴圈的每一項

i:索引值

<body>
  <div id="app">
    <p v-for="(user, i) in list">Id:{{ user.id }} --- 名字:{{ user.name }} --- 索引:{{i}}</p>
  </div>
  
  <script>
    // 建立 Vue 例項,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        list: [
          { id: 1, name: 'zs1' },
          { id: 2, name: 'zs2' },
          { id: 3, name: 'zs3' },
          { id: 4, name: 'zs4' }
        ]
      },
      methods: {}
    });
  </script>
</body>

v-for迴圈物件

val:值

key:鍵

i:索引

<body>
  <div id="app">
    <!-- 注意:在遍歷物件身上的鍵值對的時候, 除了 有  val  key  ,在第三個位置還有 一個 索引  -->
    <p v-for="(val, key, i) in user">值是: {{ val }} --- 鍵是: {{key}} -- 索引: {{i}}</p>
  </div>

  <script>
    // 建立 Vue 例項,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        user: {
          id: 1,
          name: '託尼·屎大顆',
          gender: '男'
        }
      },
      methods: {}
    });
  </script>
</body>

v-for迭代數字

注意:如果使用 v-for 迭代數字的話,前面的 count 值從 1 開始

<body>
  <div id="app">
    <!-- in 後面我們放過  普通陣列,物件陣列,物件, 還可以放數字 -->
    <!-- 注意:如果使用 v-for 迭代數字的話,前面的 count 值從 1 開始 -->
    <p v-for="count in 10">這是第 {{ count }} 次迴圈</p>
  </div>

  <script>
    // 建立 Vue 例項,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {},
      methods: {}
    });
  </script>
</body>

v-for中的 key的使用

注意:

  1. v-for 迴圈的時候,key 屬性只能使用 number或者string
  2. key 在使用的時候,必須使用 v-bind 屬性繫結的形式,指定 key 的值
  3. 在元件中,使用v-for迴圈的時候,或者在一些特殊情況中,如果 v-for 有問題,必須 在使用 v-for 的同時,指定 唯一的 字串/數字 型別 :key 值

這是一個可以體現出這個問題的小案例執行一下我想你就會明白了

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>

<body>
  <div id="app">

    <div>
      <label>Id:
        <input type="text" v-model="id">
      </label>

      <label>Name:
        <input type="text" v-model="name">
      </label>

      <input type="button" value="新增" @click="add">
    </div>
    <p v-for="item in list" :key="item.id">
      <input type="checkbox">{{item.id}} --- {{item.name}}
    </p>
  </div>

  <script>
    // 建立 Vue 例項,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        id: '',
        name: '',
        list: [
          { id: 1, name: '李斯' },
          { id: 2, name: '嬴政' },
          { id: 3, name: '趙高' },
          { id: 4, name: '韓非' },
          { id: 5, name: '荀子' }
        ]
      },
      methods: {
        add() { // 新增方法
          this.list.unshift({ id: this.id, name: this.name })
        }
      }
    });
  </script>
</body>

</html>

v-if和v-show

比較:

v-if 特點:每次都會重新刪除或建立元素,有較高的切換效能消耗

v-show 特點: 每次不會重新進行DOM的刪除和建立操作,只是切換了元素的 display:none 樣式,有較高的初始渲染消耗

使用:

v-if 有較高的切換效能消耗:如果元素涉及到頻繁的切換,最好不要使用 v-if, 而是推薦使用 v-show,因為每次切換都會刪除或建立元素

v-show 有較高的初始渲染消耗:如果元素可能永遠也不會被顯示出來被使用者看到,則推薦使用 v-if

比如:
<body>
  <div id="app">

    <!-- <input type="button" value="toggle" @click="toggle"> -->
    <input type="button" value="toggle" @click="flag=!flag">

    <!-- v-if 的特點:每次都會重新刪除或建立元素 -->
    <!-- v-show 的特點: 每次不會重新進行DOM的刪除和建立操作,只是切換了元素的 display:none 樣式 -->

    <!-- v-if 有較高的切換效能消耗 -->
    <!-- v-show 有較高的初始渲染消耗 -->

    <!-- 如果元素涉及到頻繁的切換,最好不要使用 v-if, 而是推薦使用 v-show -->
    <!-- 如果元素可能永遠也不會被顯示出來被使用者看到,則推薦使用 v-if -->
    <h3 v-if="flag">這是用v-if控制的元素</h3>
    <h3 v-show="flag">這是用v-show控制的元素</h3>

  </div>

  <script>
    // 建立 Vue 例項,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        flag: false
      },
      methods: {
        /* toggle() {
          this.flag = !this.flag
        } */
      }
    });
  </script>
</body>

事件修飾符

.stop和.self的區別: .stop會阻止冒泡行為,除了被點選元素以為,別的元素的點選事件都不會被觸發 而.self只是當前元素自己不點選不會觸發,而其他的元素依然會被觸發點選事件

.stop

使用 .stop 阻止冒泡,點選只會觸發 input的點選事件而div的點選事件不會觸發

<div class="inner" @click="div1Handler">
    <input type="button" value="戳他" @click.stop="btnHandler">
</div>

.prevent

使用 .prevent 阻止預設行為,可以阻止a標籤的預設跳轉

<a href="http://www.baidu.com" @click.prevent="linkClick">有問題,先去百度</a>

.native

使用 .native 監聽元件的點選事件如果不寫,不能確定點選的是元件中的那個元素,加了就相當於元件的根元素,Icon是iview的字型圖示元件

<Icon type="ios-eye-outline" style="color:#fff;" @click.native="handleView(item)"></Icon>

capture

使用 .capture 實現捕獲觸發事件的機制,會先執行div的點選事件,在執行input的點選事件

<div class="inner" @click.capture="div1Handler">
    <input type="button" value="戳他" @click="btnHandler">
</div>

.self

使用 .self 實現只有點選當前元素時候,才會觸發事件處理函式

<div class="inner" @click.self="div1Handler">
   <input type="button" value="戳他" @click="btnHandler">
</div>

.once

使用 .once 只觸發一次事件處理函式

第一個:只會執行一次點選事件

第二個:只會執行一次點選事件和一次預設事件阻止事件,再點就會跳轉百度

<a href="javascript:void(0)" v-on:click.once="href">百度</a>
<a href="http://www.baidu.com" v-on:click.prevent.once="href">百度</a>

vue中繫結樣式兩種方式

v-bind:class

直接傳遞一個數組,注意: 這裡的 class 需要使用 v-bind 做資料繫結

<h1 :class="['thin', 'italic']">這是一個很大很大的H1,大到你無法想象!!!</h1>

在陣列中使用三元表示式

<h1 :class="['thin', 'italic', flag?'active':'']">這是一個很大很大的H1,大到你無法想象!!!</h1>

在陣列中使用 物件來代替三元表示式,提高程式碼的可讀性

<h1 :class="['thin', 'italic', {'active':flag} ]">這是一個很大很大的H1,大到你無法想象!!!</h1>

在為 class 使用 v-bind 繫結 物件的時候,物件的屬性是類名,由於 物件的屬性可帶引號,也可不帶引號,所以 這裡我沒寫引號; 屬性的值 是一個識別符號

<h1 :class="{ red: true, thin: true, italic: flag, active: false }">這是一個很大很大的H1,大到你無法想象!!!</h1>

也可以把這些物件抽離出來儲存到一個變數內

<div id='app'>
  <h1 :class="classObj">這是一個很大很大的H1,大到你無法想象!!!</h1>
</div>

<script>
    // 建立 Vue 例項,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        flag: true,
        classObj: { red: true, thin: true, italic: flag, active: false }
      },
      methods: {}
    });
  </script>

v-bind:style

物件就是無序鍵值對的集合

使用物件的方式,注意帶橫線的 比如 font-weight 要使用引號括起來

<h1 :style="{ color: 'red', 'font-weight': 200 }">這是一個h1</h1>
將物件抽離出來儲存到變數中
<h1 :style="styleObj1">這是一個h1</h1>

使用陣列的方式

<h1 :style="[ styleObj1, styleObj2 ]">這是一個h1</h1>

將物件處理出來

<script>
    // 建立 Vue 例項,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        styleObj1: { color: 'red', 'font-weight': 200 },
        styleObj2: { 'font-style': 'italic' }
      },
      methods: {}
    });
  </script>

自定義過濾器

注意:可以傳遞多個引數,但是函式內的第一個引數是管道符前面的那個值,呼叫的時候,管道符前面的值不用自己傳遞,所以在方法內只需要協商自己想要傳遞的引數就可以了

{{ ctime | dateFormat('過濾的條件') }}

定義全域性過濾器

語法:定義全域性過濾器,所有的VM例項都可以共享

//引數1 是要被過濾的值 及 管道符前面的那個值
//引數2 是過濾的條件
Vue.filter('過濾器的名字',function('引數1','引數2'){
  return '想要返回的結果';
})

例子:過濾時間的過濾器

// 全域性的過濾器, 進行時間的格式化
    // 所謂的全域性過濾器,就是所有的VM例項都共享的
    Vue.filter('dateFormat', function (dateStr, pattern = "") {
      // 根據給定的時間字串,得到特定的時間
      var dt = new Date(dateStr)

      //   yyyy-mm-dd
      var y = dt.getFullYear()
      var m = dt.getMonth() + 1
      var d = dt.getDate()

      if (pattern.toLowerCase() === 'yyyy-mm-dd') {
        //`${y}-${m}-${d}` Es6表示字串的新語法 ${} 大括號內表示要插入變數
        return `${y}-${m}-${d}`
      } else {
        var hh = dt.getHours()
        var mm = dt.getMinutes()
        var ss = dt.getSeconds()

        return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
      }
    })

定義私有過濾器

定義私有過濾器 過濾器有兩個 條件 【過濾器名稱 和 處理函式】

處理函式內部所做的事情跟全域性過濾器所做的事情一樣

規則:過濾器呼叫的時候,採用的是就近原則,如果私有過濾器和全域性過濾器名稱一致了,這時候 優先呼叫私有過濾器


var vm2 = new Vue({
      el: '#app2',
      data: {
        dt: new Date()
      },
      methods: {},
      filters: {
        //dateFormat 過濾器的名字  
        dateFormat: function (dateStr, pattern = '') {
          // 根據給定的時間字串,得到特定的時間
          var dt = new Date(dateStr)
          //   yyyy-mm-dd
          var y = dt.getFullYear()
          var m = (dt.getMonth() + 1).toString().padStart(2, '0')
          var d = dt.getDate().toString().padStart(2, '0')

          if (pattern.toLowerCase() === 'yyyy-mm-dd') {
            return `${y}-${m}-${d}`
          } else {
            var hh = dt.getHours().toString().padStart(2, '0')
            var mm = dt.getMinutes().toString().padStart(2, '0')
            var ss = dt.getSeconds().toString().padStart(2, '0')

            return `${y}-${m}-${d} ${hh}:${mm}:${ss} ~~~~~~~`
          }
        }
      }
})

自定義全域性按鍵修飾符

f2是被繫結的鍵 113是鍵的值

使用方法,與上面的事件修飾符一樣

Vue.config.keyCodes.f2 = 113

自定義指令

注意: Vue中所有的指令,在呼叫的時候,都以 v- 開頭

自定義全域性指令

以繫結一個自動獲取焦點為例

Vue.directive('focus', {
      bind: function (el) { // 每當指令繫結到元素上的時候,會立即執行這個 bind 函式,只執行一次
        // 注意: 在每個 函式中,第一個引數,永遠是 el ,表示 被綁定了指令的那個元素,這個 el 引數,是一個原生的JS物件
        // 在元素 剛綁定了指令的時候,還沒有 插入到 DOM中去,這時候,呼叫 focus 方法沒有作用
        //  因為,一個元素,只有插入DOM之後,才能獲取焦點

      },
      inserted: function (el) {  // inserted 表示元素 插入到DOM中的時候,會執行 inserted 函式【觸發1次】
        // 和JS行為有關的操作,最好在 inserted 中去執行,放置bind JS行為不生效
        el.focus();
      },
      updated: function (el) {  // 當VNode更新的時候,會執行 updated, 可能會觸發多次
      }
    })

引數詳解:自定指令鉤子函式及內部引數

Vue.directive('color', {
      // 樣式,只要通過指令繫結給了元素,不管這個元素有沒有被插入到頁面中去,這個元素肯定有了一個內聯的樣式
      // 將來元素肯定會顯示到頁面中,這時候,瀏覽器的渲染引擎必然會解析樣式,應用給這個元素
      // 和樣式相關的操作,一般都可以在 bind 執行
      bind: function (el, binding) {
       console.log(binding.name); //自定義指令名字
       console.log(binding.expression); //自定義指令屬性的值,引號裡面是什麼內容得到的就是什麼內容 比如說v-color="'skyblue'" 那麼得到的是'skyblue'
       console.log(binding.value); //自定義指令的值,比如說 v-color="'skyblue'" 那麼得到的是 skyblue
        el.style.color = binding.value
      }
    })

自定義私有指令

fontsize 是簡寫的自定義指令

var vm2 = new Vue({
      el: '#app2',
      data: {
        dt: new Date()
      },
      methods: {},
      directives: { // 自定義私有指令
        'fontweight': { // 設定字型粗細的
          bind: function (el, binding) {
            el.style.fontWeight = binding.value
          }
        },
        'fontsize': function (el, binding) { // 注意:這個 function 等同於 把 程式碼寫到了 bind 和 update 中去
          el.style.fontSize = parseInt(binding.value) + 'px'
        }
      }
    })

生命週期函式--鉤子函式

程式碼演示:

var vm = new Vue({
      el: '#app',
      data: {
        msg: 'ok'
      },
      methods: {
        show() {
          console.log('執行了show方法')
        }
      },
      beforeCreate() { // 這是我們遇到的第一個生命週期函式,表示例項完全被創建出來之前,會執行它
        // 注意: 在 beforeCreate 生命週期函式執行的時候,data 和 methods 中的 資料都還沒有沒初始化
      },
      created() { // 這是遇到的第二個生命週期函式
        //  在 created 中,data 和 methods 都已經被初始化好了!
        // 如果要呼叫 methods 中的方法,或者操作 data 中的資料,最早,只能在 created 中操作
      },
      beforeMount() { // 這是遇到的第3個生命週期函式,表示 模板已經在記憶體中編輯完成了,但是尚未把 模板渲染到 頁面中
        // 在 beforeMount 執行的時候,頁面中的元素,還沒有被真正替換過來,只是之前寫的一些模板字串
      },
      mounted() { // 這是遇到的第4個生命週期函式,表示,記憶體中的模板,已經真實的掛載到了頁面中,使用者已經可以看到渲染好的頁面了
        // 注意: mounted 是 例項建立期間的最後一個生命週期函式,當執行完 mounted 就表示,例項已經被完全建立好了,此時,如果沒有其它操作的話,這個例項,就靜靜的 躺在我們的記憶體中,一動不動
      },


      // 接下來的3是執行中的兩個事件
      beforeUpdate() { // 這時候,表示 我們的介面還沒有被更新【資料被更新了嗎?  資料肯定被更新了】
        // 得出結論: 當執行 beforeUpdate 的時候,頁面中的顯示的資料,還是舊的,此時 data 資料是最新的,頁面尚未和 最新的資料保持同步
      },
      updated() {
        // updated 事件執行的時候,頁面和 data 資料已經保持同步了,都是最新的
      }
    });

vue-resource資料請求

讀完下面的程式碼就會用啦

Vue.http.options.root = ‘http://vue.studyit.io/‘; 配置共有的請求部分

注意: 通過 result.body 拿到伺服器返回的成功的資料

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="./lib/vue-2.4.0.js"></script>
  <!-- 注意:vue-resource 依賴於 Vue,所以先後順序要注意  -->
  <!-- this.$http.jsonp -->
  <script src="./lib/vue-resource-1.3.4.js"></script>
</head>

<body>
  <div id="app">
    <input type="button" value="get請求" @click="getInfo">
    <input type="button" value="post請求" @click="postInfo">
    <input type="button" value="jsonp請求" @click="jsonpInfo">
  </div>

  <script>
    // 建立 Vue 例項,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {},
      methods: {
        getInfo() { // 發起get請求 只有一個引數  傳遞引數的話 使用/引數 進行拼接 因為後臺有佔位符
          //'http://vue.studyit.io/api/getlunbo/引數'
          //  當發起get請求之後, 通過 .then 來設定成功的回撥函式
          this.$http.get('http://vue.studyit.io/api/getlunbo').then(function (result) {
            // 通過 result.body 拿到伺服器返回的成功的資料
          })
        },
        postInfo() { // 發起 post 請求   application/x-wwww-form-urlencoded
          //  手動發起的 Post 請求,預設沒有表單格式,所以,有的伺服器處理不了
          //  通過 post 方法的第三個引數, { emulateJSON: true } 設定 提交的內容型別 為 普通表單資料格式
          this.$http.post('http://vue.studyit.io/api/post', {}, { emulateJSON: true }).then(result => {
            console.log(result.body)
          })
        },
        jsonpInfo() { // 發起JSONP 請求 只有一個引數
          this.$http.jsonp('http://vue.studyit.io/api/jsonp').then(result => {
            console.log(result.body)
          })
        }
      }
    });
  </script>
</body>

</html>

動畫

顯示隱藏 新增刪除 都會觸發動畫

使用過渡類名實現動畫

在進入/離開的過渡中,會有 6 個 class 切換。

  1. v-enter:定義進入過渡的開始狀態。在元素被插入時生效,在下一個幀移除。
  2. v-enter-active:定義過渡的狀態。在元素整個過渡過程中作用,在元素被插入時生效,在 transition/animation 完成之後移除。這個類可以被用來定義過渡的過程時間,延遲和曲線函式。
  3. v-enter-to: 2.1.8版及以上 定義進入過渡的結束狀態。在元素被插入一幀後生效 (於此同時 v-enter 被刪除),在 transition/animation 完成之後移除。
  4. v-leave: 定義離開過渡的開始狀態。在離開過渡被觸發時生效,在下一個幀移除。
  5. v-leave-active:定義過渡的狀態。在元素整個過渡過程中作用,在離開過渡被觸發後立即生效,在 transition/animation 完成之後移除。這個類可以被用來定義過渡的過程時間,延遲和曲線函式。
  6. v-leave-to: 2.1.8版及以上 定義離開過渡的結束狀態。在離開過渡被觸發一幀後生效 (於此同時 v-leave 被刪除),在 transition/animation 完成之後移除。
具體使用方法看如下程式碼
  1. 可以使用 name='my' 修改 .v-enter .v-leave-to 等樣式的 v-字首
<transition name='my'>
這是一個H3

</transition>
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="./lib/vue-2.4.0.js"></script>
  <!-- 2. 自定義兩組樣式,來控制 transition 內部的元素實現動畫 -->
  <style>
    /* v-enter 【這是一個時間點】 是進入之前,元素的起始狀態,此時還沒有開始進入 */
    /* v-leave-to 【這是一個時間點】 是動畫離開之後,離開的終止狀態,此時,元素 動畫已經結束了 */
    .v-enter,
    .v-leave-to {
      opacity: 0;
      transform: translateX(150px);
    }

    /* v-enter-active 【入場動畫的時間段】 */
    /* v-leave-active 【離場動畫的時間段】 */
    .v-enter-active,
    .v-leave-active{
      transition: all 0.8s ease;
    }
  </style>
</head>

<body>
  <div id="app">
    <input type="button" value="toggle" @click="flag=!flag">
    
    <!-- 需求: 點選按鈕,讓 h3 顯示,再點選,讓 h3 隱藏 -->
    <!-- 1. 使用 transition 元素,把 需要被動畫控制的元素,包裹起來 -->
    <!-- transition 元素,是 Vue 官方提供的 -->
    <transition>
      <h3 v-if="flag">這是一個H3</h3>
    </transition>
    
  </div>

  <script>
    // 建立 Vue 例項,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        flag: false
      },
      methods: {}
    });
  </script>
</body>

</html>

使用第三方類實現動畫

注意:要引入 animate.css

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="./lib/vue-2.4.0.js"></script>
  <link rel="stylesheet" href="./lib/animate.css">
  <!-- 入場 bounceIn    離場 bounceOut -->
</head>

<body>
  <div id="app">
    <input type="button" value="toggle" @click="flag=!flag">
    <!-- 需求: 點選按鈕,讓 h3 顯示,再點選,讓 h3 隱藏 -->
    
    <!-- 基本使用 -->
    <!--<transition enter-active-class="animated bounceIn" leave-active-class="animated bounceOut">
      <h3 v-if="flag">這是一個H3</h3>
    </transition>-->

    <!-- 進化: 使用 :duration="毫秒值" 來統一設定 入場 和 離場 時候的動畫時長 -->
    <!-- 注意需要有 animate 可以跟動畫寫在一起,也可以跟要進行動畫的元素寫在一起 使用class="animated" -->
    <!-- <transition enter-active-class="bounceIn" leave-active-class="bounceOut" :duration="200">
      <h3 v-if="flag" class="animated">這是一個H3</h3>
    </transition> -->

    <!-- 在進化: 使用  :duration="{ enter: 200, leave: 400 }"  來分別設定 入場的時長 和 離場的時長  -->
   <transition 
    enter-active-class="bounceIn" 
    leave-active-class="bounceOut" 
    :duration="{ enter: 200, leave: 400 }">
      <h3 v-if="flag" cl