VUE家族系列:
- Vue快速上門(1)-基礎知識
- Vue快速上門(2)-模板語法
- Vue快速上門(3)-元件與複用
01、模板語法
1.1、template模板
<template>
是H5新增的模板元素,是一個用於HTML模板內容的包裝元素,主要使用其內部的內容。在普通的HTML頁面中,模板會出現在Dom樹中,但不會渲染,裡面的請求、指令碼也不會執行。<template>
是Vue裡主要的模板定義方式,除此以外,常用的定義Vue.template
方式:
Vue.template | 描述 | 示例 |
---|---|---|
<template> 模板 |
H5的模板元素,其內容作為模板內容, | <template id="tp"> |
<script> 模板 |
在一個 <script> 元素中定義模板內容,裡面的內容都會被當成字串。透過#id 引用 |
<script type="text/x-template" id="xtp"> |
字元模板 | 用HTML字串直接定義模板內容 | template: '<p>{{name}}</p>' |
內聯模板inline-template |
用在子元件上,用這個子元件元素裡面的內容作為模板,而不是渲染他的原本的內容。這個一般不常用吧,作用域有點亂。 | <mycom inline-template> </mycom> |
?Vue的
template
選項值:
- HTML語法:模板內容就是普通的HTML語法,Vue新增了一些繫結資料的指令。
- 根元素:內部都必須有一個根元素,
<template>
本身是沒啥用的,主要用的是其內部InnerHTML。- #值:如果值以 # 開始,則它將被用作
id
選擇符,並使用匹配元素的 innerHTML 作為模板。- 優先於el:根據上文中Vue生命週期流程可知,
template
內容會優先於el.outerHTML
內容,編譯為渲染render。
<div id="app5">
<h2>app</h2>
<template>
<p>vue中的template的innerHtml會被正常渲染</p>
</template>
<user-com inline-template>
<p>內聯模板,替代原有內容</p>
</user-com>
</div>
<script>
let app5 = new Vue({
el: "#app5",
template: '#tp', //<template id="tp">模板
template: '#xtp', //<script type="text/x-template" id="xtp">模板
template: '<p>{{mes}}--字元模板</p>', //字元模板
template: '<p>{{mes}}</p><span>❌</span>', //❌報錯:Component template should contain exactly one root element
data: { mes: "message:hello!" },
components: {
'user-com': {
data: function () { return { name: "same" } },
template: '<p>{{name}}-這是一個子元件</p>',
}
}
})
</script>
1.2、文字插值
Vue的模板語法基於HTML的語法,可以在模板中申明式的繫結例項資料、事件方法。在Vue中,模板被編譯成虛擬Dom渲染函式,先在虛擬Dom上進行操作,這樣可以最最佳化Dom及操作次數,然後再渲染到正式的Dom中。常用的一種資料繫結方式為—— 文字插值。
?文字插值:{{ data }}
,“Mustache”語法 (雙大括號) (/ˈmʌstæʃ; məˈstɑːʃ/ 鬍子),內容不支援html標籤、不支援繫結。
?注意:安全第一,不要用輸入的內容來插值,容易導致XSS攻擊。
<div id="app3">
<div>div1:{{html}}
<p>{{mes}}</p>
<p>{{birthday}}</p>
</div>
<div v-text="html">div2:</div>
<div v-html="html">div3:</div>
</div>
<script>
let vm2 = new Vue({
el: "#app3",
data: {
html: "<span style='color:red'>red span{{mes}}</span>",
mes: "hello world!",
birthday: '2000-12-11',
},
});
</script>
1.3、JavaScript表示式
在{{文字插值}}
、v-bind
繫結、v-on
事件繫結等指令中都支援完全的JavaScript的表示式,只能是單個表示式語句,不支援複雜語句、迴圈控制。
<div id="app3">
<div>
<p v-bind:style="'color:'+fcolor">{{mes.split(' ').join('---')}}</p>
<p>age:{{(new Date().getFullYear() - new Date(birthday).getFullYear())}}</p>
<p>age:{{((new Date() - new Date(birthday))/3600/24/365/1000).toFixed(1)}}</p>
</div>
</div>
<script>
let vm2 = new Vue({
el: "#app3",
data: {
mes:"hello world!",
birthday:'2000-12-11',
fcolor:'red',
},
});
</script>
02、模板指令
2.1、指令大全?
指令格式:指令:引數.修飾符 = "值"
Vue指令/ 簡寫 | 描述 | 示例 |
---|---|---|
v-text= | 繫結 textContent,同{{文字插值}}(如JS延遲,有閃爍) | <span v-text="msg"></> = <span>{{msg}}</> |
v-html= | 繫結 innerHTML,內容支援html標籤(不支援繫結),需注意安全性。其他插值指令的值都不支援HTML標籤,會被轉義。 | <div v-html="html"></div> |
v-bind: = / := | 繫結元素屬性值,動態地繫結一個或多個 attribute,或元件prop |
<img v-bind:src="img" :class="imgStyle"> |
v-model= | 表單元素的值雙向繫結,不支援表示式 | <input type="date" v-model="birthday"> |
v-show= | 值為真元素顯示(切換 display ),適用於頻繁切換顯示。 |
<div v-show="value =='方案1'">方案1</div> |
v-if= | 值為真才渲染,否則不會建立或銷燬已有元素,支援<template> |
<img v-if="growth > 0" alt="上升"> |
v-else-if= | v-if 的else if 塊,可連續使用,跟在v-if/v-else-if 後面 |
<img v-else-if="growth < 0" alt="下降"> |
v-else | v-if 或者 v-else-if 新增的“else 塊”,無引數 |
<img v-else alt="穩定"> |
v-for= | 列表渲染,item in/of expression ,支援index索引、物件 |
<li v-for="item in items">{{item}}</li> |
v-on: = / @= | 繫結事件,引數為事件名;值為方法名,或內聯語句func($event) | <button v-on:click="submit" @click=""> |
:key= | 元素唯一key 值,配合v-for 使用,避免重複key更新異常,用於虛擬Dom中判斷新舊元素。或用於強制元素替換而不復用 |
ul v-for="item in list" :key="item.id"> <i:key="text">{{text}}</i> //每次都是新元素 |
v-once | 只更新元素/元件一次,後續更新都視為靜態內容,不再更新 | <p v-text="message" v-once></p> |
v-pre | 不編譯,跳過這個元素和它的子元素的編譯過程,顯示原生的內容 | <div v-pre> </div> |
is | 動態的繫結一個元件,值為元件名稱/Vue選項物件 | <component is="user-info"></component> |
v-slot:= / #:= | 具名插槽,有名分的插槽。指定插槽名稱,或繫結插槽ViewModel | v-slot:header v-solt="{user}" |
ref | 給子元件、Dom元素註冊引用名,透過$refs 訪問這些被ref 標記的物件 |
元件上的ref 指向其元件Vue例項<div ref="left"> |
v-cloak | 解決{{文字插值} }會閃爍的問題,鎖定[v-cloak] 樣式直到編譯完後清除 |
[v-cloak]{ display: none;} <div v-cloak> |
2.2、[動態引數]
2.6.0新增的[動態引數],指令的引數可以使用[動態引數]
=一個JavaScript表示式。
<a v-on:[functype]="setStyle" v-bind:[href]="1+1">方案1</a>
- 字串值:這裡的動態引數預期結果為一個字串,異常則為
null
,null
也可用於顯示的移除繫結。 - 不要出現引號,包括
空格
、引號、<
、>
、/
、=
,HTML的屬性中是非法的。 - 引數名用小寫,不要用大寫,瀏覽器會強制轉換HTML屬性為小寫。如
<a v-on:[funcType]="fswitch">方案1</a>
包含大寫的屬性引數會找不到對應值。
<div id="app">
<img v-bind:[getProp(file.type)]="file.url" alt="file" v-on:[eventType]="eventHandler">
<img v-bind:[getprop1]="file.url" alt="file" v-on:[eventType]="eventHandler">
</div>
<script>
let vm2 = new Vue({
el: "#app",
data: {
file: { type: 'img', url: '../../res/bg.gif' },
eventType: 'click', //大寫會找不到,報錯:Property or method "eventtype" is not defined
eventtype: 'click',
},
computed:{ getprop1(){ return 'src'; } },
methods: {
getprop(type) { //如果有大寫(getProp)就會找不到報錯:Property or method "getprop" is not defined
switch (type) {
case 'img': return 'src';
case 'url': return 'href';
}
},
eventHandler(e) { console.log(e.target.tagName); }
}
});
</script>
2.3、v-for 列表渲染
用迴圈建立多個元素/元件,迴圈物件可以是陣列、物件、常量,也可以是計算屬性、方法、表示式。迴圈表示式中可以用in
,也可用of
(沒有區別)。如果迴圈建立多個元素沒有根元素,則可用一個模板<template>
來包裹,這時就不需要key了。
- 列表迴圈:
v-for="item in items"
- 列表迴圈-帶索引引數:
v-for="(item,index) in items"
- 物件迴圈-value:
v-for="value in user"
,Vue是按照Object.keys(obj)
的結果遍歷。 - 物件迴圈-帶引數:
v-for="(value,name,index) in user"
<div id="app">
<span v-for="n of 20">{{ n }} </span>
<ul>
<li><span v-for="item in items">{{item.name}} ; </span></li>
<li><span v-for="(item,index) in items">{{index+1}}:{{item.name}} ; </span></li>
<!--user物件-->
<li><span v-for="value in user">{{value}} ; </span></li>
<li><span v-for="(value,name,index) in user"><i>{{index+1}}</i>)<b>{{name}}</b>:{{value}} ; </span></li>
</ul>
<br>
</div>
<script>
let vm2 = new Vue({
el: "#app",
data: {
items: [{ name: 'sam' }, { name: 'zhangsan' }],
user: { name: 'sam', age: 20, birthday: '2000-12-11' }
},
});
</script>
?列表更新策略(:key):Vue預設列表項原地更新,不管資料的順序。
如果希望更新時保持資料、元素的順序,及更新的準確性、高效能,則需要給元素設定一個唯一身份標識 key:v-bind:key="kid" :key="kid"
,值應為字元、數字。
Vue預設是最大限度複用元素,虛擬Dom中用key
來判斷新舊元素,重複key
可能會導致更新異常,也可用於強制元素替換而不復用。一般推薦儘量提供key
,他是Vue識別節點的通用機制(diff中的元素比較)。在<transition-group>
列表動畫中,key
是必須的。
? 注意:
v-for
迴圈中的引數的順序須一致,別名不重要。v-for
優先順序高於v-if
,共用時需注意,可用來過濾不符合條件的項。
2.4、class樣式繫結
class
、style
為HTML原本的attribute
,透過v-bind
繫結,增強:
- 物件繫結,語法:
{classA:bindbool, classB:bindbool}
,繫結值bindbool
為真則樣式classA有效,方便基於判斷繫結多個class。除了直接物件表示式,還可以是繫結的物件、計算屬性返回的物件、普通表示式。 - 陣列繫結,繫結多個樣式,陣列中可以是繫結值、表示式、常量樣式名。
- 支援和原生class共存,會合並
class
值。包括元件也是如此,和元件的根元素class
合併。
?一個tab切換示例:
<style>
#app5 ul { list-style-type: none; margin: 0; padding: 0; text-align: center; }
#app5 ul li { display: inline-block; margin: 0 10px; }
#app5 ul li.active { background-color: antiquewhite; }
.psection {
display: none; background-color: antiquewhite;
text-align: center; margin: 0; line-height: 50px;
}
.psection.active { display: block; }
</style>
<div id="app5">
<ul>
<li v-for="item in items" v-on:click="liclick(item)" v-bind:class="{active:item.isActive}">{{item.title}}</li>
</ul>
<div>
<p v-for="item in items" v-bind:class="['psection',item.isActive?'active':'']">{{item.content}}</p>
<!-- 也可以用v-show實現切換 v-show="item.isActive" -->
<p v-for="item in items" v-show="item.isActive">{{item.content}}</p>
</div>
</div>
<script>
let app5 = new Vue({
el: "#app5",
data: {
items: [{ title: "顯示1", content: "1", isActive: false }
, { title: "顯示2", content: "2", isActive: true }
, { title: "顯示3", content: "3", isActive: false }],
},
methods: {
liclick: function (item) {
this.items.forEach(item => item.isActive = false);
item.isActive = true;
},
}
})
</script>
2.5、style內聯樣式繫結
對於Style的繫結,Vue直接把style物件化了,透過物件化表示式,或者直接一個物件繫結(更清晰)。
- 物件陣列:支援多個物件的陣列,合併物件中的style樣式規則。
- 支援一定的相容性字首,如
transition
,Vue會自動檢測瀏覽器並新增相容性字首。 - 物件屬性多重值,提供多個值的陣列
display:['-ms-flexbox','flex']
,Vue只會渲染陣列中最後一個被瀏覽器支援的值。
<div id="app5">
<div>
<!--陣列+物件混合-->
<p :style="[{color:activeColor,'font-size':'20px'},marginStyle]"> p1 - Content </p>
<p v-bind:style="marginStyle"> p2 - Content </p> <!--物件-->
</div>
</div>
<script>
let app5 = new Vue({
el: "#app5",
data: {
activeColor: 'red',
marginStyle: { margin: "30px", transform: "rotate(10deg)", display: ['-ms-flexbox', 'flex'] },
},
})
</script>
2.6、v-on/@事件.修飾符
事件繫結格式:v-on:/@ 事件名.修飾符 = ""
,@
為v-on:
的縮寫形式。事件名支援動態 [引數] 繫結。Vue的事件都是直接繫結到元素的,沒有用事件委託。
事件引數:方法預設支援事件引數物件Event,內聯JavaScript程式碼透過$event
訪問事件物件。
<div id="app7">
<!-- 只響應一次 + 右鍵點選 -->
<button @click.once.right="arrClick">button</button>
<li v-for="n in arr"><button v-on:click="arrClick($event,n)">{{n}}</button></li>
<!-- 左方向按鍵,數值增1 -->
<input type="text" v-on:keydown.preven.arrow-left="num=parseInt(num)+1" v-model="num">
</div>
<script>
let app7 = new Vue({
el: "#app7",
data: { arr: [1, 2, 3], num: 0 },
methods: {
arrClick: function (e, arg) { console.log(e?.target.tagName, arg ? arg : "") },
}
})
</script>
?修飾符 可以加強事件的能力,使用上可以串聯(注意順序),也可以只有修飾符。
修飾符 | 描述 |
---|---|
.stop | 呼叫 event.stopPropagation() ,停止向上冒泡(propagation /ˌprɒpəˈɡeɪʃn/ 傳播) |
.preven | 呼叫 event.preventDefault() ,取消預設事件行為,如checkbox、<a> 的預設事件行為,不影響冒泡 |
.self | 只當事件是從偵聽器繫結的元素本身觸發時才觸發回撥,只能自身觸發,內部冒泡事件的不會響應。 |
.once | 只觸發一次回撥 |
.capture | 新增事件偵聽器時使用 capture (捕獲)模式,事件流的捕獲階段就觸發事件。 |
.passive | (2.3.0) 以 { passive: true } 模式新增偵聽器,passive 設為 true 可以啟用效能最佳化,主要是針對滾動、觸控相關事件。參考MDN:使用 passive 改善滾屏效能,(passive /ˈpæsɪv/被動,消極)。 |
.native | 監聽元件根元素的原生事件 |
滑鼠鍵修飾符 | .left :只當點選滑鼠左鍵時觸發。.right :滑鼠右鍵觸發;.middle :滑鼠中鍵觸發 |
輔助鍵修飾符 | 配合滑鼠、按鍵事件使用:ctrl、shift、alt、meta(windows鍵,或command) |
鍵盤事件修飾符 | 針對事件keydown 、keyup 、keypress 按鍵修飾符:● esc、tab、space、enter、delete、up、down、left、right、a、b、c字母鍵等。 ● .{keyCode | keyAlias} : 按鍵修飾符,只當事件是從特定鍵觸發時才觸發回撥。可使用 KeyboardEvent.key值轉換為 kebab-case 來格式使用。 |
2.7、v-model表單繫結
使用v-model
在表單元素<input>
、<textarea>
及 <select>
上建立雙向繫結,會忽略他們本身的值屬性(value、checked、selected),所以注意設定預設值。分組的單選、多選元素組按照name
進行分組即可,一組的繫結也是一樣的。
基本原理就是監聽表單的輸入事件,實現檢視到資料的同步:
text
和textarea
元素使用value property
和input
事件。checkbox
和radio
使用checked property
和change
事件。name
用於分組名稱空間,value
作為選中的值。select
欄位將value
作為 prop 並將change
作為事件。
?v-model
修飾符:
.lazy
:change
事件同步資料,主要針對text
類表單元素,失去焦點時才會觸發change
事件。.number
:強制轉換值為數值型別,需配合type="number"
使用,如果無法parseFloat()
解析則返回原始值。.trim
:去掉首尾空格,比較實用!
<div id="app8">
<div>
<label>姓名:<input type="text" v-model.lazy.trim="name"></label>
<label>姓名:<input type="number" v-model.number="age">{{age}}</label>
</div>
<div>
<span>性別:</span>
<template v-for="(value,name) in dataset.sex">
<label><input type="radio" v-model.lazy="sex" name="sex" :value="name">{{value}}</label>
</template>
<i>結果:{{sex}}</i>
</div>
<div>
<span>技能:</span>
<label v-for="item in dataset.skill"><input type="checkbox" v-model="skill" :value="item"
name="skill">{{item}}</label>
<i>結果:{{skill}}</i>
</div>
<div>
<span>性別-選擇框:</span>
<select name="ssex" v-model="sex">
<option disabled value="">請選擇</option>
<option v-for="(value,name) of dataset.sex" v-once :value="name">{{value}}</option>
</select>
<i>結果:{{sex}}</i>
</div>
<div>
<span>技能-選擇框:</span>
<select name="sskill" v-model="skill" multiple>
<option disabled value="">請選擇</option>
<option v-for="item in dataset.skill" v-once :value="item">{{item}}</option>
</select>
<i>結果:{{skill.join()}}</i>
</div>
</div>
<script>
let app8 = new Vue({
el: "#app8",
data: {
name: '', age: 0, checked: false, sex: '', skill: ["開機"],
dataset: {
sex: { male: '男', female: "女", other: '其他' },
skill: ['開機', '關機', '寫Bug', '吃飯'],
}}
})
</script>
2.8、關於資料丟失
基於Vue對資料監聽的機制,Vue 不能檢測陣列和物件的變化。因此有些場景資料無法實現變更監聽,就無法同步檢視了,造成“資料丟失”的現象。
- 陣列透過索引修改、新增的值無法監聽。
- 未初始化的新成員,新增的物件新成員,沒有被初始化時監聽,
app1.user.新屬性=20
。 - 被凍結的物件無法監聽:
Object.freeze(obj)
。 v-model
繫結的未定義屬性不丟失!因為他是用的$set
去更新的,注意不能是data的一級屬性。
?解決辦法:
-
陣列整體賦值:新陣列賦值,或者用陣列方法修改資料,如push方法是被Vue代理實現了攔截的。
-
在Vue初始化時先申明屬性。
-
vm.$set.(obj)
強制更新,會先新增響應,然後再更新檢視。不建議動態新增data的一級屬性!在選項中預先申明。好像是一些邊界方面的技術原因。
<div id="app">
<p>p1:
<span v-for="n in arr">{{n}},</span>
</p>
<p>p2:
<b>name:</b>{{user.name}},
<b>age:</b>{{user.age}}
</p>
</div>
<script>
let app = new Vue({
el: '#app',
data: { arr: [1, 2, 3], user: { name: 'sam' }, }
})
app.arr[0] = 100; //修改,無更新
app.arr[app.arr.length] = 4; //新增,無更新
app.$set(app.arr,0,101); //強制更新
app.arr.push(5); //push有效,前面的也生效了,因為觸發了更新
app.arr = [100, 2, 3]; //重新賦值陣列,有效
app.arr = Array.of(...Array.from(app.arr),10,10); //重新賦值陣列,有效
app.user.age = 10; //這是新的屬性,無更新
app.$set(app.user,'age',18); //強制更新,有效
app.user = Object.assign({}, app.user);
app.user = user; //賦值物件,有效
</script>
03、Vue動畫
Vue提供了兩個內建元素,<transition>
和<transition-group>
,用來包裝單個元素、列表元素,輔助實現在元素顯示隱藏、建立刪除、移動過程中的過渡動畫效果。更高階、更復雜的動畫可以藉助第三方動畫元件來實現。
- Css動畫庫 Animate.css,
- Js動畫庫 anime.js (github star最高),Velocity.js,GreenSock
3.1、transition過渡動畫
Vue提供了一個<transition>
封裝元件,用來包裝需要動畫的單個內容。Vue主要提供了一個比較基礎的動畫機制,幫你處理過渡的事件、動畫類呼叫。所以還是需要你自己來寫動畫的CSS類,或者動畫JS程式碼。
- 三種型別的過渡:元素初始渲染過渡、元素進入過渡(顯示)、元素離開過渡(隱藏/刪除)。
- 包裹單元素:
<transition>
只能包裹一個跟元素(包括v-if、v-show切換),動畫應用在這個跟元素上,不會產生額外Dom元素。 - 過河拆橋--事後清理:動畫完成後,CSS動畫資源會被清除,Vue會自動監聽
transitionend
,或animationend
事件。 - 過渡CSS類名規範:如下表格,按照CSS類名寫樣式,Vue自動呼叫。
v
為動畫元件<transition>
的name
值,沒有則預設v
。 - CSS過渡類attribute:作用同上,值是Class樣式類名,優先順序更高。CSS值可以自定義,也可以很方便的呼叫第三方CSS動畫庫。
進入過渡 | 離開過渡 | CSS過渡類attribute,優先順序更高 |
---|---|---|
v-enter:初始點狀態 | v-leave:初始點狀態 | enter-class、leave-class |
v-enter-to:結束點狀態 | v-leave-to:結束點狀態 | enter-to-class、leave-to-class |
v-enter-active:進入過程,設定動畫引數 | v-leave-active:離開過程 | enter-active-class、leave-active-class |
?過渡動畫示例:CodePen
<link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet">
<div id="app15">
<div>
<button v-on:click="acitve = !acitve" ref="btn">消失</button>
<transition name="h" v-on:after-enter="updateBtn" v-on:after-leave="updateBtn">
<p v-show="acitve" style="color:red">秦時明月漢時關,萬里長征人未還!</p>
</transition>
<!-- CSS過渡類Class,使用了animate元件-->
<transition name="h" enter-active-class="animated fadeInRightBig" leave-active-class="animated zoomOut">
<p v-show="acitve" style="color:blue">秦時明月漢時關,趕快下樓做核酸!</p>
</transition>
</div>
</div>
<style>
.h-enter-active,
.h-leave-active { transition: all 0.5s cubic-bezier(1.0, 0.8, 0.5, 1.1); }
.h-enter, .h-leave-to { opacity: 0; }
.h-enter { transform: translateX(80px); }
.h-leave-to { transform: translateX(-80px); }
</style>
<script>
let app15 = new Vue({
el: "#app15",
data: { acitve: true },
methods: {
updateBtn: function (e) { this.$refs.btn.innerText = this.acitve ? "消失" : "出來"; }
}
})
</script>
transition動畫元素的屬性、鉤子事件:
✔️<transition> 屬性 |
描述 |
---|---|
name | 用於自動生成 CSS 過渡類名:name-enter 、name-leave |
appear | 開場動畫,是否在初始渲染時使用過渡,bool,預設為 false |
css | bool,是否使用 CSS 過渡類,預設ture。如果用鉤子函式JS控制動畫,可以關閉css。 |
type | Vue 監聽過渡事件型別型別,用於動畫完成後清理class資源,animation (animationend ) 或 transition(transitionend ) |
mode | 過渡模式,控制新舊元素進入/離開過渡的先後順序, out-in 、in-out ,預設同時進行。 |
duration | 過渡的持續時間(ms),{ enter: 500, leave: 500} ,用於事後清理資源,而不是設定動畫時間 |
✔️CSS 過渡類 attribute | |
進入過渡 | enter-class、enter-to-class、enter-active-class |
離開過渡 | leave-class、leave-to-class、leave-active-class |
初始渲染過渡 | appear-class、appear-to-class、appear-active-class |
✔️JavaScript 鉤子 | 用於JS的動畫控制,可以藉助第三方JS動畫庫 |
進入過渡 | before-enter(el)、enter(el, done)、after-enter(el)、enter-cancelled(el) 當只用 JavaScript 過渡的時候,在 enter 和 leave 中必須使用 done 進行回撥。否則,它們將被同步呼叫,過渡會立即完成。 |
離開過渡 | before-leave(el)、leave(el, done)、after-leave(el)、leave-cancelled (el) leaveCancelled 只用於 v-show 中 |
初始渲染過渡 | before-appear(el)、appear(el)、after-appear(el)、appear-cancelled(el) |
3.2、transition-group列表過渡動畫
列表的過渡是針對多個元素,需要 transition-group元件,支援的過渡類、特性和事件和<transition>
類似,多了tag
、移動過渡
。不過過渡針對的不是一個根元素,而是內部的每一個一級元素。<transition-group>
會產生一個元素<span>
,可透過tag修改渲染的元素,比如用來代替<ul>
不錯。
<transition-group> |
描述 |
---|---|
tag | <transition-group> 產生的元素標籤名,預設為span ,可以根據需要設定。 |
✔️CSS 過渡類 attribute | |
移動過渡 | move-class(類名:v-move) |
如果只是用進入、離開過渡,會導致其他元素的位置變化比較生硬。使用移動過渡v-move/move-class
,在元素改變定位的時候使用。Vue 使用了一個 FLIP 的動畫佇列,使用transforms
將元素位置平滑移動。
?v-for 時需設定key:
v-fo
r建立列表元素時,強烈建議設定列表項的key值,列表動畫中這是強制要求了!
程式碼示例:CodePen
<h1>app15: 動畫</h1>
<div id="app15">
<h3>列表動畫:<button @click="shuffle">隨機亂序</button></h3>
<div>
<transition-group tag="ul" name="list" enter-active-class="animated flipInX">
<li v-for="(s,i) in list" v-bind:key="s">{{s}}
<button @click="list.splice(i,1)">-</button>
<button @click="list.splice(i+1,0,s+index++)">+</button>
</li>
</transition-group>
</div>
</div>
<style>
.list-enter { opacity:0; }
.list-enter-to{ transform: translateX(50px); }
.list-leave-active{ transition: all 1s; }
.list-leave-to { opacity: 0; transform: translateX(50px); }
.list-leave-active {
position: absolute; /*讓元素移動更順滑*/
transition: all 1s; }
.list-move { transition: 0.5s; }
</style>
<script>
let app15 = new Vue({
el: "#app15",
data: { acitve: true, index: 1, list: ['張三', '李四', '王五', '對六', '小七', '李白'] },
methods: {
// 隨機排序
shuffle: function () { this.list.sort((a, b) => Math.random() - 0.5) }
}
})
</script>
©️版權申明:版權所有@安木夕,本文內容僅供學習,歡迎指正、交流,轉載請註明出處!原文編輯地址-語雀