模板語法
插值語法
Mustache插值採用{{ }}
,用於解析標籤體內容,將Vue例項中的資料插入DOM中
<h1>Hello {{name}}</h1>
指令語法
指令用於解析標籤,是vue為開發者提供的一套模板語法,輔助開發者渲染頁面的基本結構。
(指令是vue開發中最基礎、最常用、最簡單的知識點)(支援繫結簡單的資料值之外,還支援js表示式運算)
內容渲染指令
1、v-text=" "
會覆蓋元素內預設的值、無法寫HTML標籤語句
2、{{ }}
插值表示式(Mustache) 不會覆蓋元素中預設的內容
3、v-html
可以渲染包含HTML標籤的字串
v-html
有安全性問題,在網站上動態渲染任意HTML是非常危險的,容易導致XSS攻擊;永遠不要再使用者提交的內容上使用v-html
。
屬性繫結指令
v-bind:
為元素的屬性動態繫結屬性值
屬性:placeholder、src等
簡寫::
<a v-bind:href="url">點選跳轉</a>
<a :href="url">點選跳轉</a>
事件繫結指令
v-on:
為DOM元素繫結事件監聽
v-on:click=” “、v-on:input、v-on:keyup
事件處理函式,需要在methods節點中進行宣告
簡寫:@、如果事件處理函式的程式碼足夠簡單,只有一行程式碼,則可以簡寫到行內
事件物件event
<body>
<div id="app">{{username}}</div>
<button @click="addcount($event,88)">
點選我
</button>
<script src="vue.js"></script>
<script>
const vm=new Vue({
el:'#app',
data:{
username:'zs',
count:0
},
methods:{
addcount(e,88){
const nowBgColor =e.target.style.backgroundColor
console.log(nowB gColor)
this.count+=1
}
}
})
</script>
</body>
繫結事件並傳參,使用() 小括號,但會佔用event的位置
$event是vue提供的特殊變數用於佔位,用來表示原生事件引數物件event,使用e接受
事件修飾符
vue提供事件修飾符,來輔助程式設計師更方便的對事件的觸發進行控制
-
.stop
阻止事件冒泡()裡到外 -
.prevent
阻止預設行為()比如阻止跳轉 -
.capture
以捕獲模式觸發當前事件處理函式(外到裡) -
.self
只有在event.target是當前元素自身時觸發事件處理函式 -
.once
繫結的事件只觸發一次 -
.passive
事件的預設行為立即執行,無需等待事件回撥執行完畢
按鍵修飾符
監聽鍵盤事件時,我們經常需要判斷詳細的按鍵,此時可為鍵盤相關的事件新增按鍵修飾符
- .enter、.delete、.esc、.space、.tab(特殊:只適用於keydown)、.up、.down、.left、.right
- 系統修飾符(用法特殊):ctrl、alt、shift、mta 配合keyup使用:按下按鍵的同時需要再按下其他鍵,隨後事件才被觸發;keydown正常觸發事件
- 也可以使用keyCode去指定具體的按鍵(不推薦)
- Vue.config.keyCodes.自定義鍵名=鍵碼 可以去定製按鍵別名
雙向繫結指令
v-model 在不操作DOM的情況下,快速獲取表單資料(只能配合表單元素一起使用)
<input type="text" v-model:value="username"/>
<input type="text" v-model="username"/>
v-model 指令的修飾符
方便使用者對輸入的內容進行處理
.number
自動將使用者輸入值轉化為數值.trim
自動過濾使用者輸入的首尾空白字元.lazy
在change時更新而非input時更新(不實時更新,文字框失去焦點更新)
條件渲染指令
按需控制DOM的顯示和隱藏
v-if =" "
動態建立或移除DOM元素,有更高的切換開銷(重繪和迴流)
v-else-if =" "
、v-else =" "
v-show=" "
動態為元素新增或移除display樣式,有更高的初始渲染開銷。
列表渲染指令
v-for=" "
輔助開發者基於一個陣列來迴圈渲染相似的UI結構
特殊語法:item in items
<body>
<div id="root">
<!-- 遍歷陣列 -->
<ul>
<li v-for="item in persons" :key="item.id">
{{item.id}}-{{item.name}}-{{item.age}}
</li>
</ul>
<!-- 遍歷物件 -->
<ul>
<li v-for="(value,key) of cars" :key="key">
{{key}}-{{value}}
</li>
</ul>
<!-- 遍歷字串 -->
<ul>
<li v-for="(char,index) of str" :key="index">
{{index}}-{{char}}
</li>
</ul>
<!-- 遍歷指定次數 -->
<ul>
<li v-for="(number,index) of 5" :key="index">
{{index}}-{{number}}
</li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
const vm=new Vue({
el:'#root',
data:{
persons:[
{id:'001',name:'張三',age:18},
{id:'002',name:'李四',age:17},
{id:'003',name:'王五',age:42},
],
cars:{
name:'Audi',
price:"70W",
color:"black"
},
str:"hello"
}
})
</script>
</body>
for in和for of
for in一般遍歷物件,不建議遍歷陣列。遍歷陣列請使用for of或forEach。
v-for中的索引
(item,index) in items
注:v-for中的item項和index索引都是形參,任意命名
key作用和原理
當列表的資料變化(新增、刪除)時,vue會盡可能複用已存在的DOM元素,從而提升渲染的效能,但這種效能最佳化策略會導致有狀態的列表無法被正確更新,key的使用將減少不必要的DOM操作,提高更新效率。
解釋:
Vue根據初始資料生成初始虛擬DOM(Vnodes),將虛擬DOM轉為真實DOM,使用者新增新的資料,產生新虛擬DOM(Vnodes),此時將兩份虛擬DOM根據key進行對比(diff 演算法),如果對比一樣的直接複用,將之前的真實DOM直接渲染;不一樣的無法複用,將其生成真實DOM。
- 如果使用index作為key,diff對比時會完全錯位,所有節點都無法複用,效率降低。
- 如果不指定key時,vue自動使用遍歷時的索引值index作為key。
為了給vue一個提示,以便它能跟蹤每個節點的身份,需要為每項提供一個唯一的key屬性
注:
-
key只能是字串或數字型別
-
key的值必須具有唯一性
-
建議把資料項id屬性的值作為key的值,將index的值作為key的值沒有任何意義(https://blog.csdn.net/z591102/article/details/106682298/)
-
建議使用v-for時一定要指定key的值(提升效能,防止列表狀態紊亂)
-
但不存在對資料的操作,僅是渲染列表用於展示,使用index作為key沒有問題
其他內建指令
v-cloak
沒有值,配合CSS,解決網速慢、伺服器響應慢時未經解析的模板渲染到頁面上,Vue例項建立並接管容器後,會刪掉該屬性。
[v-cloak]:{
display:none;
}
v-once
沒有值,記錄初始值,在初次動態渲染後,就視為靜態內容,以後資料的改變不會引起v-once
所在結構的更新,可以用於效能最佳化。
v-pre
沒有值,跳過其所在節點的編譯過程,可以用它跳過:沒有使用指令語法、插值語法的節點,會加快編譯。
自定義指令
本質:將原生操作DOM進行二次封裝。
<body>
<div id="root">
<!-- v-big放大10倍 -->
<h2>當前的n值是:<span v-text="n"></span></h2>
<h2>放大10倍後的n值是:<span v-big="n"></span></h2>
<button @click="n++">點位n++</button>
<hr>
<!-- v-fbind在v-bind基礎上,自動獲得焦點 -->
<input type="text" v-fbind:value="n">
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
const vm=new Vue({
el:'#root',
data:{
n:0,
},
directives:{
//函式式
//何時會被呼叫:1、指令和元素成功繫結;2、指令所在的模板被重新解析時
big(element,binding){
element.innerText=binding.value*10
},
//錯誤寫法:
fbind(element,binding){
element.value=binding.value
element.focus()//.focus()呼叫時機不對,此時input還未被插入頁面
},
//物件式
fbind:{
//指令與元素成功繫結時呼叫
bind(element,binding){
element.value=binding.value
},
//指令所在元素被插入頁面時呼叫
inserted(element,binding){
element.focus()
},
//指令所在模板被重新解析時呼叫
update (element,binding) {
element.value=binding.value
},
}
},
})
</script>
</body>
注意:
- 命名多個單詞使用
-
分隔; - 指令中
this
的指向是window
; - 自定義指令預設都是區域性指令,全域性寫法:
Vue.directive
;
計算屬性
計算屬性本質上就是一個function函式,它可以實時監聽data中資料的變化,並return一個計算後的新值,供元件渲染DOM時使用。
開發者需要以function函式的形式宣告到元件的computed節點中
<template>
<div>
<input type="text" name="" id="" v-model.number="count">
<p>{{count}} 乘以2的值為:{{plus}}</p>//必須當做普通屬性使用
</div>
</template>
<script>
export default {
name:'MyCount',
data(){
return{
count:1,
}
},
//必須定義在computed節點
computed:{
//必須是一個function函式
plus(){
//必須具有返回值
return this.count*2
}
//相當於
plus:{
//當讀取plus,get會被呼叫,且返回值作為plus的值
//get何時被呼叫?1、初次呼叫plus;2、所依賴的資料發生變化
get(){
return this.count*2
}
}
}
}
</script>
側重於得到一個計算的結果,必須有return返回值
計算屬性(computed)vs方法(methods):
相對於方法,計算屬性會快取計算結果,只有計算屬性的依賴項發生變化時,才會重新進行運算,因此計算屬性的效能會更好。
watch偵聽器
watch偵聽器允許開發者監視資料的變化,從而針對資料的變化做特定的操作
開發者需要在watch節點之下,定義自己的偵聽器
<script>
export default {
name:'MyCount',
data(){
return{
username:'',
}
},
watch:{
//當username發生改變時,呼叫 handler
username:{
handler(newVal,oldVal){
console.log(newVal,oldVal)
}
}
//簡寫
username(newVal,oldVal){
console.log(newVal,oldVal)
}
}
}
</script>
<body>
<div id="app">{{username}}</div>
#匯入指令碼檔案
<script src="vue.js"></script>
<script>
const vm=new Vue({
data(){
return{
username:'zs'
}
}
})
vm.$mount=('#app')//掛載
vm.$wtach('username',{ //第二種寫法
handler(newVal,oldVal){
console.log(newVal,oldVal)
}
})
//簡寫
vm.$wtach('username',function(newVal,oldVal){
console.log(newVal,oldVal)
}
})
</script>
</body>
應用場景
使用watch檢測使用者名稱是否可用,監聽username值得變化,並使用axios發起ajax請求,檢測當前輸入的使用者名稱是否可用
<script>
import axios from 'axios'
export default {
name:'MyCount',
data(){
return{
username:'',
}
},
watch:{
async username(newVal,oldVal){
console.log(newVal,oldVal)
const {data:res}=await axios.get('https://www.escook.cn/api/finduser'+newVal)
//await簡化promise例項物件為資料
console.log(res)
}
}
}
</script>
immediate選項
預設元件在初次載入完畢後不會呼叫watch偵聽器,如果想讓watch偵聽器立即被呼叫,則需要使用immediate選項
<script>
import axios from 'axios'
export default {
name:'MyCount',
data(){
return{
username:'',
}
},
watch:{
//不能直接定義成方法,要讓監聽的資料指向一個配置物件
username:{
async handler(newVal,oldVal){
const {data:res}=await axios.get('https://www.escook.cn/api/finduser'+newVal)
//await簡化promise例項物件為資料
console.log(res)
},
//立即觸發watch偵聽器
immediate:true,
}
}
}
</script>
deep選項
當watch偵聽的是一個物件,如果物件中的屬性值發生了變化,則無法被監聽到,需要使用deep
選項偵聽所有屬性的變化。
<script>
import axios from 'axios'
export default {
name:'MyCount',
data(){
return{
username:'',
}
},
watch:{
//不能直接定義成方法,要讓監聽的資料指向一個配置物件
username:{
async handler(newVal,oldVal){
const {data:res}=await axios.get('https://www.escook.cn/api/finduser'+newVal)
//await簡化promise例項物件為資料
console.log(res)
},
deep:true,//監視多級結構(物件)中所有屬性的變化
}
}
}
</script>
監視多級結構(物件)中單個屬性的變化
<script>
import axios from 'axios'
export default {
name:'MyCount',
data(){
return{
info:{username:'zs',password:'123456'}
}
},
watch:{
//不能直接定義成方法,要讓監聽的資料指向一個配置物件
'info.username':{//只想監聽info.username的屬性變化
async handler(newVal,oldVal){
const {data:res}=await axios.get('https://www.escook.cn/api/finduser'+newVal)
//await簡化promise例項物件為資料
console.log(res)
},
deep:true,
}
}
}
</script>
計算屬性vs偵聽器
- computed能完成的功能,watch都可以完成,都能完成的,優先使用computed。
- watch可以完成的,computed不一定能完成,例如watch可以處理非同步任務。
- 計算屬性和偵聽器側重的應用場景不同。
-
前者側重監聽多個值的變化,最終計算返回一個新值
-
後者側重於單個資料的變化,最終執行特定的業務處理,不需要任何返回值
兩個原則:
- Vue所管理的函式,最好寫成普通函式,這樣this的指向才是vm或元件例項物件,否則指向window。
- 所有不被Vue所管理的函式(定時器的回撥函式、ajax的回撥函式、Promise的回撥函式),最好寫成箭頭函式,這樣this的指向才是vm或元件例項物件,否則指向window。
繫結樣式
繫結class樣式
<!--字串寫法,適用於樣式的類名不確定,需要動態指定-->
<h1 class="basic" :class:"className">Hello World!</h1>
<!--陣列寫法,適用於樣式的個數和類名都不確定-->
<h1 class="basic" :class:"classArr">Hello World!</h1>
<!--物件寫法,適用於樣式的個數和類名都確定,但要動態覺得用不用-->
<h1 class="basic" :class:"classObj">Hello World!</h1>
繫結style樣式
<!--動態指定-->
<h1 class="basic" :style="{fontSize: fsize+'px';}">Hello World!</h1>
<h1 class="basic" :style="styleObj">Hello World!</h1>
<h1 class="basic" :style="[styleObj1,styleObj2]">Hello World!</h1>
過濾器
(Vue3.x廢棄,用計算屬性、方法代替)
什麼是過濾器?
過濾器(Filters)常用於文字的格式化,本質是一個函式
過濾器應該被新增到js表示式的尾部,由“管道符”進行呼叫
- 用於插值表示式
- 用於v-bind屬性繫結
定義(區域性)過濾器
在建立vue例項期間,可以在filters節點中定義過 濾器
私有和全域性過濾器
私有過濾器:只能在被vm例項控制的區域下控制
如果想在多個vue例項之間共享過濾器,則可以按照如下格式宣告全域性過濾器:
<script>
vue.filter('capitalize',(str)=>{
return str.charAt(0).toUpperCase() + str.slice(1)+'--'
})
new Vue...
</script>
注:如果二者衝突以私有過濾器為準,就近原則
連續呼叫多個過濾器
過濾器可以串聯的地呼叫
{{message | capitalize | maxlength}
過濾器傳參
過濾器本質是js函式,第一個引數永遠是管道符前面的值,第二個引數開始才是arg1、arg2...
{{message | filterA(agr1,arg2)}
vue.filter('filterA',(msg,arg1,aarg2)=>{})
過濾器的相容性
在vue3.x版本中已經剔除了過濾器相關功能,可以使用計算方法或屬性來代替