vue筆記
vue筆記(持續(xù)更新)
Vue scoped
scoped解決了什么?
模塊化編程下,在對應(yīng)模塊的js中import css,這個css仍然是全局。因此會產(chǎn)生css樣式之間污染。scoped可以使css樣式只作用于當(dāng)前組件,解決了組件之間樣式污染。給每個style都設(shè)置上scoped,相當(dāng)于實(shí)現(xiàn)了樣式的模塊化。
官方解釋:當(dāng)style有scoped屬性時,它的CSS只作用于當(dāng)前組件中元素(解決樣式?jīng)_突)
<style scoped>
@media (min-width: 250px) {
.list-container:hover {
background: orange;
}
}
</style>
<!--
scoped 會自動添加一個唯一的 attribute (如 data-v-hash) 為組件內(nèi) CSS 指定作用域,編譯的時候 .list-container:hover 會被編譯成 .list-container[data-v-hash]:hover。
-->
例如:
<!-- scoped轉(zhuǎn)譯前 -->
<style lang="scss" scoped>
.test {
background: blue;
span{
color:red;
}
}
</style>
<!-- scoped轉(zhuǎn)譯后 -->
<style lang="css">
.test[data-v-ff86ae42] {
background: blue;
}
.test span[data-v-ff86ae42]{
color: red;
}
</style>
以前有個人在Vue提了個issue,style的scope使一些必要的css無效,然偶后尤大大親自耐心的回答了,scope的功能是為了讓css更規(guī)范,能更簡單讓css僅對本組件的內(nèi)容起到作用而不影響其他組件,這樣也是為了減少各組件之間的樣式黏性,可以避免修改單組件樣式而影響到整個項(xiàng)目眾多組件的問題。反正能用外聯(lián)css或公共css文件建立共有的css,所以我是非常建議使用scope但別穿透它
穿透scoped
為什么要穿透scoped?
通過scoped,組件的樣式是被封裝在組件范圍內(nèi)的,也就是說組件樣式對外部組件是不可見的。這種封裝樣式的機(jī)制可以防止樣式?jīng)_突和作用域污染,提高樣式的可維護(hù)性。然而某些情況下,我們希望通過組件樣式去修改或影響子組件內(nèi)部的樣式。
<template>
<div class="parent">
<child-component class="custom-class" />
</div>
</template>
<style scoped>
.parent /deep/ .custom-class {
/* 修改子組件的樣式 */
}
</style>
使用scoped情況
在模板中使用兩次style標(biāo)簽
<!-- 使用兩次style分別控制 需要覆蓋子組件的樣式 和 只能本模塊使用樣式 -->
<style lang="scss">
/*添加要覆蓋的樣式*/
</style>
<style lang="scss" scoped>
/* 本模塊樣式 */
</style>
<!-- vue官網(wǎng)明確表示一個vue文件可以包含多個style標(biāo)簽 -->
scoped穿透
<!--使用 >>> 或者 /deep/ 操作符(Sass,less 之類的預(yù)處理器無法正確解析 >>>,可以使用/deep/)-->
<style lang="scss" scoped>
.box {
/deep/ input {
width: 166px;
text-align: center;
}
}
</style>
或者
<style lang="scss" scoped>
.box >>> input {
width: 166px;
text-align: center;
}
</style>
不使用scoped情況
-
使用全局樣式:將樣式定義在全局的CSS文件中,這樣定義的樣式將會被整個應(yīng)用所共享。
-
使用CSS Modules:CSS Modules允許您在每個組件中定義獨(dú)立的、局部作用域的樣式,但仍然可以通過類名選擇器來影響其他組件的樣式
-
使用CSS預(yù)處理器:大多數(shù)CSS預(yù)處理器(如Sass、Less)都支持全局樣式和變量。
總結(jié)
scoped穿透是一種非正式的語法,不是標(biāo)準(zhǔn)的CSS規(guī)范,因此在使用時要謹(jǐn)慎考慮其兼容性和易讀性。
總而言之,scoped穿透在一定程度上打破了組件樣式的封裝性,允許父組件的樣式影響到子組件內(nèi)部的樣式,但需要注意合理使用,避免引入樣式的混亂和復(fù)雜性。
Vue nextTick
為什么會存在nextTick?
vue采用異步更新策略來提高性能,當(dāng)修改Vue實(shí)力數(shù)據(jù)時,Vue并不會立即更新真實(shí)DOM,而是講DOM更新操作推入一個隊(duì)列中,在下一個事件循環(huán)周期中進(jìn)行統(tǒng)一的更新。這樣做可以有效地合并多次數(shù)據(jù)變更,避免頻繁的DOM操作。然而,這也導(dǎo)致了一個問題:在某些情況下,我們需要在數(shù)據(jù)更新之后立即訪問更新后的DOM。
nextTick作用
通過使用nextTick方法接收一個回調(diào)函數(shù)作為參數(shù),并講這個回調(diào)函數(shù)延遲到下次DOM更新循環(huán)結(jié)束后執(zhí)行,確保DOM已經(jīng)被更新。這樣就能夠安全地操作更新后的DOM元素,而不用擔(dān)心獲取到舊的值或狀態(tài)。
nextTick實(shí)現(xiàn)原理
將傳入的回調(diào)函數(shù)包裝成異步任務(wù),異步任務(wù)又分微任務(wù)和宏任務(wù),為了盡快執(zhí)行所以優(yōu)先選擇微任務(wù);
nextTick 提供了四種異步方法 Promise.then、MutationObserver、setImmediate、setTimeout(fn,0)
這四種異步可以閱讀nextTick源碼解讀。
<!-- 例子解釋 -->
<script>
console.log('start');
process.nextTick(() => {
console.log('nextTick callback');
});
console.log('end');
</script>
<!-- 輸出結(jié)果:
start
end
nextTick callback
-->
Vue computed
computed解決了什么問題?
computed 的存在是為了提供一種方便、高效地對響應(yīng)式數(shù)據(jù)進(jìn)行計(jì)算和處理的機(jī)制。
解決的問題有:
簡化復(fù)雜邏輯:當(dāng)需要進(jìn)行復(fù)雜的數(shù)據(jù)計(jì)算或處理時,使用 computed 可以將這些邏輯封裝在一個計(jì)算屬性中,使代碼更易于理解、維護(hù)和重用。
避免重復(fù)計(jì)算:computed 會根據(jù)其依賴的響應(yīng)式數(shù)據(jù)來進(jìn)行緩存。只有在依賴發(fā)生變化時,才會重新計(jì)算計(jì)算屬性的值。這樣可以避免重復(fù)計(jì)算,提高性能并減少不必要的計(jì)算開銷。
自動追蹤依賴關(guān)系:Vue.js 的響應(yīng)式系統(tǒng)會自動追蹤 computed 屬性所依賴的響應(yīng)式數(shù)據(jù)。當(dāng)依賴的數(shù)據(jù)發(fā)生改變時,相關(guān)的計(jì)算屬性會自動重新計(jì)算,確保計(jì)算結(jié)果的及時更新。
優(yōu)化模板渲染:通過在模板中使用 computed,可以將復(fù)雜的數(shù)據(jù)處理邏輯移到計(jì)算屬性中,簡化模板的寫法,使模板更易讀、清晰。
Vue官方示例computed
<!-- message數(shù)據(jù)需要展示 -->
<template>
<div id="app">
{{message}}
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {
message: 'Hello'
}
}
}
</script>
<!-- ! 需求:對message反轉(zhuǎn)并展示 -->
<!-- 正確但不合適的做法:直接在模板轉(zhuǎn)化或在methods中定義一個方法調(diào)用 -->
<template>
<div id="app">
<p>{{message}}</p>
<p>{{message.split('').reverse().join('')}}</p>
</div>
</template>
<!-- 正確且合適的做法:使用computed -->
<template>
<div id="app">
<p>{{message}}</p>
<p>{{reverseMessage}}</p>
</div>
</template>
<script>
export default {
name: 'App',
computed: {
reverseMessage: function(){
return this.message.split('').reverse().join('');
}
},
data() {
return {
message: 'Hello'
}
}
}
</script>
解析:
當(dāng)我們使用不合適的直接轉(zhuǎn)換展示時,每次我們需要完成這個需求,都要寫一遍處理邏輯。
使用不合適的methods中定義一個方法,方法寫上處理邏輯,每次需要完成這個需求時,調(diào)用方法。這種方式表面上不需要寫很多遍處理邏輯,但是每次調(diào)用這個方法時候,都會執(zhí)行處理邏輯。
使用合適的computed時,computed會保存處理邏輯的值,每次需要完成這個需求時,直接獲取computed緩存好的值,不需要反復(fù)執(zhí)行處理邏輯,只有當(dāng)依賴項(xiàng)改變時才會重新執(zhí)行處理邏輯,并緩存更新后的值。
Vue Watch
watch作用?
Vue中的watch又名為偵聽屬性,它主要用于偵聽數(shù)據(jù)的變化,在數(shù)據(jù)發(fā)生變化的時候執(zhí)行一些操作。
作用有:
響應(yīng)式數(shù)據(jù)的監(jiān)控:通過 watch,您可以監(jiān)聽指定的數(shù)據(jù)(包括響應(yīng)式數(shù)據(jù)和計(jì)算屬性),一旦這些數(shù)據(jù)發(fā)生變化,就會觸發(fā)相應(yīng)的回調(diào)函數(shù)。這使得您可以實(shí)時捕捉數(shù)據(jù)的改變并做出相應(yīng)的處理。
復(fù)雜依賴關(guān)系的處理:有時候,數(shù)據(jù)之間存在復(fù)雜的依賴關(guān)系,一個數(shù)據(jù)的改變可能會影響到其他相關(guān)的數(shù)據(jù)。使用 watch,您可以輕松地處理這種復(fù)雜的依賴關(guān)系,監(jiān)聽多個數(shù)據(jù),并在其中一個數(shù)據(jù)發(fā)生變化時進(jìn)行相應(yīng)的處理。
異步操作的觸發(fā):watch 支持異步處理邏輯在回調(diào)函數(shù)中執(zhí)行,這對于需要進(jìn)行異步操作的場景非常有用。例如,當(dāng)某個數(shù)據(jù)發(fā)生變化后,您可以在回調(diào)函數(shù)中發(fā)送網(wǎng)絡(luò)請求或執(zhí)行其他異步任務(wù)。
避免不必要的計(jì)算開銷:由于 watch 會立即執(zhí)行回調(diào)函數(shù)來響應(yīng)數(shù)據(jù)的變化,因此您可以根據(jù)需要選擇性地監(jiān)聽特定的數(shù)據(jù),避免無謂的計(jì)算開銷和性能浪費(fèi)。
Vue 官方示例
Vue官網(wǎng)很明確的建議我們這樣使用watch偵聽屬性:當(dāng)需要在數(shù)據(jù)變化時執(zhí)行異步或開銷較大的操作時,這個方式是最有用的。
<template>
<p>
Ask a yes/no question:
<input v-model="question" />
</p>
<p>{{ answer }}</p>
</template>
<script>
export default {
data() {
return {
question: '',
answer: 'Questions usually contain a question mark. ;-)'
}
},
watch: {
// 每當(dāng) question 改變時,這個函數(shù)就會執(zhí)行
// newQuestion更新后的值,oldQuestion更新前的值
question(newQuestion, oldQuestion) {
if (newQuestion.includes('?')) {
this.getAnswer()
}
}
},
methods: {
async getAnswer() {
this.answer = 'Thinking...'
try {
const res = await fetch('https://yesno.wtf/api')
this.answer = (await res.json()).answer
} catch (error) {
this.answer = 'Error! Could not reach the API. ' + error
}
}
}
}
</script>
解析:
以上定義了一個input框收集用戶輸入的問題,一個p標(biāo)簽回答用戶問題,每當(dāng)input框的question發(fā)生改變時,都會觸發(fā)watch中的question方法執(zhí)行處理邏輯,判斷是否有?,有則執(zhí)行methods中的getAnswer方法
computed 和 watch如何選擇?
Vue官網(wǎng)的示例
<script>
// 使用computed實(shí)現(xiàn)
// 定義計(jì)算屬性fullName,將firstName和lastName的值進(jìn)行拼接并返回。
computed: {
fullName: function() {
return this.firstName + ' ' + this.lastName;
}
},
// 使用watch實(shí)現(xiàn)
// watch偵聽firstName和lastName,當(dāng)這兩個數(shù)據(jù)發(fā)生變化時更新fullName的值。
watch: {
firstName: function(newValue) {
this.fullName = newValue + ' ' + this.lastName;
},
lastName: function(newValue){
this.fullName = this.firstName + ' ' + newValue;
}
}
</script>
解析:
兩個方法效率都差不多,每次firstName,lastName都會,而computed實(shí)現(xiàn)方式更加簡潔。
computed應(yīng)用場景:模板中有復(fù)雜的計(jì)算。
watch應(yīng)用場景:當(dāng)數(shù)據(jù)發(fā)生變化時執(zhí)行 異步操作 或者 開銷較大的操作。
注意:
當(dāng)多個數(shù)據(jù)影響一個數(shù)據(jù)時,會導(dǎo)致watch多次被調(diào)用,這個時候盡量使用computed。
浙公網(wǎng)安備 33010602011771號