-
v-bind="{ a: 1, b: 1 }"
這種寫法可以將對象里的所有屬性綁定 -
v-on="onChange($event, ...arguments)"
這種寫法可以傳事件對象為第一個參數(shù)尚粘,其他參數(shù)依次往后傳遞离赫。 -
v-show
不能放在template
上使用魂迄,也不能和v-else
使用注服,為false
時元素會加上display:none
-
v-for
可以和template
標(biāo)簽一起使用
<template v-for="item in list"></template>
- 數(shù)組更新檢測
- push()
- pop()
- shift()
- unshift()
- splice()
- sort()
- reserve()
- v-for中的key是什么作用?
官方的解釋:
- key屬性主要用在Vue的虛擬DOM算法澎埠,在新舊nodes對比時辨識VNodes虽缕;
- 如果不使用key,Vue會使用一種最大限度減少動態(tài)元素并且盡可能的嘗試就地修改/復(fù)用相同類型元素的算法蒲稳;
- 而使用key時氮趋,它會基于key的變化重新排列元素順序,并且會移除/銷毀key不存在的元素江耀;
Vue事實上會對于有key和沒有key會調(diào)用兩個不同的方法剩胁;有key,那么就使用 patchKeyedChildren
方法祥国;沒有key昵观,那么久使用 patchUnkeyedChildren
方法;
沒有key的過程如下:
- c和d來說它們事實上并不需要有任何的改動舌稀;
-
但是因為我們的c被f所使用了啊犬,所有后續(xù)所有的內(nèi)容都要一次進(jìn)行改動,并且最后進(jìn)行新增壁查;
有key的diff算法如下:
第一步的操作是從頭開始進(jìn)行遍歷觉至、比較:
- a和b是一致的會繼續(xù)進(jìn)行比較;
- c和f因為key不一致睡腿,所以就會break跳出循環(huán)语御;
第二步的操作是從尾部開始進(jìn)行遍歷领斥、比較:
第三步是如果舊節(jié)點遍歷完畢,但是依然有新的節(jié)點沃暗,那么就新增節(jié)點:
第四步是如果新的節(jié)點遍歷完畢,但是依然有舊的節(jié)點何恶,那么就移除舊節(jié)點:
第五步是最特色的情況孽锥,中間還有很多未知的或者亂序的節(jié)點:
所以我們可以發(fā)現(xiàn),Vue在進(jìn)行diff算法的時候细层,會盡量利用我們的key來進(jìn)行優(yōu)化操作:
- 在沒有key的時候我們的效率是非常低效的惜辑;
- 在進(jìn)行插入或者重置順序的時候,保持相同的key可以讓diff算法更加的高效疫赎;
-
源碼如何對computedd的setter和getter處理呢盛撑?
事實上非常的簡單,Vue源碼內(nèi)部只是做了一個邏輯判斷而已捧搞;
-
watch監(jiān)聽對象
- 使用一個選項deep進(jìn)行更深層的偵聽抵卫;
- 使用immediate選項, 望一開始的就會立即執(zhí)行一次
- watch其他監(jiān)聽器的寫法:
watch: {
a: 'onChange'
},
methods: {
onChange (val, old) {}
}
還可以在created的生命周期中胎撇,使用 this.$watchs 來偵聽:
- 第一個參數(shù)是要偵聽的源
- 第二個參數(shù)是偵聽的回調(diào)函數(shù)callback介粘;
- 第三個參數(shù)是額外的其他選項,比如deep晚树、immediate姻采;
- v-model的原理
v-model的原理其實是背后有兩個操作:
- v-bind綁定value屬性的值;
- v-on綁定input事件監(jiān)聽到函數(shù)中爵憎,函數(shù)會獲取最新的值賦值到綁定的屬性中慨亲;
- v-model修飾符
- lazy
如果我們在v-model后跟上lazy修飾符,那么會將綁定的事件切換為 change 事件宝鼓,只有在提交時(比如回車)
才會觸發(fā)刑棵; - number
如果我們希望轉(zhuǎn)換為數(shù)字類型,那么可以使用 .number 修飾符愚铡,在我們進(jìn)行邏輯判斷時铐望,如果是一個string類型,在可以轉(zhuǎn)化的情況下會進(jìn)行隱式轉(zhuǎn)換的 - trim
如果要自動過濾用戶輸入的守衛(wèi)空白字符茂附,可以給v-model添加 trim 修飾符
當(dāng)我們傳遞給一個組件某個屬性正蛙,但是該屬性并沒有定義對應(yīng)的props或者emits時,就稱之為 非Prop的Attribute营曼,常見的包括class乒验、style、id屬性等蒂阱。當(dāng)組件有單個根節(jié)點時锻全,非Prop的Attribute將自動添加到根節(jié)點的Attribute中狂塘,如果我們不希望組件的根元素繼承attribute,可以在組件中設(shè)置 inheritAttrs: false鳄厌【浜担可以通過 $attrs來訪問所有的 非props的attribute,多個根節(jié)點的attribute如果沒有顯示的綁定瓷炮,那么會報警告咧七,我們必須手動的指定要綁定到哪一個屬性上。
子組件向父組件emit事件:
vue3新增申明emits:
可以是一個數(shù)組:
emits: ["add", "sub", "addN"]
也可以是對象用來驗證參數(shù)歪泳,只是起到警告作用萝勤,驗證不通過依然會傳給父組件:
emits: {
add: null,
sub: null,
addN: (num, name, age) => {
console.log(num, name, age);
if (num > 10) {
return true
}
return false;
}
},
- 非父子組件的通信
- Provide和Inject
父組件
子組件provide() { return { name: "why", age: 18, length: computed(() => this.names.length) // ref對象 .value } },
<template>
<div>
HomeContent: {{name}} - {{age}} - {{length.value}}
</div>
</template>
<script>
export default {
inject: ["name", "age", "length"],
}
</script>
<style scoped>
</style>
- 全局事件總線mitt庫
npm install mitt
import mitt from 'mitt';
const emitter = mitt();
export default emitter;
btnClick() {
console.log("about按鈕的點擊");
emitter.emit("why", {name: "why", age: 18});
}
created() {
emitter.on("why", (info) => {
console.log("why:", info);
});
emitter.on("kobe", (info) => {
console.log("kobe:", info);
});
emitter.on("*", (type, info) => {
console.log("* listener:", type, info);
})
}
- 異步組件的使用
const AsyncCategory = defineAsyncComponent(() => import("./AsyncCategory.vue"))
const AsyncCategory = defineAsyncComponent({
loader: () => import("./AsyncCategory.vue"),
loadingComponent: Loading,
// errorComponent,
// 在顯示loadingComponent組件之前, 等待多長時間
delay: 2000,
/**
* err: 錯誤信息,
* retry: 函數(shù), 調(diào)用retry嘗試重新加載
* attempts: 記錄嘗試的次數(shù)
*/
onError: function(err, retry, attempts) {
}
})
- 組件的v-model
組件的v-model實際做了兩件事:
<hy-input v-model="message"></hy-input>
<!-- 綁定兩個v-model -->
<hy-input v-model="message" v-model:title="title"></hy-input>
<hy-input :modelValue="message" @update:model-value="message = $event"></hy-input>
組件需要$emit(update:modelValue)。
配合組件自己的input的v-model使用:
<template>
<div>
<input v-model="value">
</div>
</template>
<script>
export default {
props: {
modelValue: String
},
emits: ["update:modelValue"],
computed: {
value: {
set(value) {
this.$emit("update:modelValue", value);
},
get() {
return this.modelValue;
}
}
},
methods: {
btnClick(event) {
this.$emit("update:modelValue", event.target.value);
}
}
}
</script>
<style scoped>
</style>