看這邊博客前需要知道v-bind,v-modle,v-on這三個是幹什麼用的,下方會大量用到,如果不清楚可以看我的博客(https://xunmi.blog.csdn.net/article/details/106854178)
觸發視圖更新
常用方法
Vue中有一些用於數組的方法(和Python中用於列表的方法有很多相似之處,所以如果有一定Python基礎的同學可能會很輕鬆就能看懂),Vue數組使用這些方法時就會觸發更新。
push()
: 添加元素的方法。pop()
: 刪除數組最後一個元素。shift()
: 刪除數組的第一個元素。unshift("元素")
: 在數組的開頭位置添加一個元素。
<!DOCTYPE html>
<html lang="zh_CN">
<head>
<meta charset="UTF-8">
<title>dome10</title>
</head>
<body>
<div id ="app">
<p>{{vdata}}</p>
<input type="text" v-model="vadd">
<button @click='vpush'> push添加輸入的元素 </button>
<button @click='vpop'>pop刪除數組末尾元素</button>
<button @click='vshift'>shift刪除數組開頭元素</button>
<button @click='vunshift'>unshift在數組開頭添加元素</button>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
//創建Vue實例
var vm = new Vue({
el: '#app',
data: {
vdata: ['Python', 'Django', 'Vue'],
vadd: ''
},
methods: {
vpush(){
// 在數組末尾中添加元素
this.vdata.push(this.vadd)
},
vpop(){
// 刪除數組末尾的元素
this.vdata.pop()
},
vshift(){
// 刪除數組開頭的元素
this.vdata.shift()
},
vunshift(){
// 在數組開頭添加元素
this.vdata.unshift(this.vadd)
}
}
});
</script>
</html>
splice(索引->在第幾個位置開始添加, 數量->添加幾個, 內容1, 內容2 ..., 內容x)
: 想數組中添加(內容>數量)或刪除(內容<數量)或替換元素(內容=數量)。
<!DOCTYPE html>
<html lang="zh_CN">
<head>
<meta charset="UTF-8">
<title>dome11</title>
</head>
<body>
<div id ="app">
<p>{{vdata}}</p>
<button @click="vsplice(1)">向開頭和第一個參數後添加Django</button>
<button @click="vsplice(2)">將首個參數替換爲flask</button>
<button @click="vsplice(3)">開頭前兩個參數替換爲一個abc</button>
<button @click="vsplice(4)">刪除第一個</button>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
//創建Vue實例
var vm = new Vue({
el: '#app',
data: {
vdata: ["Python", "Vue", "HTML"]
},
methods: {
vsplice(num){
if (num==1) {
// 向第一個參數後添加Django
this.vdata.splice(1, 0, "Django")
// 向開頭位置添加Django
this.vdata.splice(0, 0, "Django")
} else if(num==2) {
// 將首個參數替換爲flask
this.vdata.splice(0,1, "flask")
} else if (num==3) {
// 將前兩個替換爲abc
this.vdata.splice(0,2, "abc")
} else {
// 刪除第一個
this.vdata.splice(0,1)
}
}
}
});
</script>
</html>
6. sort(函數)
: 根據函數進行排序。這裏的排序需要傳入一個匿名函數,然後會根據匿名函數的輸出值進行排序,每次只對兩個元素排序,如果是正值,則序列不變,如果是負值,則會將顛倒
7. reverse()
: 將數組元素反轉。
<!DOCTYPE html>
<html lang="zh_CN">
<head>
<meta charset="UTF-8">
<title>dome12</title>
</head>
<body>
<div id ="app">
<p>{{vdata}}</p>
<button @click="vsort">隨機排序</button>
<p>{{vdome}}</p>
<button @click="vitem">從大到小排序</button>
<button @click="vall">反轉所有數組</button>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
//創建Vue實例
var vm = new Vue({
el: '#app',
data: {
vdata: ["Python", "Django", "Vue", "HTML"],
vdome: [1, 5, 8, 7]
},
methods: {
vsort(){
this.vdata.sort(function(){
var a = Math.random()*10-5
return a
})
},
vitem(){
this.vdome.sort(function(x,y){
if (x>y) {
return -1
} else {
return 1
}
})
},
vall(){
this.vdome.reverse()
this.vdata.reverse()
}
}
});
</script>
</html>
視圖更新注意事項
上述方法都可以立即更新視圖,但也有一些情況是無法觸發視圖更新的,避免踩坑,我會列出可能會碰到的坑, 我們直接修改數組或者字典是無法觸發視圖更新的,如果需要在數組或字典中添加新的元素,可以使用Vue.set()
方法,但是修改字典中的值是會發出視圖更新的
<!DOCTYPE html>
<html lang="zh_CN">
<head>
<meta charset="UTF-8">
<title>dome</title>
</head>
<body>
<div id ="app">
<p>{{vdata}}</p>
<button @click="append(0)">直接修改數組值</button>
<button @click="append()">使用set方法修改</button>
<p>{{vitem}}</p>
<button @click="add(0)">直接添加屬性</button>
<button @click="add(1)">使用set添加屬性</button>
<button @click="add()">修改屬性</button>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
//創建Vue實例
var vm = new Vue({
el: '#app',
data: {
vdata : ["Python", "Django", "HTML"],
vitem : {
'meizu' : '黃章',
'smartisan' : '羅永浩',
'xiaomi' : '雷軍'
}
},
methods: {
append(a){
if (a==0) {
// 直接修改某值雖然數組中值會被改變,但並不會出發視圖更新
this.vdata[0] = "json"
// 在控制檯顯示更新的內容
console.log(this.vdata)
} else {
// 使用Vue.set方法可以出發視圖更新
Vue.set(this.vdata, 1, 'json')
console.log(this.vdata)
}
},
add(a){
if (a==0) {
// 添加屬性,同樣直接添加無法觸發視圖更新
this.vitem.apple = "喬布斯"
console.log(this.vitem)
} else if(a==1) {
//這時候修改還是需要靠Vue.set
Vue.set(this.vitem, "Microsoft", "比爾蓋茨")
console.log(this.vitem)
} else {
// 雖然添加的時候無法觸發視圖更新,但修改的時候可以
this.vitem.smartisan = "行業冥燈"
}
}
}
});
</script>
</html>
計算屬性
一般情況下,我們都會將屬性放在Vue的data
中,但有些屬性我們可以需要進行一些邏輯計算。我們可以將這樣的屬性變成計算屬性computed
。
<!DOCTYPE html>
<html lang="zh_CN">
<head>
<meta charset="UTF-8">
<title>dome14</title>
</head>
<body>
<div id ="app">
<p>計算圓面積</p>
請輸入半徑: <input type="text" v-model="radius">
<p>{{radius*radius*3.14}}</p>
<!-- 調用方法(methods)我們需要加括號 -->
<p>{{m_area()}}</p>
<!-- 但是直接調用計算屬性的時候我們不需要加括號(類似python中的property裝飾器將方法變爲屬性) -->
<p>{{c_area}}</p>
<button @click="item">記錄當前半徑</button>
<p>{{vdata}}</p>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
//創建Vue實例
var vm = new Vue({
el: '#app',
data: {
radius : 0,
vdata: []
},
methods: {
// 將計算屬性放在methods中
m_area(){
console.log('methods被調用了')
return this.radius*this.radius*3.14
},
item(){
this.vdata.push(this.radius)
}
},
computed: {
// 將計算屬性放在專門爲其設立的computed中
c_area(){
console.log('computed被調用了')
return this.radius*this.radius*3.14
}
}
});
</script>
</html>
你可能對此有所疑問,計算函數爲什麼不直接放在方法中(methods)中,而要放在專門爲其設立的計算屬性(computed)中?他們有什麼區別嗎?
實際上,計算屬性更加智能,他是基於它們的響應式依賴進行緩存的。也就是說只要相關依賴(上面的c_area)沒有發生改變,那麼計算屬性的函數不會重新執行,而是直接返回之前的值。這個緩存功能讓計算屬性訪問更加高效
從上述圖片可以看出,寫在計算屬性computed
中的方法只有在計算的時候纔會被調用,而methods
中的方法,只要視圖發送更新,他就會被調用。
計算屬性中的set
計算屬性默認只有get
,不過在需要的時候,我們也可以做一個set
。但提供set
的前提是有get
方法。get是得到,一般是要返回的;set是設置,不用返回。說的直白點就是計算屬性默認只能根據this
得到的值進行計算,而不能接收參數,根據參數計算。在上面計算屬性代碼中,我也有提到計算屬性computed
和方法methods
調用都不相同,調用computed是像屬性一樣不用加括號的。這也就導致了無法傳入參數,而set方法就能解決這個問題。
<!DOCTYPE html>
<html lang="zh_CN">
<head>
<meta charset="UTF-8">
<title>dome15</title>
</head>
<body>
<div id ="app">
<p>計算圓面積</p>
<!-- .lazy是雙向綁定的一個修飾符,用於等待輸入完成後在出發更新 -->
請輸入半徑: <input type="text" v-model.lazy="radius">
<!-- 如果不理解雙向綁定可以看我的博客(https://xunmi.blog.csdn.net/article/details/106854178) -->
<input type="text" v-model.lazy="area">
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
//創建Vue實例
var vm = new Vue({
el: '#app',
data: {
radius : 0
},
computed: {
// 注意,如果需要添加get和set,這裏就不是函數了(area:function(){}或area(){}變成了area:{})
area:{
get(){
return this.radius*this.radius*3.14
},
// set可以接受參數,然後根據參加直接計算
set(value){
this.radius = (value/3.14)**0.5
}
}
}
});
</script>
</html>
監聽屬性
監聽屬性顧名思義,可以針對某個屬性進行監聽,只要這個屬性的值發生改變了,那麼就是執行相應的函數。監聽屬性存放在Vue的watch
中,並且創建使用需要監聽的屬性進行命名的方法,監聽器中的方法默認會有兩個參數,分別爲改變之前的參數和改變之後的參數。
<!DOCTYPE html>
<html lang="zh_CN">
<head>
<meta charset="UTF-8">
<title>dome16</title>
</head>
<body>
<div id ="app">
請輸入:<input type="text" v-model="keyword">
<P>{{vdata}}</P>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
//創建Vue實例
var vm = new Vue({
el: '#app',
data: {
keyword : "",
vdata : ""
},
watch: {
// 使用需要監聽的屬性進行命名
keyword(newValue, oldValue){
// 並且監聽器中的方法默認會有兩個參數,分別爲改變之前的參數和改變之後的參數
console.log("變更前的久值: "+oldValue)
console.log("變更後的新值: "+newValue)
this.vdata = "當前輸入的內容由: -> " + oldValue + " <- 變更爲 -> " + newValue + " <- 新值共:" + newValue.length + "個字。"
}
}
});
</script>
</html>
過濾器
過濾器可以過濾一些用戶輸入的字符,可以用於防範一些xss攻擊!
使用
過濾器可以用於兩個地方: 雙花括號值{{}}
和v-bind
(Vue2.1版本之後支持)中。過濾器應該被添加在JavaScript
表達式尾部,用"管道符"|
連接。
定義
過濾器的定義也有兩種,一種是在組件選項中定義的本地過濾器filters
,另一種是在創建Vue實例之前定義的全局過濾器Vue.filter
<!DOCTYPE html>
<html lang="zh_CN">
<head>
<meta charset="UTF-8">
<title>dome17</title>
</head>
<body>
<div id ="app">
請輸入: <input type="text" v-model="vdata"> (其中英文狀態下單雙引號將會被過濾)
<!-- 過濾器在{{}}雙大括號中可以調用 -->
<p>{{vdata|xss}}</p>
<!-- 過濾器在v-bind綁定中也可以使用 -->
<input type="text" :value="vdata|leach" placeholder="全局過濾器">
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
// 全局過濾器
Vue.filter('leach', (value)=>{
console.log("全局過濾器接收的值:"+value)
// .replace()中我放入的是一個正則表達式
// js的正則表達式需要使用 `//`包裹, 雙斜槓中的反斜槓是用來轉義單、雙引號用的,其中g是指的批量替換(如果沒有g只會替換一個)
value = "我是全局過濾器:"+value.replace(/\"/g,"").replace(/\'/g,"")
return value
})
//創建Vue實例
var vm = new Vue({
el: '#app',
data: {
vdata : '',
filter : ''
},
// 本地過濾器
filters: {
// xss: (value)=>{} 是xss: function(value){}的簡寫, =>可以取代匿名函數中的function
xss: (value)=>{
console.log("本地過濾器接收的值:"+value)
value = "我是本地過濾器:"+value.replace(/\"/g,"").replace(/\'/g,"")
return value
}
}});
</script>
</html>