目錄
- <<回到導覽
- vue基礎知識
- 1.1.創建一個vue實例
- 1.2.vue基礎指令
- 1.2.1.v-bind
- 1.2.2.v-model
- 1.2.3.常用事件
- 1.2.4.指令修飾符
- 1.3.計算屬性
- 1.3.1.計算屬性的完整寫法
- 1.3.2.【案例】成績
- 1.4.watch
- 1.4.1.watch屬性
- 1.4.2.翻譯業務實現
- 1.4.3.watch屬性的完整寫法
- 1.4.4.【案例】水果購物車
- 1.5.生命周期
- 1.5.1.【應用】初始化渲染
- 1.5.2.【應用】獲取焦點
<<回到導覽
vue基礎知識
mvvm模型
響應式數據,一旦數據變化,視圖效果跟著變化
1.1.創建一個vue實例
-
代碼:
<!-- 1.準備容器 --><div id="app">{{msg}}{{age-1}}</div><!-- 2.引入開發版本的包 --><script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script><script>// 3.創建實例const app = new Vue({// 4.添加配置項el: '#app',// el => 掛載data: {msg: 'hello',age: 18}})
-
插值表達式
用
{{}}
包裹變量名,將表達式插值,如上面{{msg}}和{{age-1}},瀏覽器會分別渲染值hello和 17 -
響應式特性
響應式:數據變化,視圖自動更新,當我們修改數據后,vue會監聽到數據修改,從而改變視圖
data里的數據會添加到實例身上,以上面實例為例子,我們可以通過app訪問屬性msg和age
)
1.2.vue基礎指令
-
一些基礎指令:
<!-- 1.v-html => innerHtml --><div v-html="msg2"></div><!-- 2.v-show => 通過display來顯示和隱藏 => 一般用于交互頻繁 --><div v-show="flag3">333</div><!-- 3.v-if => 條件渲染 => 用于交互不頻繁 --><div v-if="flag3">444</div><!-- 4.v-if、 v-else-if v-else => 條件渲染 --><!-- 5.v-on 注冊事件 每點擊一下,count -1 -->v-on:click="count--" => @click="count--"
-
methods屬性(用于存放事件方法)
<!-- 點擊按鈕,調用methods方法,彈出提示框 --> <button @click="methods">methods</button><!-- js --> methods: {methods() {alert('methods')} }
-
7.v-for(基于數組循環,多次渲染整個元素,
v-for="(item,index) in arr
)<!-- 編號arr中的項,并且列舉 --> <li v-for="(item, index) in list">{{index+1}}.{{item}}</li>
v-for中的key:給元素添加唯一標識,用于列表項的正確排序(key值必須具有唯一性,不推薦以index作為key值)
1.2.1.v-bind
-
可省略成
:
,用于實現熟悉的響應式<!-- imgUrl為配置項中data中的數據 --><img v-bind:src="imgUrl"><!-- 等價為 --><img :src="imgUrl" alt="">
v-bind可以操作class
-
傳對象
應用場景:一個類名,來回切換(tab欄)
<!-- size、pink、green都為類名 --> <div class="box" :class="{size:true,pink:false,green:true}">123</div>
-
-
傳數組
應用場景:批量添加或者刪除類
<div class="box" :class="['pink','size']">223</div>
-
style行內樣式
應用場景:非常方便地控制某個樣式屬性的變化(進度條),數值拼接單位
<div class="box" :style="{'background-color':'green'}"></div>
1.2.2.v-model
v-modal 可以讓數據和視圖雙向綁定,快速獲取或者設置表單元素內容
<!-- input框值變化,data中對應的數據也會變化 -->
<input type="text" v-model="username"><br>
對于不同的表單元素, v-modal 的綁定也有所不同
表單元素 | 綁定 | 備注 |
---|---|---|
輸入框 | value | text |
文本域 | value | textarea |
復選框 | checked | checkbox |
單選框 | checked | radio,name將單選框關聯 |
下拉菜單 | selected元素中,option選項的value值 | selected、option |
1.2.3.常用事件
事件 | 觸發 |
---|---|
@click | 單擊觸發 |
v-model | 常用于綁定input事件 |
@submit | 表單提交觸發 |
@mouseover | 鼠標懸停觸發 |
@mouseout | 鼠標移開觸發 |
-
焦點事件
事件 觸發 @focus
元素獲得焦點 @blur
元素失去焦點 -
表單事件
事件 觸發 @reset
點擊重置按鈕時 @submit
點擊提交按鈕 -
鍵盤事件
事件 觸發 @keydown
按下任意按鍵。 @keypress
除 Shift、Fn、CapsLock 外的任意鍵被按住。 @keyup
按鍵彈起
1.2.4.指令修飾符
- 按鍵修飾符
- @keyup.enter:鍵盤回車監聽
- v-model修飾符
- v-model.trim:去首尾空格
- v-model.number:轉數字
- 事件修飾符
- 事件名.stop:阻止冒泡
- 事件名.prevent:阻止默認行為
- 其他
- once:事件只觸發一次
1.3.計算屬性
計算屬性會對計算結果緩存,依賴項變了,會自動重新計算,并再次緩存,緩存可以被直接讀取
(性能高)
1.methods屬性
<p>禮物總數:{{ total() }} 個</p>
<p>禮物總數:{{ total() }} 個</p>
<p>禮物總數:{{ total() }} 個</p><!-- js中 -->
data: {list: [{ id: 1, name: '籃球', num: 1 },{ id: 2, name: '玩具', num: 2 },{ id: 3, name: '鉛筆', num: 5 },]
},
methods: {total() {console.log("執行了一次。");return this.list.reduce((sum, item) => sum + item.num, 0)}
}
- 控制臺會
打印三次
"執行了一次。"
- computed屬性
<!-- 計算屬性依舊是屬性,不用加() -->
<p>禮物總數:{{ total }} 個</p>
<p>禮物總數:{{ total }} 個</p>
<p>禮物總數:{{ total }} 個</p><!-- js中 -->
computed: {封裝一段對于數據的處理,求得一個結果total() {console.log("執行了一次。");return this.list.reduce((sum, item) => sum + item.num, 0)}
}
- 控制臺會
打印一次
"執行了一次。"
1.3.1.計算屬性的完整寫法
計算屬性默認只能訪問,不能修改,如果要修改,需要計算屬性的完整寫法
computed:{fullName(){return this.firstName + this.lastName}
}
以上寫法等價于
computed:{fullName:{get(){return this.firstName + this.lastName}}
}
- 上面寫法只能通過監聽firstName和lastName,來動態改變fullName的值
- 現在假設fullName會變化,我們fullName變化時,有對firstName和lastName進行拆分的需求,就需要計算屬性的完整寫法
computed:{fullName:{// 監聽firstName和lastName,動態改變fullName的值get(){return this.firstName + this.lastName},// 監聽fullName,動態改變firstName和lastName的值set(value){this.firstName = value.slice(0,1))this.lastName = value.slice(1)}}
}
從上面可以看出,set方法的形參value為fullName的值
當然除了改變firstName和lastName的值,還可以做出其他的一些操作,這里就不一一例舉了
1.3.2.【案例】成績
- 成品圖
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><link rel="stylesheet" href="./styles/index.css" /><title>Document</title>
</head><body><div id="app" class="score-case"><div class="table"><table><thead><tr><th>編號</th><th>科目</th><th>成績</th><th>操作</th></tr></thead><tbody v-if="list.length>0"><tr v-for="(item,index) in list" :key="item.id"><td>{{item.id}}</td><td>{{item.subject}}</td><td :class="{red:item.score<60}">{{item.score}}</td><td><a href="#" @click="del(item.id)">刪除</a></td></tr></tbody><tbody v-else><tr><td colspan="5"><span class="none">暫無數據</span></td></tr></tbody><tfoot><tr><td colspan="5"><span>總分:{{total}}</span><span style="margin-left: 50px">平均分:{{average}}</span></td></tr></tfoot></table></div><div class="form"><div class="form-item"><div class="label">科目:</div><div class="input"><input type="text" placeholder="請輸入科目" v-model="subject" /></div></div><div class="form-item"><div class="label">分數:</div><div class="input"><input type="text" placeholder="請輸入分數" v-model="score" /></div></div><div class="form-item"><div class="label"></div><div class="input"><button class="submit" @click="add">添加</button></div></div></div></div><script src="../../vue/vue.js"></script><script>const app = new Vue({el: '#app',data: {list: [{ id: 1, subject: '語文', score: 20 },{ id: 2, subject: '數學', score: 99 },{ id: 3, subject: '英語', score: 70 },],subject: '',score: ''},methods: {del(id) {this.list = this.list.filter(item => item.id !== id)},add() {if (!this.subject || !this.score) {alert('沒有輸入科目或者分數!!!')} else {// 往數組前面加this.list.unshift({// 以時間戳作為id,來設置keyid: +new Date(),subject: this.subject,score: this.score})this.subject = ''this.score = ''}}},computed: {total() {return this.list.reduce((sum, item) => sum + item.score, 0)},average() {if (this.list.length == 0) {return 0} else {return this.total / (this.list.length)}}}})</script>
</body></html>
重要知識點
-
刪除邏輯
del(id) {this.list = this.list.filter(item => item.id !== id)},
- 通過點擊觸發del方法,傳入id
- 通過filter,從list過濾出和被點擊項的id不同的id項,重新賦值給list(即從list刪除點擊項)
-
求和邏輯
total() {return this.list.reduce((sum, item) => sum + item.score, 0)},
- reduce累加器的運用
-
加入數組
- 往數組前面加:unshift()方法
- 往數組后面加:push()方法
1.4.watch
1.4.1.watch屬性
作用:監視數據變化,執行 業務邏輯 或 異步操作
watch:{// 該方法會在數據變化時調用執行// newValue新值, oldValue老值(一般不用) words(newValue, oldValue) {console.log('變化了', newValue,, oldValue)}
}
以上代碼監聽了data里的數據words,如果我們要監聽data里obj對象屬性words,則應該寫為 'obj.words'
'obj.words'(newValue) {console.log('變化了', newValue)}
1.4.2.翻譯業務實現
watch: {'obj.words'(newValue) { clearTimeout(this.timerId)this.timerId = setTimeout(async () => {const res = await axios({url: 'https://applet-base-api-t.itheima.net/api/translate',params: {words:newValue}})this.result = res.data.data}, 300)},}
知識點
- 防抖處理
1.4.3.watch屬性的完整寫法
-
額外配置項
配置項 效果 deep:true
深度監視,對象的子元素變化也會觸發 immediate:true
初始化立即執行一次
上面的翻譯業務實現還可以升級為,通過改變翻譯語言也會觸發watch監聽
- 對象obj有屬性words和屬性language
- 對象進行深度監視,對象的任何一個屬性(words和language)發生變化,都會觸發重新翻譯
watch: {obj: {deep: true, // 深度監視immediate: true, // 立即執行handler(newValue) {clearTimeout(this.timerId)this.timerId = setTimeout(async () => {const res = await axios({url: 'https://applet-base-api-t.itheima.net/api/translate',params: newValue})this.result = res.data.data}, 300)}},
}
1.4.4.【案例】水果購物車
- 成品圖:
- js代碼
const dedaultArr = [{id: 1,icon: 'img/火龍果.png',isChecked: true,num: 1,price: 6,},{id: 2,icon: 'img/荔枝.png',isChecked: false,num: 1,price: 20,},{id: 3,icon: 'img/榴蓮.png',isChecked: false,num: 1,price: 40,},{id: 4,icon: 'img/鴨梨.png',isChecked: true,num: 1,price: 3,},{id: 5,icon: 'img/櫻桃.png',isChecked: false,num: 1,price: 32,},
]
const app = new Vue({el: '#app',data: {// 水果列表bannerSrc: 'img/fruit.jpg',fruitList: JSON.parse(localStorage.getItem('list')) || dedaultArr},methods: {del(id) {return this.fruitList = this.fruitList.filter(item => item.id != id)}},computed: {// 計算選中個數totalCount() {return this.fruitList.reduce((sum, item) => {if (item.isChecked) {return sum + item.num} else {return sum}}, 0)},// 計算總價totalPrice() {return this.fruitList.reduce((sum, item) => {if (item.isChecked) {return sum + item.num * item.price} else {return sum}}, 0)},all: {get() {// return的值決定全選框是否勾選// 必須所有框都選中,全選按鈕才選中(every)return this.fruitList.every(item => item.isChecked)},set(value) {// 全選按鈕的value影響其他框this.fruitList.forEach(item => item.isChecked = value);}}},watch: {fruitList: {deep: true,handler(newValue) {localStorage.setItem('list', JSON.stringify(newValue))}}}
})
- 部分html代碼展示
<div class="tbody"><div class="tr active" v-for="(item,index) in fruitList"><div class="td"><input type="checkbox" v-model="item.isChecked" /></div><div class="td"><img :src="item.icon" alt="" /></div><div class="td">{{item.price}}</div><div class="td"><div class="my-input-number"><button class="decrease" @click="item.num--"> - </button><span class="my-input__inner">{{item.num}}</span><button class="increase" @click="item.num++"> + </button></div></div><div class="td">{{item.num*item.price}}</div><div class="td"><button @click="del(item.id)">刪除</button></div></div>
</div><!-- 底部 -->
<div class="bottom"><!-- 全選 --><label class="check-all"><input type="checkbox" v-model="all" />全選</label><div class="right-box"><!-- 所有商品總價 --><span class="price-box">總價 : ¥ <span class="price">{{totalPrice}}</span></span><!-- 結算按鈕 --><button class="pay">結算( {{totalCount}} )</button></div>
</div>
知識點:
- 全選框邏輯
- fruitList里添加屬性isChecked來標記item項是否勾選
- 再通過
v-model="item.isChecked
”將isChecked和每個子checkbox綁定,即checkbox和勾選狀態關聯 - 如果子checkbox發生變化,調用get()
- 再通過every檢查fruitList里的item.isChecked是否全為true,即檢查是否全勾選
- 如果全勾選,返回true,通過
v-model="all"
反作用于全選的checkbox,使其勾選 - 如果全選的checkbox發生變化,調用set(),并通過形參value傳入all的值
- 通過forEach,將所有子checkbox的isChecked設置為和all一樣的值
1.5.生命周期
在不同的生命周期,會自動運行一些函數,被稱為生命周期鉤子,讓開發者可以在特定階段運行代碼
-
生命周期四個階段
1.創建階段:創建響應式數據
2.掛載階段:渲染模板
3.更新階段:修改數據,更新視圖
4.銷毀階段:銷毀Vue實例
-
生命周期鉤子
1.5.1.【應用】初始化渲染
在created生命周期,發送獲取數據的請求
const app = new Vue({el: '#app',data: {list: []},async created() {// 1. 發送請求獲取數據const res = await axios.get('http://hmajax.itheima.net/api/news')// 2.將獲取的數據寫入數據列表this.list = res.data.data}
})
</script>
1.5.2.【應用】獲取焦點
在mounted生命周期,獲取焦點(操作dom)
const app = new Vue({el: '#app',data: {words: ''},mounted() {document.querySelector('#inp').focus()}
})