vue--知識點總結:
目錄
1. v-if與v-show的區別
相同點:v-if與v-show都可以動態控制dom元素顯示隱藏
不同點:v-if顯示隱藏是將dom元素整個添加或刪除,而v-show隱藏則是爲該元素添加css--display:none,dom元素還在。
注意:
- 手段:v-if是動態的向DOM樹內添加或者刪除DOM元素;v-show是通過設置DOM元素的display樣式屬性控制顯隱;
- 編譯過程:v-if切換有一個局部編譯/卸載的過程,切換過程中合適地銷燬和重建內部的事件監聽和子組件;v-show只是簡單的基於css切換;
- 編譯條件:v-if是惰性的,如果初始條件爲假,則什麼也不做;只有在條件第一次變爲真時纔開始局部編譯(編譯被緩存?編譯被緩存後,然後再切換的時候進行局部卸載); v-show是在任何條件下(首次條件是否爲真)都被編譯,然後被緩存,而且DOM元素保留;
- 性能消耗:v-if有更高的切換消耗;v-show有更高的初始渲染消耗;
- 使用場景:v-if適合運營條件不大可能改變;v-show適合頻繁切換。
2. Vue的雙向數據綁定原理
答:vue.js 是採用數據劫持結合發佈者-訂閱者模式的方式,通過Object.defineProperty()來劫持各個屬性的setter,getter,在數據變動時發佈消息給訂閱者,觸發相應的監聽回調。 具體步驟:
- 第一步:需要observe的數據對象進行遞歸遍歷,包括子屬性對象的屬性,都加上 setter和getter 這樣的話,給這個對象的某個值賦值,就會觸發setter,那麼就能監聽到了數據變化
- 第二步:compile解析模板指令,將模板中的變量替換成數據,然後初始化渲染頁面視圖,並將每個指令對應的節點綁定更新函數,添加監聽數據的訂閱者,一旦數據有變動,收到通知,更新視圖
- 第三步:Watcher訂閱者是Observer和Compile之間通信的橋樑,主要做的事情是:
- 在自身實例化時往屬性訂閱器(dep)裏面添加自己
- 自身必須有一個update()方法
- 待屬性變動dep.notice()通知時,能調用自身的update()方法,並觸發Compile中綁定的回調,則功成身退。
- 第四步:MVVM作爲數據綁定的入口,整合Observer、Compile和Watcher三者,通過Observer來監聽自己的model數據變化,通過Compile來解析編譯模板指令,最終利用Watcher搭起Observer和Compile之間的通信橋樑,達到數據變化 -> 視圖更新;視圖交互變化(input) -> 數據model變更的雙向綁定效果。
3. Vue的生命週期
答:總共分爲8個階段創建前/後,載入前/後,更新前/後,銷燬前/後。
- 創建前/後: 在beforeCreated階段,vue實例的掛載元素$el和數據對象data都爲undefined,還未初始化。在created階段,vue實例的數據對象data有了,$el還沒有。
- 載入前/後:在beforeMount階段,vue實例的$el和data都初始化了,但還是掛載之前爲虛擬的dom節點,data.message還未替換。在mounted階段,vue實例掛載完成,data.message成功渲染。
- 更新前/後:當data變化時,會觸發beforeUpdate和updated方法。
- 銷燬前/後:在執行destroy方法後,對data的改變不會再觸發周期函數,說明此時vue實例已經解除了事件監聽以及和dom的綁定,但是dom結構依然存在
(上圖是網上找的,忘了出處啦,侵刪)
4. 封裝 vue 組件的過程
答:首先,組件可以提升整個項目的開發效率。能夠把頁面抽象成多個相對獨立的模塊,解決了我們傳統項目開發:效率低、難維護、複用性等問題。
然後,使用Vue.extend方法創建一個組件,然後使用Vue.component方法註冊組件。子組件需要數據,可以在props中接受定義。而子組件修改好數據後,想把數據傳遞給父組件。可以採用emit方法。
5. 理解vuex
vuex的核心是:state,getter,actions,mutations
- state就是根據你項目的需求,自己定義的一個數據結構,裏面可以放些通用的狀態。建議使用mutations來改變state裏面的值,因爲不通過mutations改變state,狀態不會被同步。至於mutations下面會講到。
- getter怎麼理解呢?通俗的理解可以認爲是getter裏的函數就是vuex裏的計算屬性,類似於computed函數。 getter函數怎麼用呢?如果vuex裏定義了一個getter函數addNum。我們可以在vue文件裏的computed計算屬性裏引用,如下。先引入vuex的文件,然後在當前文件的computed中引入你在vuex的getter中定義的函數addNum。
- 更改 Vuex 的 store 中的狀態的唯一方法是提交 mutation。Vuex 中的 mutations 非常類似於事件:每個 mutation 都有一個字符串的 事件類型 (type) 和 一個 回調函數 (handler)。這個回調函數就是我們實際進行狀態更改的地方,並且它會接受 state 作爲第一個參數:(需要注意:Mutations必須是同步函數。如果我們需要異步操作,Mutations就不能滿足我們需求了,這時候我們就需要Actions了。)
- Action 類似於 mutation,不同在於:Action 提交的是 mutation,而不是直接變更狀態。Action 可以包含任意異步操作。(如果我在vue頁面裏想用action,我們可以分發 Action,Action 通過 store.dispatch 方法觸發:)
- mutations由於使用單一狀態樹,應用的所有狀態會集中到一個比較大的對象。當應用變得非常複雜時,store 對象就有可能變得相當臃腫。爲了解決以上問題,Vuex 允許我們將 store 分割成模塊(module)。每個模塊擁有自己的 state、mutation、action、getter、甚至是嵌套子模塊——從上至下進行同樣方式的分割:
總結:mutation 只管存,你給我(dispatch)我就存;action只管中間處理,處理完我就給你,你怎麼存我不管(所有的改變state狀態的都是mutation 來操作);Getter 我只管取,我不改的(類似計算屬性)。
6.vue頁面間傳值
一、父組件向子組件傳遞數據通過props
父組件:使用v-bind傳值
子組件:使用props接收
父組件:
<header-box v-bind="message"></header-box>
子組件:
props: {
message: String
},
二、子組件向父組件傳值 (參考的vue組件之間的通信來完成,侵刪)
子組件向父組件傳遞分爲兩種類型:
- 子組件改變父組件傳遞的props(你會發現通過props中的Object類型參數傳輸數據,可以通過子組件改變數據內容。這種方式是可行的,但是不推薦使用,因爲官方定義prop是單向綁定)
- 通過$on和$emit
**父組件代碼**
<template>
<div id="counter-event-example">
<p>{{ total }}</p>
<button-counter v-on:increment="incrementTotal"></button-counter>
</div>
</template>
<script>
import ButtonCounter from './buttonCounter'
export default {
name: 'index',
components: {
'button-conuter': ButtonCounter
},
data () {
return {
total: 0
}
},
methods: {
incrementTotal () {
this.total++
}
}
}
</script>
**子組件代碼**
<template>
<button @click="incrementCounter">{{counter}}</button>
</template>
<script>
export default {
name: 'button-counter',
data () {
return {
counter: 0
}
},
metheds: {
incrementCounter () {
this.$emit('increment')
this.counter++
}
}
}
</script>
三、同級傳參的兩種方式:
- query傳參,或者params傳參
使用
this.$router.push({ path:'路徑值' , query: { 參數名: '參數值' }})
this.$router.push({name: '路由名',params: {參數名: '參數值'}})
注意1:使用params時不能使用path
接收:
var a = this.$route.query.參數名
var b = this.$route.params.參數名
注意:接收傳來的值時,最好把接收值的方法放在鉤子函數中觸發,或者在路由守衛beforeRouteEnter、beforeRouteLeave, 並且使用watch來監聽(可以自己搜一下,在鉤子函數和路由守衛中觸發的區別)
代碼示例:
watch: {
// 監測路由變化,只要變化了就調用獲取路由參數方法將數據存儲本組件即可
'$route': 'getParams'
},
beforeRouteEnter (to, from, next) {
next(vm =>{
vm.getParams();
})
},
beforeRouteLeave(to, from, next) {
next(vm =>{
vm.getParams();
});
},
methods: {
getParams:function(){
var pid = this.$route.query.pid;
},
}
注意2:實用params去傳值的時候,在頁面刷新時,參數會消失,用query則不會有這個問題。
四、vue組件之間使用bus(總線/觀察者模式)傳值
- 創建Bus.js
import Vue from 'vue'
const Bus = new Vue();
export default Bus
- 在需要通信的兩個組件中引入Bus
import Bus from '@/components/utils/Bus.js';
- 發送消息
Bus.$emit('消息名', 消息值);
- 接收消息
接受組件的事件:寫在鉤子函數內:例如:mounted created都可以
Bus.$on('msg', (e) => {
this.num = e;
})
五、通過設置Session Storage緩存的形式進行傳遞
- 兩個組件A和B,在A組件中設置緩存orderData
const orderData = { 'orderId': 123, 'price': 88 }
sessionStorage.setItem('緩存名稱', JSON.stringify(orderData))
- B組件就可以獲取在A中設置的緩存了
const dataB = JSON.parse(sessionStorage.getItem('緩存名稱'))
注意:瞭解一下 Session Storage(程序退出銷燬) 和 Local Storage(長期保存) 的區別。
四、vuex
7. vue樣式的切換及vue動態樣式的使用
- vue中style與class綁定API
<div id="wrap" class="box">
<div v-for="(list,index) in navLists" class="nav"
:class="{ red:changeRed == index}"
@click="reds(index)"
>
{{list.text}}
</div>
</div>
css和js:
*{
padding: 0;margin: 0;
}
.box{
height: 40px;
background: cyan;
}
.nav{
line-height: 40px;
display: inline-block;
margin-left: 100px;
cursor: pointer;
}
.red{
color: red;
}
//前提是必須引入vuejs哦!
var vm = new Vue({
el:"#wrap",
data:{
navLists:[
{
"text":"首頁"
},
{
"text":"組件"
},
{
"text":"API"
},
{
"text":"我們"
}
],
changeRed:0
},
methods:{
reds:function(index){
this.changeRed = index;
}
}
});
2. 動態樣式的解決方法
- 方法1
:class="{active: isActive}"
通過改變isActive是否爲true和false來動態改變樣式
- 方法2
class="[lineStyle(courseClick)]"
lineStyle(isClick){
if (isClick===true){
return 'tab-items-current'
}else {
return 'class-tab-items'
}
}
3. v-show和v-if來控制元素的顯示、隱藏(上面有說明)
8. vue路由傳參3種的基本模式
在vue路由中,支持3種傳參方式:
<li v-for="info in indexInfo" @click="getIndexInfo(indexInfo.id)">
- 方案一:
getIndexInfo(id) {
// 直接調用$router.push 實現攜帶參數的跳轉
this.$router.push({
path: `/home/${id}`,
})
// 方案一,需要對應路由配置如下:
{
path: '/home/:id',
name: 'home',
component: home
}
// 很顯然,需要在path中添加/:id來對應 $router.push 中path攜帶的參數。
// 在子組件中可以使用來獲取傳遞的參數值。
$route.params.id