又是一個陽光明媚,風和日麗的週末,有人陪女神去逛街,有人陪女神去看電影,小編卻默默的拿出電腦。哈哈哈,不是小編屌絲,女神正坐在旁邊玩手機(感受不是屌絲纔怪)。javascript
這兩天小編重讀了一遍vue2.0官網的風格指南,整理了這九條關鍵規則。css
v-for設置鍵值
提到v-for
須要設置鍵值,許多人第一反應會從diff
算法的角度去講緣由,我更喜歡舉一個例子來演示一下緣由html
假設有這樣的一個頁面,頁面的列表是經過遍歷數組得來的,以下圖所示前端
示例代碼以下vue
<!--模板部分-->
<div id="app">
<div v-for="item in arr">
{{item}}
<input/>
</div>
<button @click="deleteData">刪除第二個元素</button>
</div>
複製代碼
// js 部分
new Vue({
el: '#app',
data() {
return {
arr: [1,2,3]
}
},
methods:{
deleteData() {
this.arr.splice(1,1)
}
}
})
複製代碼
如今須要刪除第二個元素。下面咱們分別在渲染列表是 不使用key,使用索引做爲key, 使用惟一值id做爲key,看三種場景刪除第二個元素以後的效果java
v-for
不使用key
點擊查看代碼演示v-for
使用索引做爲key
點擊查看代碼演示
key
以後,與不使用key的效果同樣,刪除第二個元素以後,輸入框前面的數字顯示正確的,可是數字3後面的輸入框的內容顯示錯了,應該顯示 我是第三個v-for
使用惟一值id做爲key
點擊查看代碼演示使用id做爲key
,顯示正確算法
爲何v-for
須要設置key,緣由很簡單。 對比數組 [1,2,3]和[1,3],咱們很容易發現刪掉了2,可是計算機不是這樣的邏輯數組
那麼爲何不能用索引做爲key呢? 當刪掉[1,2,3]中的2以後,數組的長度由3變成了2,那麼原來數字3的索引就變成了數字2的索引了。bash
而對於使用id做爲key,那麼每條數據都有了惟一的標識,當刪掉[{id:'1',value: 1},{id: '2',value: 2}, {id: '3', value:3}]
中的第二個,整個過程以下app
沒得問題嘛!!!!
模板中的複雜邏輯使用計算屬性代替
vue在模板可使用表達式是很是方便的,但表達式在設計之初是爲了進行簡單邏輯處理的,若是在模板中使用太多或太複雜的邏輯,會讓模板的可讀性和可維護性變得不好,整個模板顯得很臃腫。
<!--v-if使用了一連串的條件判斷,可讀性比較差-->
<button v-if=" user.roles && user.roles.includes('Workflowbeheer') && data.userId === user.id && data.status === 1 " >
刪除
</button>
複製代碼
<template>
<button v-if="deletable">
刪除
</button>
</template>
<script> export default { computed: { // 判斷是否能夠刪除 deletable() { const { data, user } = this // 若是當前用戶不是流程管理員,則不能編輯 if (user.roles && user.roles.includes('Workflowbeheer')) { // 若是當前用戶爲流程發起者且狀態爲未啓動,則能夠刪除 return data.userId === user.id && data.status === 1 } return false } } } </script>
複製代碼
避免v-for與v-if混用
在開發vue項目中,你們可能會遇到這樣的代碼
<ul>
<li v-for="item in list" v-if="item.visible" :key="item.id">
{{ item.name }}
</li>
</ul>
複製代碼
若是在項目中啓用了eslint
,則可能會看到下面這樣的異常提示(須要啓用eslint vue/no-use-v-if-with-v-for
規則)
The 'list' variable inside 'v-for' directive should be replaced with a computed property that returns filtered array instead. You should not mix 'v-for' with 'v-if'.
複製代碼
在vue處理指令的時候,v-for
比v-if
會有更高的優先級,那麼上述的代碼用js能夠模擬爲
list.map(item => {
if(item.visible) {
return item.name
}
})
複製代碼
經過上述代碼能夠看到,即便大部分數據的visible都是false,也會將整個list所有遍歷一次。若是每一次都須要遍歷整個數組,將會影響速度,尤爲是當之須要渲染很小一部分的時候。
對於上述的問題,可使用計算屬性來處理
<ul>
<li v-for="item in getList" :key="item.id">
{{ item.name }}
</li>
</ul>
computed: {
getList() {
return this.list.filter(item => {
return item.visible
})
}
}
複製代碼
經過上述的代碼,咱們能夠得到如下好處
儘可能使用私有屬性/方法
在開發vue組件的時候,咱們能夠經過組件的ref
來調用組件對外提供的方法,可是一個組件內部有些方法是內部私有的,不該該被外部調用,但實際上js中並無像其餘語言同樣有私有方法(好比java
的private
),因此在js中通常約定使用_
開頭的屬性或者方法表示私有的。
{
// 公共的
selectRows(rows) {},
// 私有的 外部雖然能夠調用到,可是由於是`_`開頭,因此按照約定不該該去調用
_select(rows){}
}
複製代碼
在vue中定義私有屬性/方法又與js常規約定有所不一樣。在Vue內部,已經使用了_
開頭去定義Vue原型上面的私有屬性/方法,若是在組件內上面繼續使用_
開頭去定義私有屬性/方法可能會出現覆蓋實例上面屬性/方法的狀況,好比下面這種狀況:
methods: {
// 初始化組件的數據方法
_init() {
fetch().then(data => {
})
}
}
複製代碼
上面的代碼看似沒有問題,實際上運行的時候會報錯,由於_init
方法會覆蓋Vue.prototype
上面的同名方法,以下圖爲Vue原型鏈的方法,第一個即是_init
在Vue2.0風格指南中,建議使用$_
來定義私有方法,能夠確保不會和Vue自身發生衝突。修改上例爲
methods: {
// 初始化組件的數據方法
$_init() {
fetch().then(data => {
})
}
}
複製代碼
組件數據必須是一個函數,並返回一個對象
在說爲何組件的數據必須返回一個函數以前,咱們先來了解一下js中的基本類型與引用類型。
在es2020發佈了bigint類型以後,js中的基本類型一種包含七種,分別是
基本類型的特色包括
let a = 2
let b = a
// 對a的值的修改,會在棧內存開闢新的空間,因此不會影響到b的值
a = 3
// 輸出 3 2
console.log(a,b)
// 不能給基本類型上面掛載新的屬性
a.testProp = '掛載的屬性'
// 輸出undefined
console.log(a.testProp)
複製代碼
Object
,Array
,Function
,RegExp
,Date
等等引用類型的特色包括
let obj1 = {a: 1, b: 2}
let obj2 = obj1
// 由於引用類型的值是保存到堆內存的,obj1與obj2引用的是同一塊堆內存空間,因此對obj1的值進行
// 修改,會直接影響到obj2的值
obj1.a = 3
// 輸出 3
console.log(obj2.a)
// 掛載新的屬性
obj1.testProp = '掛載的新屬性值'
// 輸出 "掛載的新屬性值"
console.log(obj1.testProp)
複製代碼
經過上面的對比,我想你們其實也清楚了爲何vue的數據必須返回一個函數了。
假設咱們如今開發了一個組件,組件上面的data是一個普通的對象,那麼當咱們實例化多個組件的時候,全部的實例將共享引用同一個數據對象,任何一個實例對數據的修改都會影響到其餘實例。而將組件上面的數據定義爲一個函數以後,當實例化多個組件的時候,每一個實例經過調用 data 函數,從而返回初始數據的一個全新副本數據對象,這時候就避免了對象引用。
爲組件樣式設置做用域
在前端發展突飛猛進的今天,全部的一切都在飛速的發展,前端項目規模愈來愈大,而css做爲一個只有全局做用域的語言,樣式衝突會帶來不少麻煩。JS語言模塊已經標準化,CSS仍是在不斷探索,同時這也是一個急需解決的問題。如今人們提出了許多爲css添加做用域的解決方法,好比BEM樣式規範,好比css module。
在Vue中,使用了經過給元素添加scoped attribute
的方式爲css添加做用域,具體代碼以下
<template>
<button class="button">按鈕</button>
</template>
<!--給style標籤添加scoped屬性-->
<style scoped> .button { width: 50px; height: 40px; } </style>
複製代碼
編譯以後的結果以下
<!--html 添加了一個新屬性 data-v-039c5b43,對於組件內的全部元素,都會添加同一個屬性data-v-039c5b43,這樣保證了同一個組件內全部元素都在同一個做用域內-->
<button data-v-039c5b43="" class="button">按鈕</button>
複製代碼
/*經過爲樣式添加屬性選擇器,去限制樣式的做用域*/
.button[data-v-039c5b43] {
width: 50px;
height: 40px;
}
複製代碼
雖然咱們建議爲組件樣式添加做用域,可是不必定必須使用vue提供的attribute scoped
,對於組件庫之類可能須要在外部覆蓋樣式,若是使用attribute scoped
,由於屬性名不肯定,且樣式權重較高,致使樣式覆蓋很困難.
這時候更建議使用相似BEM之類的命名規範來約束,這讓覆寫內部樣式更容易,使用了常人可理解的 class 名稱且沒有過高的選擇器優先級,並且不太會致使衝突。好比element ui 和 vant 均使用了BEM
將複雜頁面拆分紅多個多個組件文件
你有沒有見過一個Vue文件裏面有一大坨密密麻麻的模板代碼,模板代碼裏面還加載了大量的v-if
,v-for
,v-show
之類的指令,我不知道你看到以後感受怎麼樣,對於小編來講,這無疑是地獄,各類邏輯耦合到一塊兒,改bug比蜀道還要難 對於一個複雜的頁面,咱們建議將頁面按照模塊/功能進行拆分,而後寫成多個小的,單一的組件,而後在主入口文件中引用。好比,對於一個複雜的頁面,咱們能夠拆分紅
header.vue
main.vue
footer.vue
三個文件,而後在三個文件內完成各自的邏輯,最後經過將三個組件都引入主入口文件,來實現頁面的拼裝。 這樣作的好處包括
prop應該儘可能詳細
對比下面的兩段代碼
// 第一段
export default {
props:['status','data']
}
// 第二段
export default {
props:{
status: {
type: Boolean,
default: true
},
data:{
type: Array,
required: true
}
}
}
複製代碼
對比上面兩段代碼,經過第二段代碼咱們能夠很清楚的知道組件須要什麼屬性,屬性的類型是什麼,默認值是什麼,是不是必須的,這樣作的好處包括:
組件名應該由多個單詞組成
對於組件名應該由多個單詞組成的必要性,我想到了本身曾經見過的一段代碼
<header class="header">
<!--欄目-->
<ul>
<li>首頁</li>
<li>關於</li>
</ul>
</header>
複製代碼
看到這段代碼,而後感受很正常,沒啥毛病,而後我看了一眼界面,誒,爲何header左側有一個logo呢?我笑着說,這必定是樣式裏面加的咯,而後看了一眼樣式,wtf,什麼鬼,樣式裏面也沒有加啊,這是怎麼作到的,好神奇。後來就看到了這樣的一段代碼
import Header from '@/components/header'
export default {
components: {
Header
}
}
複製代碼
個人四十米長大砍刀呢!!!!!!
爲何組件名應該又多個單詞組成,由於這樣作能夠避免跟現有的以及將來的 HTML 元素相沖突。更關鍵的是,這樣作不會被打,固然你也能夠作,祝你好運,(手動調皮)。
本文主要參考了:
感謝做者,如侵權當即刪除。若是您以爲本文對您有幫助,但願您能夠給小編一個贊,不勝感激。小手一讚,豔遇不斷,哈哈哈哈哈