一、引入
在 Vue.js 中,指令(Directives)是一種特殊的標記,用於向 Vue 例項提供特殊的行為。指令以 v-
開頭,例如 v-if
、v-for
等。
- 指令的本質就是語法糖,標誌位。在編譯階段 render 函式里,會把指令編譯成 JavaScript 程式碼。
- 注意:指令都是放在標籤上的
二、指令
1、文字指令
(1)v-text
v-text
是渲染字串,會覆蓋原先的字串
(2)v-html
v-html
是渲染為html。- 但是,不建議使用v-html指令,因為它會導致被惡意者進行XSS攻擊的潛在風險。
(3)示例
{{}}
雙大括號和v-text
都是輸出為文字。那如果想輸出為html。使用v-html
,如下例子
<div id="app">
<div>{{innerHtml}}</div>
<div v-text="innerHtml">123</div>
<div v-html="innerHtml">123</div>
</div>
<script>
new Vue({
el:"#app",
data:{
innerHtml:'<button>一個按鈕</button>'
}
})
</script>
2、事件指令
(1)v-on
-
v-on 事件繫結指令,用來輔助程式設計師為DOM 元素繫結事件監聽,並提供處理邏輯。
-
語法:
v-on:事件型別="methods中函式名"
v-on:事件型別="內聯語句"
-
由於v-on 指令在開發中使用頻率非常高,因此,vue 官方為其提供了簡寫形式(簡寫為英文的@)
-
常用的事件有:點選事件,雙擊事件,拖動事件,得到焦點,失去焦點。。。。
例如:
<body>
<div id="app">
<!-- 完整寫法 v-on: -->
// v-on:事件名 = "methods中的函式名"
<div v-on:click="handleClick">點選事件</div>
// v-on:事件名 = "內聯語句"
<button v-on:click="count++">按鈕</button>
<!-- 縮寫 @ -->
<div @click="handleClick">點選事件</div>
<button @click="count++">按鈕</button>
</div>
</body>
<script>
new Vue({
el:"#app",
data:{
},
methods:{
// 定義一個 點選函式
handleClick:function(){
console.dir('click event')
}
},
})
</script>
(2)es6的物件寫法
var hobby=['抽菸','燙頭']
var obj={
'name':'lqz', // 正常寫法
age:19, // 1、key之可以不用加引號
hobby, // 2、陣列可以直接寫名字,但必須在外面定義好
showName:function() { // 3、定義函式
console.log(this.name)
},
showName() { // 4、函式簡寫
console.log(this.name)
}
}
console.log(obj)
obj.showName() // 外部直接呼叫內部函式
(3)v-on呼叫傳參
- 函式有一個引數
- 如果在事件中觸發函式,沒有傳引數,會自動把事件物件傳入
- 定義好的引數,傳的就是什麼引數
- 把事件物件傳入(
$event
)
- 函式有多個引數
- 少傳不加括號,但是js裡面的函式需要多個引數,結果是第一個是事件物件,其他為undefined
- 少傳加括號,但是js裡面的函式需要多個引數,不會把自動把事件物件傳入,均為undefined
- 需要3個引數,但是多傳了引數,結果是隻接受自己的3個引數,多的不要
- 多個引數中,需要傳入事件物件,方式為
$event
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./vue/vue.js"></script>
<style>
img {
height: 300px;
width: 200px;
}
</style>
</head>
<body>
<div id="app">
<h1>事件指令--函式有引數</h1>
<button @click="handleFunc1">不傳引數-函式有引數</button>
<br>
<button @click="handleFunc1(isShow)">傳引數-函式有引數</button>
<br>
<button @click="handleFunc1($event)">傳引數-函式有引數-把事件物件傳入</button>
<br>
<button @click="handleFunc2">多個引數-少傳不加括號</button>
<br>
<button @click="handleFunc2()">多個引數-少傳-加括號event不會自動傳入</button>
<br>
<button @click="handleFunc2(1,2,3,4,5,6,)">多個引數-多傳</button>
<br>
<button @click="handleFunc2(1,$event)">多個引數-event作為第二個引數</button>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
isShow:true
},
methods: {
handleFunc1(event){
//1 如果在事件中觸發函式,沒有傳引數,會自動把 事件物件傳入
console.log(event)
},
handleFunc2(a,b,c){
console.log(a)
console.log(b)
console.log(c)
}
}
})
</script>
</html>
3、屬性指令
(1)v-bind
v-bind 屬性繫結指令,用來動態的設定html的標籤屬性,比如:src、url、title。。。
- 語法:
v-bind:屬性名="表示式"
- 簡寫為
:屬性名="表示式"
示例:
- 控制圖片輪播
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./vue/vue.js"></script>
</head>
<body>
<div id="app">
<button @click="toggleAutoChange">{{ isAutoChanging ? '停止' : '開始' }}自動切換美女圖片</button>
<img :src="currentImage" alt="Beautiful Girl">
</div>
</body>
<script>
var vm = new Vue({
el: "#app",
data: {
isAutoChanging: false,
images: [
"http://img.netbian.com/file/2024/0416/004850qAPxg.jpg",
"http://img.netbian.com/file/2024/0411/0016435MJh0.jpg",
"http://img.netbian.com/file/2024/0409/002601sxcu4.jpg",
"http://img.netbian.com/file/2024/0323/001609whWN7.jpg"
],
currentIndex: 0,
intervalId: null
},
computed: {
currentImage() {
return this.images[this.currentIndex];
}
},
methods: {
toggleAutoChange() {
this.isAutoChanging = !this.isAutoChanging;
if (this.isAutoChanging) {
this.interval = setInterval(() => {
this.currentIndex = (this.currentIndex + 1) % this.images.length;
}, 1000);
} else {
clearInterval(this.interval);
}
}
},
destroyed() {
clearInterval(this.interval);
}
})
</script>
</html>
- 點選按鈕隨機切換圖片
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./vue/vue.js"></script>
</head>
<body>
<div id="d1">
<button @click="handleChange">點我換一張</button>
<br>
<img :src="img_change" alt="">
</div>
</body>
<script>
var vm = new Vue({
el: "#d1",
data: {
img_change: './img/1.jpg', // 圖片是以數字命名的
},
methods: {
handleChange: function () {
this.img_change = `./img/${Math.ceil(Math.random() * this.list1.length)}.jpg`
}
}
})
</script>
</html>
(2)v-bind 對於樣式控制的增強 - 操作class
語法::class=字串/陣列/物件
- class可以繫結的型別有字串、陣列、物件
var vm = new Vue({
el: '#app',
data: {
// 1、繫結的可以是字串形式
str_class: 'background',
// 2、繫結的也可以是陣列形式(常用)
list_class: ['background'],
// 3、物件形式
obj_class: {'background': true, 'fontsize': false},
},
methods: {
handleChangeBack1: function () {
this.str_class = this.str_class + ' fontsize'
},
handleChangeBack2: function () {
// this.list_class.push('fontsize')
this.list_class.pop('background')
},
handleChangeBack3: function () {
this.obj_class.fontSize = true
},
}
(3)v-bind 對於樣式控制的增強 - 操作style
var vm = new Vue({
el: '#app',
data: {
// 1、字串形式
str_style: 'background-color: yellow',
// 2、陣列形式
list_style: [{'background': 'yellow'}],
// 3、物件形式(更合適),一般用物件是用來修改裡面的值會好一點
// obj_style: {'background-color': 'pink', 'font-size': '50px'},
// js的key可以去掉'',到那時中間有 - 的要轉成駝峰
obj_style: {backgroundColor: 'pink', fontSize: '50px'},
},
methods: {
handleChangeBack4: function () {
this.str_style = this.str_style + ';font-size: 60px'
},
handleChangeBack5: function () {
// this.list_style.push({'font-size': '60px'})
this.list_style.push({'margin': 'auto'})
},
handleChangeBack6: function () {
// 物件或者陣列新增加的屬性,vm監控不到就無法實現響應式,於是頁面就沒有發生變化,但是資料已經變了
// this.obj_style ['font-size'] = '90px'
// 但是物件中原來有的屬性,修改是能監控得到的
// this.obj_style ['background-color'] = 'yellowgreen'
//這麼寫的話原來物件沒有的值,就能監控到了--> 如果改了物件沒有影響到頁面--> vm沒有監控到的話--> 就使用Vue.set
Vue.set(this.obj_style, 'font-size', '90px')
}
}
(4)完整示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./vue/vue.js"></script>
<style>
.div1 {
width: 300px;
height: 300px;
}
.div2 {
background-color: pink;
}
.div3 {
font-size: 60px;
}
.div4 {
margin: auto;
}
</style>
</head>
<body>
<div id="app">
<h1>class屬性</h1>
<!-- <div :class="class_str">我</div>-->
<!-- <div :class="class_list">我</div>-->
<div :class="class_obj">我是div</div>
<button @click="handleChange">點選變化</button>
<h2>style屬性</h2>
<div :style="style_obj">我是div</div>
<button @click="handleChange2">點選變化</button>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
//1 class 屬性可以是字串,陣列,物件
class_str: 'div1 div2',
class_list: ['div1', 'div2'], // 類用它多
class_obj: {div1: true, div2: true, div3: true, div4: false}, //
//2 style 屬性可以是字串,陣列,物件
style_str: 'background-color: green;height: 300px;width: 300px',
style_list: [{'background-color': 'green'}, {height: '300px'}, {width: '300px'}],
style_obj: {backgroundColor: 'green', height: '330px', width: '300px'} // 用的多
}, methods: {
handleChange() {
// 1 字串形式
// this.class_str='div1 div2 div3 div4'
// 2 陣列形式,用的多,可以追加,可以刪除--》樣式就變化了
// this.class_list.push('div3') // 陣列.push()-->返回值是 陣列大小
// this.class_list.pop()
// 3 物件形式
this.class_obj.div4 = true
},
handleChange2() {
// 1 字串形式
// this.style_str = 'background-color: green;height: 300px;width: 300px;margin:auto'
// 2 陣列形式
// this.style_list.push({'margin':'auto'})
// 3 物件形式
// 換背景色
// this.style_obj['backgroundColor'] = 'pink'
// 居中
// this.style_obj['margin'] = 'auto' // 物件中原來沒有,後來加進去,就不會觸發響應式
// 使用set解決
Vue.set(this.style_obj,'margin','auto')
}
}
})
</script>
</html>
(5)問題補充
-
如果當你改了物件,或陣列,發現頁面沒有變化,而實際上值真正的被改了,這是為什麼呢?
- 這是因為物件或者陣列新增加的屬性,vm監控不到就無法實現響應式,於是頁面就沒有發生變化,但是資料已經變了
-
解決方案:使用Vue.set
-
Vue.set(object, key, value)
object
: 要向其新增屬性的目標物件。key
: 要新增的屬性的鍵。value
: 要新增的屬性的值
4、條件渲染
(1)v-if v-else-if v-else
- v-if指令,控制元素是否載入。
- v-esle-if/v-else指令不能單獨使用,必須配合v-if一起使用。
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./vue/vue.js"></script>
</head>
<body>
<div id="app">
<h1>條件判斷</h1>
<h2>分數是:{{score}}</h2>
<h3 v-if="score>=90&&score<=100">優秀</h3>
<h3 v-else-if="score>=80&&score<90">良好</h3>
<h3 v-else-if="score>=60&&score<80">及格</h3>
<h3 v-else>不及格</h3>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
score: 80
}
})
</script>
</html>
(2)v-show
- v-show 指令,控制元素的顯示隱藏,元素存在並佔據空間。
- 元素隱藏時,相當於給該元素新增了 CSS 樣式:display:none;
<div v-show="show">hello vue</div>
<button @click="show = !show">changeShow</button>
(3)v-if 和 v-show的區別
v-if和v-show有同樣的效果,不同在於v-if
是重新渲染,而v-show
使用display
屬性來控制顯示隱藏。頻繁切換的話使用v-show
減少渲染帶來的開銷。
5、列表渲染
(1)v-for
v-for 列表渲染指令,基於資料迴圈,多次渲染整個元素---> 陣列、物件、數字。。。
語法:
<div v-for="item in items" :key="item.id">
{{ item.text }}
</div>
v-for="item in items"
:這裡items
是一個陣列或者物件,item
是陣列中的每個元素,或者物件中的每個屬性值,你可以用item
來引用當前遍歷的元素。:key="item.id"
:為了給 Vue 提供一個提示,以便它能跟蹤每個節點的身份,從而重用和重新排序現有元素,你需要為每項提供一個唯一key
屬性。
示例:
如果我們有一個儲存了使用者資訊的陣列:
data: {
users: [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Charlie' }
]
}
我們可以使用 v-for
來迴圈渲染每個使用者的名字:
<div v-for="user in users" :key="user.id">
{{ user.name }}
</div>
這樣就會生成如下 HTML 結構:
<div>Alice</div>
<div>Bob</div>
<div>Charlie</div>
(2)v-for的key的解釋
語法:key屬性 = "唯一標識"
作用:給列表項新增的唯一標識,便於Vue進行列表項的正確排序複用。vue中使用的是虛擬DOM,會和原生的DOM進行比較,然後進行資料的更新,提高資料的重新整理速度(虛擬DOM用了diff演算法)。[想深入瞭解的可以點選參考此文](vue 虛擬 DOM_vdom樹-CSDN部落格)
如果你不給 v-for
渲染的每個項新增 key
,Vue 會發出警告,但並不會導致程式崩潰。沒有為 v-for
新增 key
會導致 Vue 難以跟蹤每個項的變化,可能會影響列表的效能和導致一些意外行為,特別是在涉及列表項的更新、刪除和重新排序時。
注意點:
- key的值只能是字串或者數字型別
- key的值必須具有唯一性
- 推薦使用id作為key(唯一),不推薦使用index作為key(會變化,不對應)
(3)v-for可以迴圈的變數
在 Vue.js 中,v-for
指令可以用於迴圈遍歷多種資料型別,包括:
-
陣列:你可以直接在
v-for
中使用陣列,迴圈渲染陣列中的每一項。<ul> <li v-for="item in names" :key="item.id">{{ item.name }}</li> </ul>
data: { names: ['張三', '彭于晏', 'quan', 'xiao'], },
-
物件:你也可以在
v-for
中使用物件,迴圈渲染物件的屬性值。<ul> <li v-for="(value, key) in object" :key="key">{{ key }}: {{ value }}</li> </ul>
data: { userinfo: {name: 'xiao', age: 18, hobby: 'play'}, },
-
數字:你可以使用整數來指定迴圈的次數。
<ul> <li v-for="n in 10" :key="n">{{ n }}</li> </ul>
-
字串:你可以在
v-for
中使用 字串。<ul> <li v-for="value in s" :key="value">{{value}}</li> </ul>
data: { s: 'xiao is very handsome' },
6、資料雙向繫結
(1)v-model
作用:針對 input 標籤,在頁面中輸入值,js中有對應變數,雙向資料繫結,可以快速獲取或設定表單元素內容
語法:v-model="變數"
- 資料單向繫結:變數變了頁面也會變;但是頁面變,變數不會變
- 資料雙向繫結:變數變化,頁面會自動更新;檢視變化,資料也會自動更新
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./vue/vue.js"></script>
</head>
<body>
<div id="app">
<h1>資料單向繫結</h1>
<input type="text" :value="name">
<h1>資料雙向繫結</h1>
<input type="text" v-model="name2">
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
name: 'xiao',
name2:'sss'
}
})
</script>
</html>
(2)v-model 應用於其他表單元素
在 Vue.js 中,v-model
指令通常用於在表單元素上建立雙向資料繫結。這意味著當表單元素的值發生變化時,與之關聯的 Vue 例項的資料也會相應地更新,反之亦然。雖然 v-model
最常用於 <input>
元素,但它也可以應用於其他表單元素,如 <select>
和 <textarea>
。
例如,你可以在 <select>
元素上使用 v-model
來建立雙向資料繫結,示例如下:
<select v-model="selectedOption">
<option value="option1">Option 1</option>
<option value="option2">Option 2</option>
<option value="option3">Option 3</option>
</select>
在上面的示例中,selectedOption
是 Vue 例項中的一個資料屬性,它將與 <select>
元素的選定選項進行雙向繫結。當使用者選擇不同的選項時,selectedOption
的值將更新,反之亦然。
同樣地,你也可以在 <textarea>
元素上使用 v-model
來實現雙向資料繫結,例如:
<textarea v-model="message" placeholder="Enter your message"></textarea>
在這個示例中,message
是 Vue 例項中的一個資料屬性,它將與 <textarea>
元素的內容進行雙向繫結。當使用者在文字區域中輸入內容時,message
的值將相應地更新,反之亦然。
總之,v-model
可以應用於不同型別的表單元素,以實現雙向資料繫結,使得資料的更新能夠與使用者介面的互動實時同步。
三、事件處理
1、input 標籤的事件處理
事件 | 說明 |
---|---|
input | 當輸入框進行輸入的時候 觸發的事件 |
change | 當元素的值發生改變時 觸發的事件 |
blur | 當輸入框失去焦點的時候 觸發的事件 |
focus | 當輸入框獲取焦點的時候 觸發的事件 |
change
和blur
最本質的區別:
- 如果輸入框為空,失去焦點後,change不會觸發,但是blur會觸發
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./vue/vue.js"></script>
</head>
<body>
<div id="app">
<h1>input事件</h1>
<input type="text" v-model="name1" @input="handleInput">-->{{name1}}
<h1>change事件</h1>
<input type="text" v-model="name2" @change="handleChange">-->{{name2}}
<h1>blur事件</h1>
<input type="text" v-model="name3" @blur="handleBlur">-->{{name3}}
<h1>focus事件</h1>
<input type="text" v-model="name4" @focus="handleFocus">-->{{name4}}
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
name1:'',
name2:'',
name3:'',
name4:'asdfasd',
},
methods:{
handleInput(event){
console.log(event.data)
},
handleChange(){
console.log('handleChange')
},
handleBlur(){
console.log('handleBlur')
},
handleFocus(){
console.log('Focus')
this.name4=''
}
}
})
</script>
</html>
2、過濾案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./Vue/vue.js"></script>
</head>
<body>
<div id="app">
<h2>過濾案例</h2>
<input type="text" v-model="search" @input="handleSearch">
<ul>
<li v-for="item in newDataList">{{item}}</li>
</ul>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
search: '',
dataList: ['a', 'ac', 'bdsfc', 'ffaw', 'casdad', 'atnefk', 'fwead', 'fewfe'],
newDataList: ['a', 'ac', 'bdsfc', 'ffaw', 'casdad', 'atnefk', 'fwead', 'fewfe']
},
methods: {
// 1、笨辦法
handleSearch(event) {
console.log(this) // 這個this是vue例項
var _this = this
// 過濾dataList中每一個是否包含使用者輸入的 this.search
this.newDataList = this.dataList.filter(function (item) {
console.log(_this) // this是window的物件,要換成_this
return item.indexOf(_this.search) >= 0
})
},
// // 2、箭頭函式的寫法 把function去掉,在形參括號和函式體大括號之間加個 =>
// handleSearch(event) {
// this.newDataList = this.dataList.filter(item => item.indexOf(this.search) >= 0)
// },
}
})
</script>
</html>
在我們構造邏輯時存在兩個問題
- 函式里面的this指向的是window物件---> 在外部定義一個_this=this就可以了
- 改資料是在dataList上改的,回退搜尋的關鍵字時就無法顯示了---> 再寫一個newDataList,在這上操作就可以了
3、補充 陣列的過濾和判斷子字串是否在字串中
// 補充1 陣列的過濾
var dataList = ['a', 'ac', 'bdsfc', 'ffaw', 'casdad', 'atnefk', 'fwead', 'fewfe']
// 1、過濾掉所有
var newDataList = dataList.filter(function (item){
return true
// 2、只保留長度大於2的
var newDataList = dataList.filter(function (item){
if (item.length > 2){
return true
}else{
return false
}
})
console.log(newDataList)
// 3、只保留包含at的
var search = 'at'
var newDataList = dataList.filter(function (item){
return item.indexOf(search) >= 0
})
console.log(newDataList)
// 補充2 判斷子字串是否在字串中
var search = 'at'
var s = 'attr'
var res = s.indexOf(search) // 字串在字串的哪個位置
console.log(res)
四、箭頭函式
箭頭函式(Arrow Functions)是 ES6(ECMAScript 2015)引入的一種新的函式定義方式,它提供了一種更簡潔的語法來定義函式。與傳統的函式定義方式相比,箭頭函式具有以下特點和優勢:
-
簡潔的語法:箭頭函式可以讓你用更短的程式碼來定義函式,尤其適合於簡單的函式表示式。
-
更簡潔的語法:當函式只有一個引數時,你可以省略引數周圍的括號。當函式體只有一條語句時,你可以省略花括號和
return
關鍵字。 -
繫結
this
:箭頭函式的this
值在函式建立時就已經確定,並且在整個函式生命週期內保持不變,它不會被函式的呼叫方式所影響。這解決了傳統函式中this
值難以理解和控制的問題,特別適合於在回撥函式中使用。 -
不繫結
arguments
物件:箭頭函式不繫結arguments
物件,而是繼承父級函式的arguments
物件。如果你需要訪問函式的引數,可以使用 rest 引數或者透過...args
來獲取所有引數。 -
不能作為建構函式:箭頭函式不能用作建構函式,也就是不能透過
new
關鍵字來呼叫,因為它沒有自己的this
值。 -
沒有
arguments
物件:箭頭函式沒有自己的arguments
物件,如果需要訪問函式的引數,可以使用 rest 引數或者透過...args
來獲取所有引數。
下面是一些箭頭函式的示例:
// 正常的匿名函式
var f = function (name) {
console.log(name)
}
f('xiao')
// 箭頭函式寫法 把function去掉,在形參括號和函式體大括號之間加個 =>
// 1、無引數無返回值
var f = () => {
console.log('fff')
}
f()
// 2、有一個引數無返回值
var f = (name) =>{
console.log(name)
}
f('xiao')
// 如果只有一個引數可以簡寫成 但是如果有多個那麼就必須加在括號裡
var f = name =>{
console.log(name)
}
f('xiao')
// 3、有多個引數無返回值(箭頭函式的返回值是物件時,需要用括號包裹)
var f2 = (name,age) => {
console.log(name,age)
}
f2()
// 4、有一個引數有一個返回值
var f = name =>{
return name+'nb'
}
var res = f('xiao')
console.log(res)
// 如果沒有其他程式碼可以簡寫成
var f = name => name + 'nnb'
var res = f('xiao')
console.log(res)
重點:箭頭函式內部,沒有自己this,箭頭函式內部用this ==> 就是上一個作用域的this
五、指令的修飾符
1、事件修飾符
事件修飾符 | 釋義 |
---|---|
.stop | 只處理自己的事件,父控制元件冒泡的事件不處理(阻止事件冒泡),寫在子標籤上 |
.self | 只處理自己的事件,子控制元件冒泡的事件不處理,寫在父標籤上 |
.prevent | 阻止a連結的跳轉 |
.once | 事件只會觸發一次(適用於抽獎頁面) |
使用修飾符時,使用順序很重要;相應的程式碼會以同樣的順序產生
- 用
v-on:click.prevent.self
會阻止所有的點選- 而
v-on:click.self.prevent
只會阻止對元素自身的點選
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./Vue/vue.js"></script>
</head>
<body>
<div id="app">
<h1>事件修飾符</h1>
<h2>.once:只能點選一次</h2>
<button @click.once="handleClick">點我有驚喜</button>
<h2>.prevent:阻止a的跳轉</h2>
<a href="https://www.baidu.com" @click.prevent="handleA">點我看美女</a>
<h2>.stop:只處理自己的事件,父控制元件冒泡的事件不處理(阻止事件冒泡)</h2>
<h3>寫在子標籤上</h3>
<ul @click="handleUl">
<li @click.stop="handleLi">li01</li>
<li>li02</li>
</ul>
<h2>.self:只處理自己的事件,子控制元件冒泡的事件不處理(阻止事件冒泡)</h2>
<h3>寫在父標籤上</h3>
<ul @click.self="handleUl">
<li @click="handleLi">li01</li>
<li>li02</li>
</ul>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {},
methods: {
handleClick() {
alert('我是彈窗')
},
handleA() {
console.log('點過了')
location.href = 'https://www.cnblogs.com'
},
handleUl() {
console.log('我是ul')
},
handleLi() {
console.log('我是li')
},
}
})
</script>
</html>
2、按鍵修飾符
按鍵修飾符是 Vue.js 中用於監聽鍵盤事件的一種方式。它們可以讓你在處理鍵盤事件時更加靈活和方便。是一些常用的按鍵修飾符及其作用:
-
.enter
:監聽 Enter 鍵。 -
.tab
:監聽 Tab 鍵。 -
.delete
或.backspace
:監聽刪除鍵。 -
.esc
:監聽 Esc 鍵。 -
.space
:監聽空格鍵。 -
.up
:監聽上箭頭鍵。 -
.down
:監聽下箭頭鍵。 -
.left
:監聽左箭頭鍵。 -
.right
:監聽右箭頭鍵。 -
.ctrl
:監聽 Ctrl 鍵。 -
.alt
:監聽 Alt 鍵。 -
.shift
:監聽 Shift 鍵。
這些按鍵修飾符可以與事件監聽指令(如 @keydown
、@keyup
、@keypress
)一起使用,以便在特定的鍵被按下時觸發相應的事件處理函式。例如:
<input @keydown.enter="submitForm">
<input @keyup.tab="focusNextInput">
<input @keypress.space="playPauseVideo">
<input @keyup.13="focusNextInput">
# @keyup.Keycode也能實現
六、表單控制
1、checkbox選中
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>checkbox</title>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>
<div id="app">
<h3>使用者登入示例</h3>
<p>使用者名稱:<input type="text" v-model="username"></p>
<p>密碼:<input type="password" v-model="pwd"></p>
<p>是否記住密碼:<input type="checkbox" v-model="rem"></p>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
username: '',
pwd: '',
rem: '', // 只做選中或者不選中判斷,使用布林
},
})
</script>
</html>
2、radio單選
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>單選</title>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>
<div id="app">
<p>性別:
<input type="radio" v-model="gender" value="男">男
<input type="radio" v-model="gender" value="女">女
<input type="radio" v-model="gender" value="保密">保密
</p>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
gender: ''
},
})
</script>
</html>
3、checkbox多選
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>多選</title>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>
<div id="app">
<p>愛好:
<input type="checkbox" v-model="hobbys" value="足球">足球
<input type="checkbox" v-model="hobbys" value="籃球">籃球
<input type="checkbox" v-model="hobbys" value="乒乓球">乒乓球
</p>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
hobbys: [], // 放多個元素需要使用陣列
},
})
</script>
</html>
4、購物車案例 - 結算
- 選中商品並自動計算總價 數量 * 價格
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./Vue/vue.js"></script>
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.0/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.0/js/bootstrap.min.js"></script>
</head>
<body>
<div id="app">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<h1 class="text-center">購物車</h1>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th scope="col">商品id</th>
<th scope="col">商品名字</th>
<th scope="col">商品數量</th>
<th scope="col">商品價格</th>
<th scope="col">操作</th>
</tr>
</thead>
<tbody>
<tr v-for="good in goodsList">
<td>{{good.id}}</td>
<td>{{good.name}}</td>
<td>{{good.count}}</td>
<td>{{good.price}}</td>
<td><input type="checkbox" v-model="checkGoodList" :value="good"></td>
</tr>
</tbody>
</table>
<hr>
<h3>選中的商品:{{checkGoodList}}</h3>
<!-- 插值插入的方法的返回值-->
<h3>總價格:{{getPrice()}}</h3>
</div>
</div>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
goodsList: [
{id: 1, name: '鍵盤', count: 2, price: 133},
{id: 2, name: '滑鼠', count: 10, price: 12},
{id: 3, name: '揹包', count: 34, price: 34},
{id: 4, name: '衝鋒衣', count: 3, price: 67},
{id: 5, name: '顯示器', count: 9, price: 89}
],
checkGoodList: []
},
methods: {
getPrice() {
// 計算選中的總價格
var total = 0
// 迴圈選中的,計算總價格this.checkGoodList
for (var item of this.checkGoodList) {
console.log(item)
total += item.price * item.count
}
return total
}
}
})
</script>
</html>
5、購物車案例 - 全選/全不選
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./Vue/vue.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.0/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.0/js/bootstrap.min.js"></script>
</head>
<body>
<div id="app">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<h1 class="text-center">購物車</h1>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th scope="col">商品id</th>
<th scope="col">商品名字</th>
<th scope="col">商品數量</th>
<th scope="col">商品價格</th>
<th scope="col">全選/全不選 <input type="checkbox" v-model="checkAll" @change="handleCheckAll"></th>
</tr>
</thead>
<tbody>
<tr v-for="good in goodsList">
<td>{{good.id}}</td>
<td>{{good.name}}</td>
<td>{{good.count}}</td>
<td>{{good.price}}</td>
<td><input type="checkbox" v-model="checkGoodList" :value="good" @change="handleCheckOne"></td>
</tr>
</tbody>
</table>
<hr>
<h3>選中的商品:{{checkGoodList}}</h3>
<h3>是否全選:{{checkAll}}</h3>
<!-- 插值插入的方法的返回值-->
<h3>總價格:{{getPrice()}}</h3>
</div>
</div>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
goodsList: [
{id: 1, name: '鍵盤', count: 2, price: 133},
{id: 2, name: '滑鼠', count: 10, price: 12},
{id: 3, name: '揹包', count: 34, price: 34},
{id: 4, name: '衝鋒衣', count: 3, price: 67},
{id: 5, name: '顯示器', count: 9, price: 89}
],
checkGoodList: [],
checkAll: false,
},
methods: {
getPrice() {
// 計算選中的總價格
var total = 0
// 迴圈選中的,計算總價格this.checkGoodList
for (var item of this.checkGoodList) {
console.log(item)
total += item.price * item.count
}
return total
},
handleCheckAll() {
if (this.checkAll) {
// 全選了
this.checkGoodList = this.goodsList
} else {
// 全不選
this.checkGoodList = []
}
},
handleCheckOne() {
// 如果checkGoodList等於商品總長度,說明許可權了,讓checkAll等於true
if (this.checkGoodList.length == this.goodsList.length) {
this.checkAll = true
} else {
// 只要長度不等,都是false
this.checkAll = false
}
},
}
})
</script>
</html>
6、購物車案例 - 數量加減
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./Vue/vue.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.0/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.0/js/bootstrap.min.js"></script>
</head>
<body>
<div id="app">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<h1 class="text-center">購物車</h1>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th scope="col">商品id</th>
<th scope="col">商品名字</th>
<th scope="col">商品數量</th>
<th scope="col">商品價格</th>
<th scope="col">全選/全不選 <input type="checkbox" v-model="checkAll" @change="handleCheckAll"></th>
</tr>
</thead>
<tbody>
<tr v-for="good in goodsList">
<td>{{good.id}}</td>
<td>{{good.name}}</td>
<td><span class="btn" @click="handleAdd(good)">+</span>
<input type="text" v-model="good.count">
<span class="btn" @click="handleMin(good)">-</span></td>
<td>{{good.price}}</td>
<td><input type="checkbox" v-model="checkGoodList" :value="good" @change="handleCheckOne"></td>
</tr>
</tbody>
</table>
<hr>
<h3>選中的商品:{{checkGoodList}}</h3>
<h3>是否全選:{{checkAll}}</h3>
<!-- 插值插入的方法的返回值-->
<h3>總價格:{{getPrice()}}</h3>
</div>
</div>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
goodsList: [
{id: 1, name: '鍵盤', count: 2, price: 133},
{id: 2, name: '滑鼠', count: 10, price: 12},
{id: 3, name: '揹包', count: 34, price: 34},
{id: 4, name: '衝鋒衣', count: 3, price: 67},
{id: 5, name: '顯示器', count: 9, price: 89}
],
checkGoodList: [],
checkAll: false,
},
methods: {
getPrice() {
// 計算選中的總價格
var total = 0
// 迴圈選中的,計算總價格this.checkGoodList
for (var item of this.checkGoodList) {
console.log(item)
total += item.price * item.count
}
return total
},
handleCheckAll() {
if (this.checkAll) {
// 全選了
this.checkGoodList = this.goodsList
} else {
// 全不選
this.checkGoodList = []
}
},
handleCheckOne() {
// 如果checkGoodList等於商品總長度,說明許可權了,讓checkAll等於true
if (this.checkGoodList.length == this.goodsList.length) {
this.checkAll = true
} else {
// 只要長度不等,都是false
this.checkAll = false
}
},
handleAdd(good) { // 傳的是物件 不是數字或者id
good.count++
},
handleMin(good) {
if (good.count > 1) {
good.count--
} else {
alert('不能再減了')
}
},
}
})
</script>
</html>
七、v-model進階用法
屬性 | 說明 |
---|---|
lazy | 等待input框的資料繫結失去焦點之後再變化 |
number | 數字開頭,只保留數字,後面的字母不保留;字母開頭,都保留 |
trim | 去除首尾的空格 |
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>v-model 之 lazy、number、trim</title>
<script src="./Vue/vue.js"></script>
</head>
<body>
<div id="box">
<input type="text" v-model="myText1" placeholder="normal"> {{myText1}}
<br>
<input type="text" v-model.lazy="myText2" placeholder="lazy"> {{myText2}}
<br>
<input type="text" v-model.number="myText3" placeholder="number"> {{myText3}}
<br>
<input type="text" v-model.trim="myText4" placeholder="trim"> {{myText4}}
</div>
</body>
<script>
var vm = new Vue({
el: '#box',
data: {
myText1: '',
myText2: '',
myText3: '',
myText4: '',
},
})
</script>
</html>
八、前後端互動的三種方式
思維邏輯:前後端要打通----> 從前端傳送ajax---> 核心:使用js傳送http請求,接收返回
1、使用 jQuery 的 Ajax 方法
- jQuery 提供了方便的
$.ajax()
方法,封裝了原生的 XMLHttpRequest 物件,簡化了開發者的操作流程。 - 它支援跨瀏覽器相容性,並提供了豐富的功能選項,如設定請求型別、請求頭、處理錯誤等。
- 然而,由於現代前端框架(如 Vue.js)一般不推薦使用 jQuery,因此在與這些框架結合使用時可能不太適合。
後端
# # flask框架構建後端入口
from flask import Flask, jsonify
app = Flask(__name__)
@app.route('/userinfo', methods=['GET'])
def userinfo():
res = jsonify({'username': 'xiao', 'age': 13})
res.headers = {'Access-Control-Allow-Origin':'*'}
return res
if __name__ == '__main__':
app.run()
前端
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./Vue/vue.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.0/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.0/js/bootstrap.min.js"></script>
</head>
<body>
<div id="app">
<h1>與後端互動</h1>
<button @click="handleLoad">載入使用者資訊</button>
<p>使用者名稱:{{username}}</p>
<p>年齡:{{age}}</p>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
username: '',
age: '',
},
methods: {
handleLoad() {
// 後端傳送請求,拿到資料,賦值給username和age 頁面就有了
// 1.傳送請求方式1:使用jq的ajax
$.ajax({
url: 'http://127.0.0.1:5000/userinfo',
method: 'get',
success: data => {
// 會導致CORS policy 跨域問題---> 解決方案:在後端響應頭裡加入:Access-Control-Allow-Origin即可
// console.log(data)
data = JSON.stringify(data)
this.username = data.username
this.age = data.age
}
})
}
}
})
</script>
</html>
2、使用原生js的fetch傳送ajax請求
- 這是一種傳統的方式,透過使用 JavaScript 的 XMLHttpRequest 物件來傳送和接收資料。
- 開發者需要手動處理請求和響應的各個階段,包括請求引數的拼裝、請求頭的設定、監聽響應事件等。
- 儘管這種方法具有靈活性,但是編寫和維護複雜度較高,需要考慮不同瀏覽器的相容性問題。
<script>
var vm = new Vue({
el: '#app',
data: {
username: '',
age: '',
},
methods: {
handleLoad() {
// 後端傳送請求,拿到資料,賦值給username和age 頁面就有了
// 1.傳送請求方式2:使用原生js的fetch傳送ajax請求
fetch('http://127.0.0.1:5000/userinfo').then(response => {
return response.json();
}).then(data => {
this.username = data.username
this.age = data.age
});
}
}
})
</script>
3、使用第三方庫(如 Axios 或 Fetch)
- 第三方庫如 Axios 和 Fetch 提供更簡潔、易用且功能強大的方式來傳送 Ajax 請求。它們以 Promise 或 async/await 為基礎,使得非同步請求程式碼更加清晰和易於維護。
- Axios 是一個流行的第三方庫,廣泛應用於前端專案中。同時,原生的 Fetch API 也是一種現代的標準方式,但需要注意相容性問題
- axios官網:http://www.axios-js.com/
<script>
var vm = new Vue({
el: '#app',
data: {
username: '',
age: '',
},
methods: {
handleLoad() {
// 後端傳送請求,拿到資料,賦值給username和age 頁面就有了
// 1.傳送請求方式3:使用axios傳送請求
axios.get('http://127.0.0.1:5000/userinfo')
.then(res => {
console.log(res.data) //真正的響應體資料是在res.data中
this.username = res.data.username
this.age = res.data.age
})
.catch(error => {
console.log(error)
});
}
}
})
</script>
九、補充
1、JS中的for迴圈操作
(1)基於索引的迴圈--> 最基本的
for (var i = 0; i < 10; i++){
console.log(i)
}
(2)in 迴圈
var names = ['xiao','quan','zha'] // 陣列
for (items in names) // 迴圈索引
console.log(items)
console.log(names[items])
}
var userinfo = {'name':'xiao','age':13} // 物件
for (items in userinfo){ // 迴圈的是key
console.log(userinfo[items])
}
var s = 'xiao' // 字串
for(items in s){ // 迴圈的是索引
console.log(s[items])
}
(3)of迴圈
var names = ['xiao','quan','zha'] // 陣列
for (items of names) // 迴圈 具體值
console.log(items)
}
var s = 'xiao' // 字串
for (items of s) { // 迴圈具體值
console.log(items)
}
var userinfo = {'name':'xiao','age':13} // of不能迴圈物件
for (items of userinfo){
console.log(items)
}
for (items of 10) { // of不能迴圈數字
console.log(items)
}
(4)陣列的forEach方法,實現迴圈
var names = ['xiao','quan','zha']
names.forEach(function (value,index){
console.log(index)
console.log(value)
})
(5)jquery的each迴圈
var names = ['xiao','quan','zha'] // 陣列
$.each(names,function (value,index){
console.log(value)
console.log(index)
})
var userinfo = {'name':'xiao','age':13} // 物件
$.each(userinfo,function (key,value){
console.log(key)
console.log(value)
})
var s = 'xiao' // 字串不行
$.each(s,function (index,value){
console.log(index)
console.log(value)
})
2、vm物件介紹
<body>
<div id="app">
<!--插值語法-->
<h1>{{name}}</h1>
<br>
<h2> 方法中的 this 物件 </h2>
<button @click="handleClick1">點我</button>
</div>
</body>
<script>
<!-- 將建立的Vue物件封裝到 vm 變數裡面。控制檯全域性可以透過 vm.name 取值 -->
// 寫在 data 或 methods 中的屬性或方法,可以從 vm 中直接 透過 vm.屬性取值
// methods的函式中,如果想使用data或methods中的屬性,直接this.名字 就可以了
var vm = new Vue({
el: "#app",
data: {
name: "dream",
},
methods: {
handleClick1() {
console.log(this) // this 就是當前的 例項的 vm 物件
// xr {_uid: 0, _isVue: true, __v_skip: true, _scope: t, $options: {…}, …}
}
},
})
</script>
vm
是一個Vue例項物件的變數名。
- Vue例項物件是Vue.js框架中最核心的概念之一,它扮演著連線資料和檢視的橋樑作用。
- 資料繫結:
- 透過將
vm
物件傳遞給模板語法,可以實現資料的動態渲染。- 例如,在模板中使用
{{name}}
的插值語法,name
會被vm
物件中的data
屬性中的name
所替換,從而實現了name
資料的動態展示。- 方法呼叫:
- 在
vm
物件的methods
屬性中定義的方法,可以透過模板中的事件繫結(如@click="handleClick1"
)來進行呼叫。- 在這個例子中,當點選按鈕時,會觸發
handleClick1
方法,輸出this
物件。- 在方法中,
this
指向當前的Vue例項物件vm
,透過this
可以訪問到vm
例項中的屬性和方法。- 總結起來,
vm
物件是Vue例項物件的引用,透過這個物件可以訪問和操作Vue例項的資料和方法。
- 它的作用是管理資料和行為,實現資料的雙向繫結,以及處理使用者互動和響應。
- 在模板中可以透過
vm
物件來訪問資料,並觸發相應的方法來實現業務邏輯的處理。
十、 小練習
- 要求:點選按鈕,載入最新電影
- 前端:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./vue/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="app">
<h1>點選按鈕,獲取資料,顯示</h1>
<button @click="handleLoad">獲取電影資訊</button>
<div v-for="item in filmList">
<p>電影名:{{item.name}}</p>
<p>介紹:{{item.synopsis}}</p>
<p>圖片: <img :src="item.poster" alt="" height="300px" width="150px"></p>
<hr>
</div>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
filmList: [],
},
methods: {
handleLoad() {
axios.get('http://127.0.0.1:5000/films')
.then(res => {
this.filmList=res.data.result
})
.catch(error => {
console.log(error);
});
}
}
})
</script>
</html>
- 後端:
# pip install flask
from flask import Flask, jsonify
import json
app = Flask(__name__)
@app.route('/films')
def films():
with open('./fiml.json', 'r', encoding='utf-8') as f:
res_dict = json.load(f)
res = jsonify(res_dict)
res.headers['Access-Control-Allow-Origin'] = '*'
return res
if __name__ == '__main__':
app.run()