開篇
-
1.什么是Vue?
- Vue.js是一套構建用戶界面的
框架,它不僅易于上手,還可以與其它第三方庫整合(Swiper、IScroll、...)。
- Vue.js是一套構建用戶界面的
-
2.框架和庫的區(qū)別?
- 框架:是一套完整的解決方案;對項目的
侵入性較大,項目如果需要更換框架,則需要重構整個項目。 - 庫(插件):提供某一個小功能,對項目的
侵入性較小,如果某個庫無法完成某些需求,可以很容易切換到其它庫實現(xiàn)需求。- 例如: 從jQuery 切換到 Zepto, 無縫切換
- 從IScroll切換到ScrollMagic, 只需要將用到IScroll的代碼替換成ScrollMagic代碼即可
- 框架:是一套完整的解決方案;對項目的
-
3.為什么要學習框架?
- 提升開發(fā)效率:在企業(yè)中,時間就是效率,效率就是金錢;
- 前端提高開發(fā)效率的發(fā)展歷程:原生JS -> jQuery之類的類庫 -> 前端模板引擎 -> Vue / React / Angular
-
4.框架有很多, 為什么要先學Vue
- Vue、Angular、React一起,被稱之為前端三大主流框架!
- 但是Angular、React是老外編寫的, 所以所有的資料都是英文的
- 而Vue是國人編寫的,所以所有的資料都是中文的,并且Vue中整合了Angular、React中的眾多優(yōu)點
- 所以為了降低我們的學習難度,我們先學Vue, 學完之后再學習Angular和React
- Vue、Angular、React一起,被稱之為前端三大主流框架!
-
5.使用Vue有哪些優(yōu)勢?
- 5.1Vue的核心概念之一:
- 通過數(shù)據(jù)驅動界面更新,無需操作DOM來更新界面
- 使用Vue我們只需要關心如何獲取數(shù)據(jù),如何處理數(shù)據(jù),如何編寫業(yè)務邏輯代碼,我們只需要將處理好的數(shù)據(jù)交給Vue, Vue就會自動將數(shù)據(jù)渲染到模板中(界面上)
- 通過數(shù)據(jù)驅動界面更新,無需操作DOM來更新界面
- 5.2Vue的核心概念之二:
- 組件化開發(fā),我們可以將網(wǎng)頁拆分成一個個獨立的組件來編寫,將來再通過封裝好的組件拼接成一個完整的網(wǎng)頁
- 思維導圖:https://cn.vuejs.org/images/components.png
- 5.1Vue的核心概念之一:
Vue基本模板
-
1.Vue框架使用方式
- 1.1傳統(tǒng)下載導入使用
- 1.2vue-cli安裝導入使用
-
2.Vue框架使用步驟
- 2.1下載Vue框架
- 2.2導入Vue框架
- 2.3創(chuàng)建Vue實例對象
- 2.4指定Vue實例對象控制的區(qū)域
- 2.5指定Vue實例對象控制區(qū)域的數(shù)據(jù)
Vue數(shù)據(jù)單向傳遞
-
1.MVVM設計模式
- 在MVVM設計模式中由3個部分組成
- M : Model 數(shù)據(jù)模型(保存數(shù)據(jù), 處理數(shù)據(jù)業(yè)務邏輯)
- V : View 視圖(展示數(shù)據(jù), 與用戶交互)
- VM: View Model 數(shù)據(jù)模型和視圖的橋梁(M是中國人, V是美國人, VM就是翻譯)
- MVVM設計模式最大的特點就是支持數(shù)據(jù)的雙向傳遞
- 數(shù)據(jù)可以從 M -> VM -> V
- 也可以從 V -> VM -> M
- 在MVVM設計模式中由3個部分組成
-
2.Vue中MVVM的劃分
- Vue其實是基于MVVM設計模式的
- 被控制的區(qū)域: View
- Vue實例對象 : View Model
- 實例對象中的data: Model
- Vue其實是基于MVVM設計模式的
-
3.Vue中數(shù)據(jù)的單向傳遞
- 我們把"數(shù)據(jù)"交給"Vue實例對象","Vue實例對象"將數(shù)據(jù)交給"界面"
- Model -> View Model -> View
<!--這里就是MVVM中的View-->
<div id="app">
<p>{{ name }}</p>
</div>
<script>
// 這里就是MVVM中的View Model
let vue = new Vue({
el: '#app',
// 這里就是MVVM中的Model
data: {
name: "微雙"
}
});
</script>
Vue數(shù)據(jù)雙向傳遞
-
1.Vue調試工具安裝
- 如果你能打開谷歌插件商店, 直接在線安裝即可
https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd?hl=zh-CN - 由于國內(nèi)無法打開谷歌國外插件商店, 所以可以離線安裝
https://www.chromefor.com/vue-js-devtools_v5-3-0/
- 如果你能打開谷歌插件商店, 直接在線安裝即可
-
2.安裝步驟:
- 2.1下載離線安裝包
- 2.2打開谷歌插件界面
- 2.3直接將插件拖入
- 2.4報錯程序包無效:"CRX_HEADER_INVALID",可以將安裝包修改為rar后綴,解壓之后再安裝
- 2.5重啟瀏覽器
-
3.數(shù)據(jù)雙向綁定
- 默認情況下Vue只支持數(shù)據(jù)單向傳遞 M -> VM -> V,但是由于Vue是基于MVVM設計模式的,所以也提供了雙向傳遞的能力
- 在<input>、<textarea> 及 <select> 元素上可以用v-model指令創(chuàng)建雙向數(shù)據(jù)綁定
注意點:
v-model 會忽略所有表單元素的value、checked、selected 特性的初始值,而總是將 Vue 實例的數(shù)據(jù)作為數(shù)據(jù)來源
常用指令-v-once
-
1.什么是指令?
- 指令就是Vue內(nèi)部提供的一些自定義屬性,這些屬性中封裝好了Vue內(nèi)部實現(xiàn)的一些功能,只要使用這些指令就可以使用Vue中實現(xiàn)的這些功能
-
2.Vue數(shù)據(jù)綁定的特點
- 只要數(shù)據(jù)發(fā)生變化, 界面就會跟著變化
-
3.v-once指令
- 讓界面不要跟著數(shù)據(jù)變化, 只渲染一次
-
4.v-model指令
- 渲染多次
- 示例
<div id="app">
<p v-once>{{ name }}</p>
<p>{{ name }}</p>
</div>
<script src="js/vue.js"></script>
<script>
let vue = new Vue({
el: '#app',
data: {
name: "微雙"
}
});
</script>
常用指令-v-cloak
-
1.Vue數(shù)據(jù)綁定過程
- 1.1會先將未綁定數(shù)據(jù)的界面展示給用戶
- 1.2然后再根據(jù)模型中的數(shù)據(jù)和控制的區(qū)域生成綁定數(shù)據(jù)之后的HTML代碼
- 1.3最后再將綁定數(shù)據(jù)之后的HTML渲染到界面上
- 正是在最終的HTML被生成渲染之前會先顯示模板內(nèi)容,所以如果用戶網(wǎng)絡比較慢或者網(wǎng)頁性能比較差, 那么用戶會看到模板內(nèi)容
-
2.如何解決這個問題
- 利用v-cloak配合 [v-cloak]:{display: none}默認先隱藏未渲染的界面,等到生成HTML渲染之后再重新顯示
-
3.v-cloak指令作用:
- 數(shù)據(jù)渲染之后自動顯示元素
- 示例:
<style>
[v-cloak] { display: none }
</style>
<div id="app">
<p v-cloak>{{ name }}</p>
</div>
<script src="js/vue.js"></script>
<script>
let vue = new Vue({
el: '#app',
data: {
name: "微雙"
}
});
</script>
常用指令v-text和v-html
-
1.什么是v-text指令
- v-text就相當于過去學習的innerText
- 會覆蓋便簽內(nèi)原有的內(nèi)容
- 不會解析html
-
2.什么是v-html指令
- v-html就相當于過去學習的innerHTML
- 會覆蓋便簽內(nèi)原有的內(nèi)容
- 會解析html
<div id="app">
<!--插值的方式: 可以將指定的數(shù)據(jù)插入到指定的位置-->
<p>++++{{ name }}++++</p>
<!--插值的方式: 不會解析HTML-->
<p>++++{{ msg }}++++</p>
<!--v-text的方式: 會覆蓋原有的內(nèi)容-->
<p v-text="name">++++++++</p>
<!--v-text的方式: 也不會解析HTML-->
<p v-text="msg">++++++++</p>
<!--v-html的方式: 會覆蓋原有的內(nèi)容-->
<p v-html="name">++++++++</p>
<!--v-html的方式:會解析HTML-->
<p v-html="msg">++++++++</p>
</div>
<script>
let vue = new Vue({
el: '#app',
data: {
name: "微雙",
msg: "<span>我是span</span>"
}
});
</script>
常用指令v-if/v-else
-
1.什么是v-if指令
- 條件渲染: 如果v-if取值是true就渲染元素, 如果不是就不渲染元素
-
2.==v-if特點==:
- 如果條件不滿足根本就不會創(chuàng)建這個元素
-
3.v-if注意點
- v-if可以從模型中獲取數(shù)據(jù)
- v-if也可以直接賦值一個表達式
<div id="app">
<p v-if="show">我是true</p>
<p v-if="hidden">我是false</p>
</div>
<script>
let vue = new Vue({
el: '#app',
data: {
show: true,
hidden: false
}
});
</script>
- 4.v-else指令
- v-else指令可以和v-if指令配合使用
- 當v-if不滿足條件時就執(zhí)行v-else就顯示v-else中的內(nèi)容
- v-else指令可以和v-if指令配合使用
<div id="app">
<p v-if="age >= 18">成年人</p>
<p v-else>未成年人</p>
</div>
<script>
let vue = new Vue({
el: '#app',
data: {
show: true,
hidden: false,
age: 17
}
});
</script>
5.v-else注意點
- v-else不能單獨出現(xiàn)
- v-if和v-else中間不能出現(xiàn)其它內(nèi)容
// 錯誤寫法
<div id="app">
<p v-if="age >= 18">成年人</p>
<p>中間的內(nèi)容</p>
<p v-else>未成年人</p>
</div>
- 6.v-else-if指令
- v-else-if可以和v-if指令配合使用
- 當v-if不滿足條件時就依次執(zhí)行后續(xù)v-else-if, 哪個滿足就顯示哪個
- v-else-if可以和v-if指令配合使用
<div id="app">
<p v-if="score >= 80">優(yōu)秀</p>
<p v-else-if="score >= 60">良好</p>
<p v-else>差</p>
</div>
<script>
let vue = new Vue({
el: '#app',
data: {
show: true,
hidden: false,
age: 17,
score: 50
}
});
</script>
- 7.v-else-if注意點
- v-else-if不能單獨出現(xiàn)
- v-if和v-else-if中間不能出現(xiàn)其它內(nèi)容
常用指令v-show
-
1.什么是v-show指令
- v-show和v-if的能夠一樣都是條件渲染, 取值為true就顯示, 取值為false就不顯示
-
2.==v-show特點==
- 如果條件不滿足根本就不會創(chuàng)建這個元素
-
3.v-show注意點
- v-show可以從模型中獲取數(shù)據(jù)
- v-show也可以直接賦值一個表達式
v-if和v-show區(qū)別
-
區(qū)別1:元素是否存在
- v-if: 只要取值為false就不會創(chuàng)建元素
- v-show: 哪怕取值為false也會創(chuàng)建元素, 只是如果取值是false會設置元素的display為none
-
區(qū)別2:應用場景
- 由于取值為false時v-if不會創(chuàng)建元素,所以如果需要切換元素的顯示和隱藏,每次v-if都會創(chuàng)建和刪除元素
- 由于取值為false時v-show會創(chuàng)建元素并設置display為none,所以如果需要切換元素的顯示和隱藏,不會反復創(chuàng)建和刪除,只是修改display的值
- 所以: 如果企業(yè)開發(fā)中需要頻繁切換元素顯示隱藏, 那么推薦使用v-show, 可以提高性能,否則使用v-if
常用指令v-for
-
1.什么是v-for指令
- 相當于JS中的for in循環(huán),可以根據(jù)數(shù)據(jù)多次渲染元素
-
2.v-for特點
- 可以遍歷 數(shù)組, 字符, 數(shù)字(輸出是從1開始的), 對象
- 示例:
<div id="app">
<ul>
<li v-for="(value, index) in list">{{index}}---{{value}}</li> // 遍歷數(shù)組
<li v-for="(value, index) in 'abcdefg'">{{index}}---{{value}}</li> // 遍歷字符串
<li v-for="(value, index) in 6">{{index}}---{{value}}</li> // 遍歷數(shù)字
<li v-for="(value, key) in obj">{{key}}---{{value}}</li> // 遍歷對象
</ul>
</div>
<script>
let vue = new Vue({
el: '#app',
data: {
list: ["張三", "李四", "王五", "趙六"],
obj: {
name: "lnj",
age: 33,
gender: "man",
class: "知播漁"
}
}
});
</script>
==注意點==
-
1.v-for注意點
- 1.1v-for為了提升性能,在更新已渲染過的元素列表時,會采用“就地復用”策略。也正是因為這個策略,在某些時刻會導致我們的數(shù)據(jù)混亂
- 例如: 在列表前面新增了內(nèi)容
- 1.2為了解決這個問題,我們可以在渲染列表的時候給每一個元素加上一個獨一無二的key
- v-for在更新已經(jīng)渲染過的元素列表時,會先判斷key是否相同, 如果相同則復用, 如果不同則重新創(chuàng)建
- 1.1v-for為了提升性能,在更新已渲染過的元素列表時,會采用“就地復用”策略。也正是因為這個策略,在某些時刻會導致我們的數(shù)據(jù)混亂
-
2.key屬性注意點
- 不能使用index的作為key,因為當列表的內(nèi)容新增或者刪除時index都會發(fā)生變化
- 添加到列表的末尾,index到不會發(fā)生變化,但是添加到列表頭的話,整體的index都會發(fā)生變化
- 不能使用index的作為key,因為當列表的內(nèi)容新增或者刪除時index都會發(fā)生變化
示例:
<div id="app">
<form>
<input type="text" v-model="name">
<input type="submit" value="添加" @click.prevent="add">
</form>
<ul>
<li v-for="(person,index) in persons" :key="person.id">
<input type="checkbox">
<span>{{index}} --- {{person.name}}</span>
</li>
</ul>
</div>
<script>
let vue = new Vue({
el: '#app',
data: {
persons: [
{name: "zs", id: 1},
{name: "ls", id: 2},
{name: "ww", id: 3}
],
name: ""
},
methods: {
add(){
let lastPerson = this.persons[this.persons.length - 1];
let newPerson = {name: this.name, id: lastPerson.id + 1};
// this.persons.push(newPerson);
this.persons.unshift(newPerson);
this.name = "";
}
}
});
</script>
常用指令v-bind
-
1.什么是v-bind指令
- 給"元素的==屬性=="綁定數(shù)據(jù),就必須使用v-bind
- 不同于給"元素"綁定數(shù)據(jù),我們可以使用{{}}, v-text, v-html
- 給"元素的==屬性=="綁定數(shù)據(jù),就必須使用v-bind
-
2.v-bind格式
v-bind:屬性名稱="綁定的數(shù)據(jù)": 屬性名稱="綁定的數(shù)據(jù)"
<input type="text" v-bind:value="age">
<input type="text" :value="age">
<script>
let vue = new Vue({
el: '#app',
data: {
age: 18
}
});
</script>
- 3.v-bind特點
- 賦值的數(shù)據(jù)可以是任意一個合法的JS表達式
- 例如:
:屬性名稱="age + 1"
綁定類名
-
1.v-bind指令的特殊作用
- v-bind指令給"任意標簽"的"任意屬性"綁定數(shù)據(jù),對于大部分的屬性而言我們只需要直接賦值即可, 例如:value="name"
- 但是對于class和style屬性而言, 它的格式比較特殊
-
2.通過v-bind綁定類名格式
-
:class="['需要綁定類名', ...]"普通格式 -
:class="[flag?'active':'']"數(shù)組的每一個元素都可以是一個三目運算符按需導入 -
:class="[{'active': true}]"通過對象來決定是否需要綁定 -
:class="對象名"(==這種方法不錯==,修改方便)——使用Model中的對象來替換數(shù)組- 綁定的類名太多可以將類名封裝到Model中例如:obj: {'color': true,'size': true,'active': false}
-
注意點:
1.(:class="需要綁定類名")直接賦值一個類名(沒有放到數(shù)組中)默認回去Model中查找,但是Model中沒有對應的類名, 所以無效
2.(:class="[需要綁定類名]")如果想讓v-bind去style中查找類名,那么就必須把類名放到數(shù)組中,但是放到數(shù)組中之后默認還是回去Model中查找
- 4.綁定類名企業(yè)應用場景
- 從服務器動態(tài)獲取樣式后通過v-bind動態(tài)綁定類名,這樣就可以讓服務端來控制前端樣式
- 常見場景: 618 雙11等
綁定樣式
-
通過v-bind給style屬性綁定數(shù)據(jù)
- 1.將數(shù)據(jù)放到對象中
:style="{color:'red','font-size':'50px'}"
- 2.將數(shù)據(jù)放到Model對象中
:style="obj"- Model對象中:
- obj: {color: 'red','font-size':'80px'}
- 3.如果需要綁定Model中的多個對象,可以放到一個數(shù)組中賦值
:style="[obj1,obj2]"- Model對象中:
- obj1: {color: 'red','font-size':'80px'}
- obj2: {'background-color': 'blue'}
- 1.將數(shù)據(jù)放到對象中
示例:
<div id="app">
<p :style="{color: 'red', 'font-size': '100px'}">我是段落</p>
<p :style="obj">我是段落</p>
<p :style="[obj1, obj2]">我是段落</p>
</div>
<script>
let vue = new Vue({
el: '#app',
data: {
obj:{
"color": "blue", // color可以用引號括起來,也可以不括
"font-size": "100px"
},
obj1:{
"color": "blue",
"font-size": "100px"
},
obj2: {
"background-color": "red"
}
}
});
</script>
- ==重點==:
- 屬性和取值都用引號括起來
- 個別屬性不用,但是都括起來沒毛病
- 屬性和取值都用引號括起來
注意點:
如果屬性名稱包含-, 那么必須用引號括起來
常用指令-v-on
-
1.什么是v-on指令?
- v-on指令專門用于給元素綁定監(jiān)聽事件
-
2.v-on指令兩種格式
v-on:事件名稱="回調函數(shù)名稱"@事件名稱="回調函數(shù)名稱"- 示例:
<div id="app">
<!--<button v-on:click="myFn">我是按鈕</button>-->
<button @click="myFn">我是按鈕</button>
</div>
<script>
let vue = new Vue({
el: '#app',
data: {
},
methods: {
myFn(){
alert('lnj')
}
}
});
</script>
注意點:
v-on綁定的事件被觸發(fā)之后,會去Vue實例對象的methods中查找對應的回調函數(shù)
v-on修飾符
-
1.v-on修飾符
- 在事件中有很多東西需要我們處理,例如事件冒泡,事件捕獲,阻止默認行為等.那么在Vue中如何處理以上內(nèi)容呢,我們可以通過v-on修飾符來處理
-
2.常見修飾符
-
.once- 只觸發(fā)一次回調。
-
.prevent- 調用 event.preventDefault()。阻止事件默認行為
-
.stop- 調用 event.stopPropagation()。
- 默認情況下載嵌套的元素中,如果都監(jiān)聽了相同的事件,那么會觸發(fā)事件冒泡,這個stop就是阻止事件冒泡
-
.self- 當前元素觸發(fā)事件的時候才觸發(fā)回調。
-
.capture- 添加事件偵聽器時使用 capture 模式。
- 默認情況下是事件冒泡,如果想變成事件捕獲, 那么就需要使用.capture修飾符
-
- 示例:
<style>
*{
margin: 0;
padding: 0;
}
.a{
width: 300px;
height: 300px;
background: red;
}
.b{
width: 200px;
height: 200px;
background: blue;
}
.c{
width: 100px;
height: 100px;
background: green;
}
</style>
<div id="app">
<!--<button v-on:click.once ="myFn">我是按鈕</button>-->
<!--<a v-on:click.prevent="myFn">我是A標簽</a>-->
<!--<div class="a" @click="myFn1">
<div class="b" @click.stop="myFn2">
<div class="c" @click="myFn3"></div>
</div>
</div>-->
<!--<div class="a" @click="myFn1">
<div class="b" @click.self="myFn2">
<div class="c" @click="myFn3"></div>
</div>
</div>-->
<div class="a" @click.capture="myFn1">
<div class="b" @click.capture="myFn2">
<div class="c" @click.capture="myFn3"></div>
</div>
</div>
</div>
<script>
let vue = new Vue({
el: '#app',
data: {
},
// 專門用于存儲監(jiān)聽事件回調函數(shù)
methods: {
myFn1(){
console.log("爺爺");
},
myFn2(){
console.log("爸爸");
},
myFn3(){
console.log("兒子");
}
}
});
</script>
v-on注意點
-
1.綁定回調函數(shù)名稱的時候,后面可以寫()也可以不寫
- v-on:click="myFn"
- v-on:click="myFn()"
-
2.可以給綁定的回調函數(shù)傳遞參數(shù)
- v-on:click="myFn('lnj', 33)"
- 示例:
<div id="app">
<button @click="myFn('ws',29)">按鈕</button>
</div>
<script>
let vue = new Vue({
el: '#app',
data: {
},
methods:{
myFn(name,age){
console.log(name,age);
}
}
});
</script>
- 3.如果在綁定的函數(shù)中需要用到data中的數(shù)據(jù)必須加上this
- 示例:
<div id="app">
<button @click="myFn('ws',29,$event)">按鈕</button>
</div>
<script>
let vue = new Vue({
el: '#app',
data: {
gender: 'man'
},
methods:{
myFn(name,age,e){
console.log(name,age,this.gender);
}
}
});
</script>
v-on按鍵修飾符
-
1.什么是按鍵修飾符
- 我們可以通過按鍵修飾符監(jiān)聽特定按鍵觸發(fā)的事件
- 例如: 可以監(jiān)聽當前事件是否是回車觸發(fā)的, 可以監(jiān)聽當前事件是否是ESC觸發(fā)的等
-
2.按鍵修飾符分類
- 2.1系統(tǒng)預定義修飾符
- .enter/.tab/.delete (捕獲“刪除”和“退格”鍵)/.esc/.space/.up/.down/.left/.right等
- 2.2自定義修飾符
- 可以使用
v-on:keyup.自定義按鍵名稱- Vue.config.keyCodes.自定義按鍵名稱 = 查詢keycode列表里自定義按鍵對應的值
- 可以使用
- 2.1系統(tǒng)預定義修飾符
<div id="app">
<!--<input type="text" @keyup.enter="myFn">-->
<input type="text" @keyup.f2="myFn">
</div>
<script>
Vue.config.keyCodes.f2 = 113;
let vue = new Vue({
el: '#app',
data: {
},
methods: {
myFn(){
alert("lnj");
}
}
});
</script>
自定義指令
-
1.自定義全局指令
- 在Vue中除了可以使用Vue內(nèi)置的一些指令以外, 我們還可以自定義指令
-
2.自定義全局指令語法
- 格式如下:
<script>
Vue.directive('自定義指令名稱',
{
生命周期名稱: function (el) {
指令業(yè)務邏輯代碼
}
});
</script>
- 3.指令生命周期方法
- 自定義指令時一定要明確指令的業(yè)務邏輯代碼更適合在哪個階段執(zhí)行
- 例如: 指令業(yè)務邏輯代碼中沒有用到元素事件, 那么可以在bind階段執(zhí)行
- 例如: 指令業(yè)務邏輯代碼中用到了元素事件, 那么就需要在inserted階段執(zhí)行
- 示例:
<div id="app">
<!-- <p v-color>我是段落</p>-->
<input type="text" v-focus>
</div>
<script>
Vue.directive("color", {
// 這里的el就是被綁定指令的那個元素
bind: function (el) { // bind是生命周期名稱
el.style.color = "red";
}
});
Vue.directive("focus", {
inserted: function (el) {
el.focus(); // 聚焦
}
});
</script>
自定義指令注意點:
使用時需要加上v-, 而在自定義時不需要加上v-
自定義指令參數(shù)
-
1.自定義指令參數(shù)
- 在使用官方指令的時候我們可以給指令傳參
- 例如: v-model="name"在我們自定義的指令中我們也可以傳遞傳遞
-
2.獲取自定義指令傳遞的參數(shù)
- 在執(zhí)行自定義指令對應的方法的時候,除了會傳遞el給我們,還會傳遞一個對象給我們,這個對象中就保存了指令傳遞過來的參數(shù)
- 示例:
<div id="app">
<!--<p v-color="'blue'">我是段落</p>-->
<p v-color="curColor">我是段落</p>
</div>
<script>
Vue.directive("color", {
bind: function (el, obj) {
// el.style.color = "red";
el.style.color = obj.value;
}
});
let vue = new Vue({
el: '#app',
data: {
curColor: 'green'
}
});
</script>
自定義局部指令
-
1.自定義全局指令的特點
- 在任何一個Vue實例控制的區(qū)域中都可以使用
-
2.自定義局部指令的特點
- 只能在自定義的那個Vue實例中使用
-
3.如何自定義一個局部指令
- 給創(chuàng)建Vue實例時傳遞的對象添加
- 格式如下:
<script>
let vue = new Vue({
el: '#app',
data: {
},
directives: {
// key: 指令名稱
// value: 對象
'自定義生命周期名稱': {
bind: function (el, obj) {
指令業(yè)務邏輯代碼
}
}
}
});
</script>
- 示例:
<div id="app1">
<p v-color="'blue'">我是段落</p>
</div>
<div id="app2">
<p v-color="'red'">我是段落</p>
</div>
<script>
let vue1 = new Vue({
el: '#app1',
data: {},
methods: {}
});
let vue2 = new Vue({
el: '#app2',
data: {},
methods: {},
// 專門用于定義局部指令的
directives: {
"color": {
bind: function (el, obj) {
el.style.color = obj.value;
}
}
}
});
</script>
計算屬性
-
1.插值語法特點
- 可以在{{}}中編寫合法的JavaScript表達式
-
2.在插值語法中編寫JavaScript表達式缺點
- 2.1沒有代碼提示
- 2.2語句過于復雜不利于我們維護
-
3.如何解決?
- 對于任何復雜邏輯,你都應當使用計算屬性computed
- 示例:
<div id="app">
<!--<p>{{msg.split("").reverse().join("")}}</p>-->
<p>{{msg2}}</p>
</div>
<script>
let vue = new Vue({
el: '#app',
data: {
// msg: "abcdef"
},
// 專門用于定義計算屬性的
computed: {
msg2: function () {
let res = "abcdef".split("").reverse().join("");
return res;
}
}
});
</script>
注意點:
雖然在定義計算屬性的時候是通過一個函數(shù)返回的數(shù)據(jù),但是在使用計算屬性的時候不能在計算屬性名稱后面加上()
因為它是一個屬性不是一個函數(shù)(方法)
計算屬性和函數(shù)的區(qū)別
-
1.計算屬性和函數(shù)的共同點
- 通過計算屬性或者通過函數(shù)我們都能拿到處理后的數(shù)據(jù)
-
2.計算屬性和函數(shù)的區(qū)別
- 2.1函數(shù)"不會"將計算的結果緩存起來,每一次訪問都會重新求值
- 2.2計算屬性"會"將計算的結果緩存起來, 只要數(shù)據(jù)沒有發(fā)生變化, 就不會重新求值
-
3.計算屬性應用場景
- 計算屬性:比較適合用于計算不會頻繁發(fā)生變化的的數(shù)據(jù),這樣會比使用函數(shù)的性能高
- 函數(shù):經(jīng)常發(fā)生變化的數(shù)據(jù)
<div id="app">
<p>{{msg1()}}</p>
<p>{{msg1()}}</p>
<p>{{msg1()}}</p>
<p>{{msg2}}</p>
<p>{{msg2}}</p>
<p>{{msg2}}</p>
</div>
<script>
let vue = new Vue({
el: '#app',
data: {
},
// 專門用于存儲監(jiān)聽事件回調函數(shù)
methods: {
// 函數(shù)的特點: 每次調用都會執(zhí)行
msg1(){
console.log("msg1函數(shù)被執(zhí)行了");
let res = "abcdef".split("").reverse().join("");
return res;
}
},
// 專門用于定義計算屬性的
computed: {
msg2: function () {
console.log("msg2計算屬性被執(zhí)行了");
let res = "abcdef".split("").reverse().join("");
return res;
}
}
});
</script>
自定義全局過濾器
-
1.什么是過濾器?
- 過濾器和函數(shù)和計算屬性一樣都是用來處理數(shù)據(jù)的,但是過濾器一般用于格式化插入的文本數(shù)據(jù)
-
2.自定義全局過濾器的特點
- 在任何一個Vue實例控制的區(qū)域中都可以使用
-
3.如何自定義全局過濾器Vue.filter
- Vue.filter(參數(shù)1,參數(shù)2);
- 第一個參數(shù): 過濾器名稱
- 第二個參數(shù): 處理數(shù)據(jù)的函數(shù)
- Vue.filter(參數(shù)1,參數(shù)2);
注意點:
默認情況下處理數(shù)據(jù)的函數(shù)接收一個參數(shù),就是當前要被處理的數(shù)據(jù)
-
4.如何使用全局過濾器
{{msg | 過濾器名稱}}:value="msg | 過濾器名稱"
-
5.過濾器注意點
- 5.1只能在插值語法和v-bind中使用
- 5.2過濾器可以連續(xù)使用
- 示例:
<div id="app">
<!--Vue會把name交給指定的過濾器處理之后, 再把處理之后的結果插入到指定的元素中-->
<p>{{name | formartStr1 | formartStr2}}</p>
</div>
<script>
Vue.filter("formartStr1", function (value) {
value = value.replace(/學院/g, "大學");
return value;
});
Vue.filter("formartStr2", function (value) {
value = value.replace(/大學/g, "幼兒園");
return value;
});
let vue = new Vue({
el: '#app',
data: {
name: "知播漁學院, 指趣學院, 前端學院, 區(qū)塊鏈學院"
}
});
</script>
自定義局部過濾器
-
1.自定義局部過濾器的特點
- 只能在自定義的那個Vue實例中使用
-
2.如何自定義一個局部指令
- 給創(chuàng)建Vue實例時傳遞的對象添加
- 格式如下:
filters: {
// key: 過濾器名稱
// value: 過濾器處理函數(shù)
'過濾器名稱': function (value) {
過濾器處理函數(shù)
}
}
- 示例:
<div id="app1">
<p>{{name | formartStr}}</p>
</div>
<div id="app2">
<p>{{name | formartStr}}</p>
</div>
<script>
let vue1 = new Vue({
el: '#app1',
data: {
name: "知播漁學院, 指趣學院, 前端學院, 區(qū)塊鏈學院"
}
});
let vue2 = new Vue({
el: '#app2',
data: {
name: "知播漁學院, 指趣學院, 前端學院, 區(qū)塊鏈學院"
},
// 專門用于定義局部過濾器的
filters: {
"formartStr": function (value) {
value = value.replace(/學院/g, "大學");
return value;
}
}
});
</script>
- ==注意點==
- 在使用過濾器的時候,可以在過濾器名稱后面加上()
- 如果給過濾器的名稱后面加上了(),那么就可以給過濾器的函數(shù)傳遞參數(shù)
- 示例:
<div id="app">
<p>{{time | filter1('yyyy-MM-dd')}}</p>
</div>
<script>
Vue.filter('filter1',function (value,frm) {
let date = new Date(value);
let year = date.getFullYear();
let mouth = date.getMonth() + 1 + '';
let day = date.getDate() + '';
let hour = date.getHours() + '';
let minute = date.getMinutes() + '';
let second = date.getSeconds() + '';
if(frm && frm === 'yyyy-MM-dd'){
return `${year}-${mouth.padStart(2,'0')}-${day.padStart(2,'0')}`;
}
return `${year}-${mouth.padStart(2,'0')}-${day.padStart(2,'0')} ${hour.padStart(2,'0')}:${minute.padStart(2,'0')}:${second.padStart(2,'0')}`;
});
let vue = new Vue({
el: '#app',
data: {
name:'知播漁學院, 指趣學院, 前端學院, 區(qū)塊鏈學院',
time: Date.now()
}
});
</script>
過渡動畫
1.默認類名(v-xxx)來指定過渡動畫
- 如何給Vue控制的元素添加過渡動畫
- 1.將需要執(zhí)行動畫的元素放到transition組件中
- 2.transition組件中會自動查找
- 顯示時會自動查找
.v-enter/.v-enter-active/.v-enter-to類名 - 隱藏時會自動查找
.v-leave/ .v-leave-active/.v-leave-to類名
- 顯示時會自動查找
- 3.我們只需要在
.v-enter和.v-leave-to中指定動畫動畫開始的狀態(tài) - 4.在
.v-enter-active和.v-leave-active中指定動畫執(zhí)行的狀態(tài) - 5.即可完成過渡動畫
- 示例:
<style>
*{
margin: 0;
padding: 0;
}
.box{
width: 200px;
height: 200px;
background: red;
}
.v-enter{
opacity: 0;
}
.v-enter-to{
opacity: 1;
}
.v-enter-active{
transition: all 3s;
}
.v-leave{
opacity: 1;
}
.v-leave-to{
opacity: 0;
}
.v-leave-active{
transition: all 3s;
}
</style>
<div id="app">
<button @click="toggle">我是按鈕</button>
<transition>
<div class="box" v-show="isShow"></div>
</transition>
</div>
<script>
let vue = new Vue({
el: '#app',
data: {
isShow: false
},
methods: {
toggle(){
this.isShow = !this.isShow;
}
}
});
</script>
==注意點==
-
1.初始動畫設置
- 默認情況下第一次進入的時候沒有動畫的
- 如果想一進來就有動畫,我們可以通過給transition添加appear屬性的方式,告訴Vue第一次進入就需要顯示動畫
-
2.如何給多個不同的元素指定不同的動畫
- 如果有多個不同的元素需要執(zhí)行不同的過渡動畫,那么我們可以通過給transition指定name的方式,來指定"進入之前/進入之后/進入過程中,離開之前/離開之后/離開過程中"對應的類名,來實現(xiàn)不同的元素執(zhí)行不同的過渡動畫
注意點:
transition中只能放一個元素, 多個元素無效
如果想給多個元素添加過渡動畫, 那么就必須創(chuàng)建多個transition組件
<style>
*{
margin: 0;
padding: 0;
}
.box{
width: 200px;
height: 200px;
background: red;
}
.one-enter{
opacity: 0;
}
.one-enter-to{
opacity: 1;
margin-left: 500px;
}
.one-enter-active{
transition: all 3s;
}
.two-enter{
opacity: 0;
}
.two-enter-to{
opacity: 1;
margin-top: 500px;
}
.two-enter-active{
transition: all 3s;
}
</style>
<div id="app">
<button @click="toggle">我是按鈕</button>
<transition appear name="one">
<div class="box" v-show="isShow"></div>
</transition>
<transition appear name="two">
<div class="box" v-show="isShow"></div>
</transition>
</div>
<script>
let vue = new Vue({
el: '#app',
data: {
isShow: true
},
methods: {
toggle(){
this.isShow = !this.isShow;
}
}
});
</script>
2.JS鉤子函數(shù)來指定過渡動畫
-
1.當前過渡存在的問題
- 通過transition+類名的方式確實能夠實現(xiàn)過渡效果,但是實現(xiàn)的過渡效果并不能保存動畫之后的狀態(tài)
- 因為Vue內(nèi)部的實現(xiàn)是在過程中動態(tài)綁定類名, 過程完成之后刪除類名
- 正是因為刪除了類名, 所以不能保存最終的效果
-
2.在Vue中如何保存過渡最終的效果
- 通過Vue提供的JS鉤子來實現(xiàn)過渡動畫
v-on:before-enter="beforeEnter"進入動畫之前v-on:enter="enter"進入動畫執(zhí)行過程中v-on:after-enter="afterEnter"進入動畫完成之后v-on:enter-cancelled="enterCancelled"進入動畫被取消v-on:before-leave="beforeLeave"離開動畫之前v-on:leave="leave"離開動畫執(zhí)行過程中v-on:after-leave="afterLeave"離開動畫完成之后v-on:leave-cancelled="leaveCancelled"離開動畫被取消
- 通過Vue提供的JS鉤子來實現(xiàn)過渡動畫
-
3.JS鉤子實現(xiàn)過渡注意點
- 3.1在動畫過程中必須寫上el.offsetWidth或者el.offsetHeight
- 3.2在enter和leave方法中必須調用done方法,否則after-enter和after-leave不會執(zhí)行
- 3.3若需要添加初始動畫,那么需要把done方法包裹到setTimeout方法中調用
- 示例:
<div id="app">
<button @click="toggle">我是按鈕</button>
<transition appear
v-bind:css="false"
v-on:before-enter="beforeEnter"
v-on:enter="enter"
v-on:after-enter="afterEnter">
<div class="box" v-show="isShow"></div>
</transition>
</div>
<script>
let vue = new Vue({
el: '#app',
data: {
isShow: true
},
methods: {
toggle(){
this.isShow = !this.isShow;
},
beforeEnter(el){
// 進入動畫開始之前
console.log("beforeEnter");
el.style.opacity = "0";
},
enter(el, done){
// 進入動畫執(zhí)行過程中
console.log("enter");
// el.offsetWidth;
el.offsetHeight;
el.style.transition = "all 3s";
// done();
/*
注意點: 如果想讓元素一進來就有動畫, 那么最好延遲以下再調用done方法
*/
setTimeout(function () {
done();
}, 0);
},
afterEnter(el){
// 進入動畫執(zhí)行完畢之后
console.log("afterEnter");
el.style.opacity = "1";
el.style.marginLeft = "500px";
}
}
});
</script>
配合使用第三方 JavaScript 動畫庫,實現(xiàn)過渡動畫
- 配合Velocity實現(xiàn)過渡動畫
- 在Vue中我們除了可以自己實現(xiàn)過渡動畫以外,還可以結合第三方框架實現(xiàn)過渡動畫
- 1.導入Velocity庫
- 2.在動畫執(zhí)行過程鉤子函數(shù)中編寫Velocity動畫
- 示例:
- 在Vue中我們除了可以自己實現(xiàn)過渡動畫以外,還可以結合第三方框架實現(xiàn)過渡動畫
<style>
*{
margin: 0;
padding: 0;
}
.box{
width: 200px;
height: 200px;
background: red;
}
</style>
<div id="app">
<button @click="toggle">我是按鈕</button>
<transition appear
v-bind:css="false"
v-on:before-enter="beforeEnter"
v-on:enter="enter"
v-on:after-enter="afterEnter">
<div class="box" v-show="isShow"></div>
</transition>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js"></script>
<script>
let vue = new Vue({
el: '#app',
data: {
isShow: true
},
methods: {
toggle(){
this.isShow = !this.isShow;
},
beforeEnter(el){
},
enter(el, done){
Velocity(el, {opacity: 1, marginLeft: "500px"}, 3000);
done();
},
afterEnter(el){
}
}
});
</script>
使用自定義類名的方式來指定過渡動畫
-
1.自定義類名動畫
- 1.在Vue中除了可以使用默認類名(v-xxx)來指定過渡動畫
- 2.除了可以使用自定義類名前綴(yyy-xx)來指定過渡動畫(transition name="yyy")
- 3.除了可以使用 JS鉤子函數(shù)來指定過渡動畫以外
- 4.還可以使用自定義類名的方式來指定過渡動畫
-
enter-class進入動畫開始之前 -
enter-active-class進入動畫執(zhí)行過程中 -
enter-to-class進入動畫執(zhí)行完畢之后 -
leave-class離開動畫開始之前 -
leave-active-class離開動畫執(zhí)行過程中 -
leave-to-class離開動畫執(zhí)行完畢之后
-
示例:
<style>
*{
margin: 0;
padding: 0;
}
.box{
width: 200px;
height: 200px;
background: red;
}
.a{
opacity: 0;
}
.b{
opacity: 1;
margin-left: 500px;
}
.c{
transition: all 3s;
}
</style>
<div id="app">
<button @click="toggle">我是按鈕</button>
<transition appear
enter-class="a"
enter-active-class="c"
enter-to-class="b">
<div class="box" v-show="isShow"></div>
</transition>
</div>
<script>
let vue = new Vue({
el: '#app',
data: {
isShow: true
},
methods: {
toggle(){
this.isShow = !this.isShow;
}
}
});
</script>
配合使用第三方 CSS 動畫庫Animate.css實現(xiàn)過渡動畫
- 配合Animate.css實現(xiàn)過渡動畫步驟
- 1.導入Animate.css庫
- 2.在執(zhí)行過程中的屬性上綁定需要的類名
- 示例:
<link rel="stylesheet" type="text/css">
<div id="app">
<button @click="toggle">我是按鈕</button>
<transition appear
enter-active-class="animated bounceInRight">
<div class="box" v-show="isShow"></div>
</transition>
</div>
<script>
let vue = new Vue({
el: '#app',
data: {
isShow: true
},
methods: {
toggle(){
this.isShow = !this.isShow;
}
}
});
</script>
過渡動畫(添加多個)
- 如何同時給多個元素添加過渡動畫
- 通過transition可以給單個元素添加過渡動畫,如果想給多個元素添加過渡動畫,那么就必須通過transition-group來添加
- transition-group和transition的用法一致,只是一個是給單個元素添加動畫,一個是給多個元素添加動畫而已
- 示例(不是最終版,里面還有bug,下面有講注意點):
<style>
*{
margin: 0;
padding: 0;
}
.v-enter{
opacity: 0;
}
.v-enter-to{
opacity: 1;
}
.v-enter-active{
transition: all 3s;
}
.v-leave{
opacity: 1;
}
.v-leave-to{
opacity: 0;
}
.v-leave-active{
transition: all 3s;
}
</style>
<div id="app">
<form>
<input type="text" v-model="name">
<input type="submit" value="添加" @click.prevent="add">
</form>
<ul>
<transition-group appear>
<li v-for="(person,index) in persons" :key="person.id" @click="del(index)">
<input type="checkbox">
<span>{{index}} --- {{person.name}}</span>
</li>
</transition-group>
</ul>
</div>
<script>
let vue = new Vue({
el: '#app',
data: {
persons: [
{name: "zs", id: 1},
{name: "ls", id: 2},
{name: "ww", id: 3}
],
name: ""
},
methods: {
add(){
let lastPerson = this.persons[this.persons.length - 1];
let newPerson = {name: this.name, id: lastPerson.id + 1};
// this.persons.push(newPerson);
this.persons.unshift(newPerson);
this.name = "";
},
del(index){
this.persons.splice(index, 1);
}
}
});
</script>
注意點:
-
1.標簽問題
- 默認情況下transition-group會將動畫的元素放到span標簽中
- 解決方法:我們可以通過tag屬性來指定將動畫元素放到什么標簽中(把html里面對應的標簽刪除,tag屬性就會自動添加標簽)
- 默認情況下transition-group會將動畫的元素放到span標簽中
-
2.transition-group動畫混亂問題
- 一般情況下組動畫出現(xiàn)動畫混亂都是因為v-for就地復用導致的
- 解決方案:我們只需要保證所有數(shù)據(jù)key永遠是唯一的即可
- 示例(上面示例就有這個bug),解決如下:
- 1.data里面新增一個id,賦值為3(list的長度)
- 2.add方法中
- 添加
this.id++ -
let lastPerson = this.persons[this.persons.length - 1];刪除 -
let newPerson = {name: this.name, id: lastPerson.id + 1};改成let newPerson = {name: this.name, id: this.id}; - 成品View Model如下:
- 添加
- 一般情況下組動畫出現(xiàn)動畫混亂都是因為v-for就地復用導致的
<script>
let vue = new Vue({
el: '#app',
data: {
persons: [
{name: "zs", id: 1},
{name: "ls", id: 2},
{name: "ww", id: 3}
],
name: "",
id: 3
},
methods: {
add(){
this.id++;
// let lastPerson = this.persons[this.persons.length - 1];
let newPerson = {name: this.name, id: this.id};
// this.persons.push(newPerson);
this.persons.unshift(newPerson);
this.name = "";
},
del(index){
this.persons.splice(index, 1);
}
}
});
</script>