Vue
1苗踪、基本概念
- 漸進式框架
? 漸進式意味著你可以將Vue作為你應(yīng)用的一部分嵌入其中整以,帶來更豐富的交互體驗 - 特點
- 解耦視圖和數(shù)據(jù)
- 可復(fù)用的組件
- 前端路由技術(shù)
- 狀態(tài)管理
- 虛擬DOM
2、安裝Vue.js
?1. 直接CDN引入
<!-- 開發(fā)環(huán)境版本,包含了有幫助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 生產(chǎn)環(huán)境版本本鸣,優(yōu)化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
? 2. 下載后項目中引入js文件
? 3. 使用npm安裝
3、 初體驗
<div id="app">
<h2>{{message}}</h2>
<ul>
<li v-for="item in movies">{{item}}</li>
</ul>
<h2>{{count}}</h2>
<button type="button" @click="add">+</button>
<button type="button" @click="sub">-</button>
</div>
//數(shù)據(jù)和視圖分離 引入vue的js文件
<script src="../js/vue.js"></script>
<script>
//let(ES6定義變量)/const(常量)
let app=new Vue({
el:'#app',//用于掛載要管理的元素,id的方式就用#
data:{//定義數(shù)據(jù)
message:'Hello Vue',
// 數(shù)組
movies:['Hello','World','VUE']
}硅蹦,
methods:{
add:function(){
console.log('add執(zhí)行');
this.count++;
},
sub:function(){
console.log('sub執(zhí)行');
this.count--;
}
}
});
</script>
-
演示
演示
4永高、什么是MVVM
- View層
視圖層
在我們前端開發(fā)中,通常就是DOM層提针。
主要的作用是給用戶展示各種信息命爬。 - Model層
數(shù)據(jù)層
數(shù)據(jù)可能是我們固定的死數(shù)據(jù),更多的是來自我們服務(wù)器辐脖,從網(wǎng)絡(luò)上請求下來的數(shù)據(jù)饲宛。
在我們計數(shù)器的案例中,就是后面抽取出來的obj嗜价,當(dāng)然艇抠,里面的數(shù)據(jù)可能沒有這么簡單。 -
VueModel層
視圖模型層
視圖模型層是View和Model溝通的橋梁久锥。
一方面它實現(xiàn)了Data Binding家淤,也就是數(shù)據(jù)綁定,將Model的改變實時的反應(yīng)到View中
另一方面它實現(xiàn)了DOM Listener瑟由,也就是DOM監(jiān)聽絮重,當(dāng)DOM發(fā)生一些事件(點擊、滾動歹苦、touch等)時青伤,可以監(jiān)聽到,并在需要的情況下改變對應(yīng)的Data殴瘦。
官網(wǎng)模型
6狠角、Vue實例的Options
- el:
類型:string | HTMLElement
作用:決定之后Vue實例會管理哪一個DOM - data:
類型:Object | Function (組件當(dāng)中data必須是一個函數(shù))
作用:Vue實例對應(yīng)的數(shù)據(jù)對象 - methods:
類型:{ [key: string]: Function }
作用:定義屬于Vue的一些方法,可以在其他地方調(diào)用蚪腋,也可以在指令中使用
7丰歌、Vue的生命周期
-
官方解釋
官方
8姨蟋、語法
8.1、插入操作
8.1.1立帖、Mustache
- 就是兩個{{}}眼溶,并且可以在里面寫入簡單的表達式
<h2>{{firstName + lastName}}</h2>
8.1.2、v-once
- 有時候我們想一些界面數(shù)據(jù)不跟隨其他的進行改變厘惦,該指令表示元素和組件(組件后面才會學(xué)習(xí))只渲染一次偷仿,不會隨著數(shù)據(jù)的改變而改變。
<h2 v-once>{{message}}</h2>
8.1.3宵蕉、v-html
- 某些情況下酝静,我們從服務(wù)器請求到的數(shù)據(jù)本身就是一個HTML代碼
- 如果我們直接通過{{}}來輸出,會將HTML代碼也一起輸出
- 但是我們可能希望的是按照HTML格式進行解析羡玛,并且顯示對應(yīng)的內(nèi)容
<h2 v-html="url"></h2>
//則顯示的時候是相當(dāng)于正常使用a標(biāo)簽顯示一樣
url: '<a
8.1.4别智、v-text
- v-text作用和Mustache比較相似:都是用于將數(shù)據(jù)顯示在界面中
<h2 v-text="message"></h2>
8.1.5、v-pre
- v-pre用于跳過這個元素和它子元素的編譯過程稼稿,用于顯示原本的Mustache語法
<h2 v-pre>{{message}}</h2>
- 直接顯示出{{message}}
8.1.6薄榛、v-cloak
- 在某些情況下,我們?yōu)g覽器可能會直接顯然出未編譯的Mustache標(biāo)簽
- 防止閃爍..防止htlml先顯示{{message}}之類的
<div id="app" v-cloak>
<h2>{{message}}</h2>
</div>
8.2让歼、綁定屬性
8.2.1敞恋、v-bind
- v-bind用于綁定一個或多個屬性值,或者向另一個組件傳遞props值
<div id="app">
<a v-bind:href="ahref">百度</a>
</div>
<script>
let app=new Vue({
el:'#app',//用于掛載要管理的元素
data:{//定義數(shù)據(jù)
ahref:'http://www.baidu.com'
}
});
</script>
//簡寫 : <a :href="ahref">xxx</a>
8.2.2谋右、v-bind綁定class-對象語法
- 直接通過{}綁定一個類
<h2 :class="{'active': isActive}">Hello World</h2>
- 也可以通過判斷硬猫,傳入多個值
<h2 :class="{'active': isActive, 'line': isLine}">Hello World</h2>
- 和普通的類同時存在,并不沖突
注:如果isActive和isLine都為true改执,那么會有title/active/line三個類
<h2 class="title" :class="{'active': isActive, 'line': isLine}">Hello World</h2>
- 如果過于復(fù)雜啸蜜,可以放在一個methods或者computed中
注:classes是一個計算屬性
<h2 class="title" :class="classes">Hello World</h2>
8.2.3、v-bind綁定class-數(shù)組語法
- 直接通過{}綁定一個類
<h2 :class="['active']">Hello World</h2>
- 也可以通過判斷辈挂,傳入多個值
<h2 :class=“[‘a(chǎn)ctive’, 'line']">Hello World</h2>
- 和普通的類同時存在衬横,并不沖突
注:如果isActive和isLine都為true,那么會有title/active/line三個類
<h2 class="title" :class=“[‘a(chǎn)ctive’, 'line']">Hello World</h2>
- 如果過于復(fù)雜终蒂,可以放在一個methods或者computed中
注:classes是一個計算屬性
<h2 class="title" :class="classes">Hello World</h2>
8.2.4蜂林、v-bind綁定style
- 在寫CSS屬性名的時候,比如font-size
- 我們可以使用駝峰式 (camelCase) fontSize
- 或短橫線分隔 (kebab-case后豫,記得用單引號括起來) ‘font-size’
8.2.5悉尾、v-bind綁定style--對象語法
:style="{color: currentColor, fontSize: fontSize + 'px'}"
style后面跟的是一個對象類型
- 對象的key是CSS屬性名稱
- 對象的value是具體賦的值,值可以來自于data中的屬性
8.2.5挫酿、v-bind綁定style--數(shù)組語法
<div v-bind:style="[baseStyles, overridingStyles]"></div>
style后面跟的是一個數(shù)組類型
- 多個值以,分割即可
8.3愕难、計算屬性
- 我們知道早龟,在模板中可以直接通過插值語法顯示一些data中的數(shù)據(jù)惫霸。
- 但是在某些情況,我們可能需要對數(shù)據(jù)進行一些轉(zhuǎn)化后再顯示葱弟,或者需要將多個數(shù)據(jù)結(jié)合起來進行顯示
比如我們有firstName和lastName兩個變量壹店,我們需要顯示完整的名稱。 - 但是如果多個地方都需要顯示完整的名稱芝加,我們就需要寫多個{{firstName}} {{lastName}}硅卢,重復(fù)的東西太多這在開發(fā)當(dāng)中是非常忌諱的
<div id="app">
<h2>{{firstName + ' ' + lastName}}</h2>
<h2>{{firstName}} {{lastName}}</h2>
<h2>{{getFullName()}}</h2>
<h2>{{fullName}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
firstName: 'Lebron',
lastName: 'James'
},
// computed: 計算屬性()
computed: {
fullName: function () {
return this.firstName + ' ' + this.lastName
}
//上面的可以簡寫成如下
fullName() {
return this.firstName + ' ' + this.lastName
}
},
//同樣上述的可以寫成方法進行實現(xiàn),記住調(diào)用的時候有些不一樣
methods: {
getFullName() {
return this.firstName + ' ' + this.lastName
}
}
})
</script>
- Tips
計算屬性是基于它們的依賴進行緩存的藏杖。只有依賴值改變時将塑,計算屬性才重新求值。依賴不變時蝌麸,多次訪問計算屬性点寥,會直接返回之前的計算結(jié)果,不必再次執(zhí)行函數(shù)来吩。
而每次訪問調(diào)用方法時敢辩,它都會再次執(zhí)行函數(shù)。即使當(dāng)前頁面已經(jīng)調(diào)用過一次了弟疆,新調(diào)用時還會重新計算
計算屬性只有在改變的時候才會再次執(zhí)行對應(yīng)函數(shù)戚长,方法則每次都會再次執(zhí)行函數(shù)
計算屬性會進行緩存,如果多次使用時怠苔,計算屬性只會調(diào)用一次(內(nèi)容沒修改的前提下)
8.3.1同廉、復(fù)雜操作
圖片1.png
8.3.2、計算屬性的setter嘀略、getter
// 計算屬性一般是沒有set方法, 只讀屬性.
fullName: {
set: function(newValue) {
// console.log('-----', newValue);
const names = newValue.split(' ');
this.firstName = names[0];
this.lastName = names[1];
},
get: function () {
return this.firstName + ' ' + this.lastName
}
}
//一般還是直接簡寫成上面的那種形式
- 使用set的情況:如果我在控制臺修改:fuuName="xxx xxx"恤溶,默認會調(diào)用set方法。
8.4帜羊、事件監(jiān)聽
- 在前端開發(fā)中咒程,我們需要經(jīng)常和用于交互。
- 這個時候讼育,我們就必須監(jiān)聽用戶發(fā)生的時間帐姻,比如點擊、拖拽奶段、鍵盤事件等等
8.4.1饥瓷、v-on的使用
- 綁定事件監(jiān)聽器
- 縮寫:@
<button v-on:click="increment">+</button>
//簡寫
<button @click="decrement">-</button>
8.4.2、v-on參數(shù)
- 如果該方法不需要額外參數(shù)痹籍,那么方法后的()可以不添加
<button @click="decrement()">-</button>
//直接寫成如下形式
<button @click="decrement">-</button>
<!--2.在事件定義時, 寫方法時省略了小括號,
但是方法本身是需要一個參數(shù)的, 這個時候, Vue會默認將
瀏覽器生產(chǎn)的event事件對象作為參數(shù)傳入到方法-->
<button @click="btn2Click">按鈕2</button>
<!--3.方法定義時, 我們需要event對象, 同時又需要其他參數(shù)-->
<!-- 在調(diào)用方式, 如何手動的獲取到瀏覽器參數(shù)的event對象: $event-->
<button @click="btn3Click(abc, $event)">按鈕3</button>
//對應(yīng)的方法
btn2Click(event) {
console.log('--------', event);
},
btn3Click(abc, event) {
console.log('++++++++', abc, event);
}
-
演示
image.png
9.1.3呢铆、v-on修飾符
演示.png
8.5、條件判斷
- v-if后面的條件為false時蹲缠,對應(yīng)的元素以及其子元素不會渲染棺克。
- 也就是根本沒有不會有對應(yīng)的標(biāo)簽出現(xiàn)在DOM中
<div id="app">
<h2 v-if="score>=90">優(yōu)秀</h2>
<h2 v-else-if="score>=80">良好</h2>
<h2 v-else-if="score>=60">及格</h2>
<h2 v-else>不及格</h2>
//也可以寫在計算屬性當(dāng)中
<h1>{{result}}</h1>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
score: 99
},
computed: {
result() {
let showMessage = '';
if (this.score >= 90) {
showMessage = '優(yōu)秀'
} else if (this.score >= 80) {
showMessage = '良好'
}
return showMessage
}
}
})
</script>
8.5.1悠垛、小案例
- 用戶再登錄時,可以切換使用用戶賬號登錄還是郵箱地址登錄
<div id="app">
<span v-if="isUser">
<label for="username">用戶賬號</label>
<input type="text" id="username" placeholder="用戶賬號">
</span>
<span v-else>
<label for="email">用戶郵箱</label>
<input type="text" id="email" placeholder="用戶郵箱">
</span>
<button @click="isUser = !isUser">切換類型</button>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
isUser: true
}
})
</script>
- 我們可以發(fā)現(xiàn)隨便測試能夠?qū)崿F(xiàn)我們的功能娜谊,但是存在一個問題确买,如果我們在用戶賬號的輸入框輸入內(nèi)容的時候,我們再點擊用戶郵箱時纱皆,會發(fā)現(xiàn)輸入框里面的內(nèi)容也任然是存在的湾趾,文字依然顯示之前的輸入的內(nèi)容。
Q:為什么會存在這種問題么派草?另一個input原本是沒有內(nèi)容的搀缠。
A:這是因為Vue在進行DOM渲染時,出于性能考慮澳眷,會盡可能的復(fù)用已經(jīng)存在的元素胡嘿,而不是重新創(chuàng)建新的元素,任然會復(fù)用原本的input - 解決
這時候我們需要保證key的不同钳踊,避免復(fù)用衷敌,將上述代碼添加各自的key,確保唯一!
<input type="text" id="username" placeholder="用戶賬號" key="username">
<input type="text" id="email" placeholder="用戶郵箱" key="email">
8.6拓瞪、v-show
- v-show的用法和v-if非常相似缴罗,也用于決定一個元素是否渲染
v-if和v-show對比
- v-if當(dāng)條件為false時,壓根不會有對應(yīng)的元素在DOM中祭埂。
- v-show當(dāng)條件為false時面氓,僅僅是將元素的display屬性設(shè)置為none而已
如何選擇?
- 當(dāng)需要在顯示與隱藏之間切片很頻繁時蛆橡,使用v-show
- 當(dāng)只有一次切換時舌界,通過使用v-if
<!--v-show: 當(dāng)條件為false時, v-show只是給我們的元素添加一個行內(nèi)樣式: display: none-->
<h2 v-show="isShow" id="bbb">{{message}}</h2>
8.7、循環(huán)遍歷--數(shù)組
- 格式:item in items的形式
//不需要索引值
<!--1.在遍歷的過程中,沒有使用索引值(下標(biāo)值)-->
<ul>
<li v-for="item in names">{{item}}</li>
</ul>
<!--2.在遍歷的過程中, 獲取索引值-->
//其中的index就代表了取出的item在原數(shù)組的索引值
<ul>
<li v-for="(item, index) in names">
{{index+1}}.{{item}}
</li>
</ul>
8.7.1泰演、循環(huán)遍歷--對象
<div id="app">
<!--1.在遍歷對象的過程中, 如果只是獲取一個值, 那么獲取到的是value-->
<ul>
<li v-for="item in info">{{item}}</li>
</ul>
<!--2.獲取key和value 格式: (value, key) -->
<ul>
<li v-for="(value, key) in info">{{value}}-{{key}}</li>
</ul>
<!--3.獲取key和value和index 格式: (value, key, index) -->
<ul>
<li v-for="(value, key, index) in info">{{value}}-{{key}}-{{index}}</li>
</ul>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
info: {
name: 'why',
age: 18,
height: 1.88
}
}
})
</script>
8.7.2呻拌、組件的key屬性
- 官方推薦我們在使用v-for時,給對應(yīng)的元素或組件添加上一個:key屬性
- 這其實和Vue的虛擬DOM的Diff算法有關(guān)系
- 可以這么理解睦焕,好比有一個數(shù)組藐握,我們得我往中間插入一個數(shù)據(jù),那么就需要插入位置后面的數(shù)據(jù)全部往后面移動一位垃喊,顯然這是很沒有效率的
- 所以就需要通過key給每一個節(jié)點做一個唯一標(biāo)識猾普,通過Diff算法就可以正確的識別此節(jié)點了,并且找到正確的位置區(qū)插入新的節(jié)點
- key的作用主要是為了高效的更新虛擬DOM
<div id="app">
<ul>
<li v-for="item in letters" :key="item">{{item}}</li>
</ul>
</div>
8.8本谜、檢測數(shù)組更新
- vue是響應(yīng)式的初家,當(dāng)數(shù)據(jù)發(fā)生改變,Vue檢測到data數(shù)據(jù)改變就會重新渲染dom
- push()
- pop()
- shift()
- unshift()
- splice()
- sort()
-
reverse()
相關(guān)代碼
8.9、小案例--圖書購物車
<div id="app">
<div v-if="books.length">
<table>
<thead>
<tr>
<th></th>
<th>書籍名稱</th>
<th>出版日期</th>
<th>價格</th>
<th>購買數(shù)量</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in books">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.date}}</td>
<td>{{item.price | showPrice}}</td>
<td>
<button @click="decrement(index)" v-bind:disabled="item.count <= 1">-</button>
{{item.count}}
<button @click="increment(index)">+</button>
</td>
<td><button @click="removeHandle(index)">移除</button></td>
</tr>
</tbody>
</table>
<h2>總價格: {{totalPrice | showPrice}}</h2>
</div>
<h2 v-else>購物車為空</h2>
</div>
<script>const app = new Vue({
el: '#app',
data: {
books: [
{
id: 1,
name: '《算法導(dǎo)論》',
date: '2006-9',
price: 85.00,
count: 1
},
{
id: 2,
name: '《UNIX編程藝術(shù)》',
date: '2006-2',
price: 59.00,
count: 1
}
]
},
methods: {
increment(index) {
this.books[index].count++
},
decrement(index) {
this.books[index].count--
},
removeHandle(index) {
this.books.splice(index, 1)
}
},
computed: {
totalPrice() {
let totalPrice = 0
for (let i = 0; i < this.books.length; i++) {
totalPrice += this.books[i].price * this.books[i].count
}
return totalPrice
}
},
filters: {
showPrice(price) {
return '¥' + price.toFixed(2)
}
}
})
</script>
9笤成、表單綁定v-model
- Vue中使用v-model指令來實現(xiàn)表單元素和數(shù)據(jù)的雙向綁定
- 當(dāng)我們在輸入框輸入內(nèi)容時
- 因為input中的v-model綁定了message评架,所以會實時將輸入的內(nèi)容傳遞給message眷茁,message發(fā)生改變炕泳。
- 當(dāng)message發(fā)生改變時,因為上面我們使用Mustache語法上祈,將message的值插入到DOM中培遵,所以DOM會發(fā)生響應(yīng)的改變。
- 所以登刺,通過v-model實現(xiàn)了雙向的綁定籽腕。
<div id="app">
<input type="text" v-model="message">
{{message}}
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊'
}
})
</script>
9.1、v-model的原理
- v-model其實是一個語法糖纸俭,它的背后本質(zhì)上是包含兩個操作:
- v-bind綁定一個value屬性
- v-on指令給當(dāng)前元素綁定input事件
<input type="text" v-model="message">
等同于
<input type="text" v-bind:value="message" v-on:input="message = $event.target.value">
9.1.1皇耗、v-model:radio
- 單選框
<div id="app">
<label for="male">
<input type="radio" id="male" value="男" v-model="sex">男
</label>
<label for="female">
<input type="radio" id="female" value="女" v-model="sex">女
</label>
<h2>您選擇的性別是: {{sex}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
sex: '女'
}
})
</script>
9.1.1、v-model:checkbox
- 多選框
單個勾選框:
- v-model即為布爾值揍很。
- 此時input的value并不影響v-model的值郎楼。
多個復(fù)選框:
- 當(dāng)是多個復(fù)選框時,因為可以選中多個窒悔,所以對應(yīng)的data-中屬性是一個數(shù)組呜袁。
- 當(dāng)選中某一個時,就會將input的value添加到數(shù)組中简珠。
<!--1.checkbox單選框-->
<label for="agree">
<input type="checkbox" id="agree" v-model="isAgree">同意協(xié)議
</label>
<h2>您選擇的是: {{isAgree}}</h2>
<button :disabled="!isAgree">下一步</button>
<!--2.checkbox多選框-->
<input type="checkbox" value="籃球" v-model="hobbies">籃球
<input type="checkbox" value="足球" v-model="hobbies">足球
<input type="checkbox" value="乒乓球" v-model="hobbies">乒乓球
<input type="checkbox" value="羽毛球" v-model="hobbies">羽毛球
<h2>您的愛好是: {{hobbies}}</h2>
<label v-for="item in originHobbies" :for="item">
<input type="checkbox" :value="item" :id="item" v-model="hobbies">{{item}}
</label>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
isAgree: false, // 單選框
hobbies: [], // 多選框,
originHobbies: ['籃球', '足球', '乒乓球', '羽毛球', '臺球', '高爾夫球']
}
})
</script>
9.2.3阶界、v-model:select
單選:只能選中一個值。
- v-model綁定的是一個值聋庵。
- 當(dāng)我們選中option中的一個時膘融,會將它對應(yīng)的value賦值到mySelect中
多選:可以選中多個值。
- v-model綁定的是一個數(shù)組祭玉。
- 當(dāng)選中多個值時氧映,就會將選中的option對應(yīng)的value添加到數(shù)組mySelects中
<div id="app">
<!--1.選擇一個-->
<select name="abc" v-model="fruit">
<option value="蘋果">蘋果</option>
<option value="香蕉">香蕉</option>
<option value="榴蓮">榴蓮</option>
<option value="葡萄">葡萄</option>
</select>
<h2>您選擇的水果是: {{fruit}}</h2>
<!--2.選擇多個值 增加multiple-->
<select name="abc" v-model="fruits" multiple>
<option value="蘋果">蘋果</option>
<option value="香蕉">香蕉</option>
<option value="榴蓮">榴蓮</option>
<option value="葡萄">葡萄</option>
</select>
<h2>您選擇的水果是: {{fruits}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
fruit: '香蕉',
fruits: []
}
})
</script>
9.3、值綁定
9.4攘宙、修飾符
- lazy修飾符:
- 默認情況下屯耸,v-model默認是在input事件中同步輸入框的數(shù)據(jù)的。
- 也就是說蹭劈,一旦有數(shù)據(jù)發(fā)生改變對應(yīng)的data中的數(shù)據(jù)就會自動發(fā)生改變疗绣。
- lazy修飾符可以讓數(shù)據(jù)在失去焦點或者回車時才會更新:
<input type="text" v-model.lazy="message">
- number修飾符:
- 默認情況下,在輸入框中無論我們輸入的是字母還是數(shù)字铺韧,都會被當(dāng)做字符串類型進行處理多矮。
- 但是如果我們希望處理的是數(shù)字類型,那么最好直接將內(nèi)容當(dāng)做數(shù)字處理。
- number修飾符可以讓在輸入框中輸入的內(nèi)容自動轉(zhuǎn)成數(shù)字類型:
<input type="number" v-model.number="age">
- trim修飾符:
- 如果輸入的內(nèi)容首尾有很多空格塔逃,通常我們希望將其去除
- trim修飾符可以過濾內(nèi)容左右兩邊的空格
<input type="text" v-model.trim="name">