最近在團隊的小組里做了一次關于Vue.js 2.0的一些 最佳實踐 和常見的 采坑記錄 的小分享,這里總結了一下分享給大家~ 如果哪里有問題歡迎大家diss ^_^
代碼規(guī)范
關于代碼規(guī)范,我的理解是不一定非要用什么特別嚴苛的標準或是特別權威的規(guī)范,只要項目團隊遵循一套統(tǒng)一的約定就可以。當然,參考他人的經驗沉淀從而制定自己的代碼規(guī)范還是很有必要的。
1. 對齊
- 靜態(tài)屬性 (static binding) 在前, 動態(tài)屬性 (dynamic binding) 在后
- 屬性綁定 (:屬性)在前, 事件綁定 (@事件) 在后
- 如果有使用指令,則指令語句寫在最前面
e.g:
<!-- bad -->
<li
:name="n.name"
@click="check"
v-for="n in list"
:key="n.id"
class="list-item"
:tag="n.tag"
type="product"
>{{ n.name }}
</li>
<!-- good -->
<li
v-for="n in list"
class="list-item"
type="product"
:key="n.id"
:name="n.name"
:tag="n.tag"
@click="check"
>{{ n.name }}
</li>
2. 簡化的表達式(不要在模版里使用復雜的表達式)
- 對于列表里的數(shù)據表達式,可以用
filter來處理 - 其他情況下,可以使用
computed property
e.g:
<!-- bad -->
<template>
<h1>
{{ `${(new Date()).getUTCFullYear()}-${('0' + ((new Date()).getUTCMonth()+1)).slice(-2)}` }}
</h1>
</template>
<!-- good -->
<template>
<h1>
{{ `${year}-${month}` }}
</h1>
</template>
<script type="text/javascript">
export default {
computed: {
month() {
return this.twoDigits((new Date()).getUTCMonth() + 1);
},
year() {
return (new Date()).getUTCFullYear();
}
},
methods: {
twoDigits(num) {
return ('0' + num).slice(-2);
}
},
};
</script>
3. 組件編碼規(guī)范
- 導出一個清晰、組織有序的組件,使得代碼易于閱讀和理解。同時也便于標準化。
- 能避免操作
dom就盡量避免,實在要用的話最好使用ref來代替querySelector等選擇器方法 - 一個
.vue的文件行數(shù)最好控制在 200 行左右 - 善用
v-if和v-show。比如,涉及到權限的必須用v-if而非v-show。例如,用戶必須登錄后才能查看的,請用v-if - 請盡量保證數(shù)據流的可追蹤性。盡量不要使用
$parent,而是通過props屬性接收父組件的傳入
最佳實踐
1. 屬性綁定
1.1 綁定字符串不需要加冒號
e.g:
<!-- bad -->
<component :message="hello" />
<!-- good -->
<component message="hello" />
1.2 布爾屬性省略值時默認為 true
e.g :
<my-modal visible />
<!--等價于-->
<my-modal :visible="true" />
1.3 HTML原生屬性可以不用 props 綁定 或者 組件特有的特性也不用 props 綁定
e.g:
<component class="className" />
<bootstrap-date-input data-date-picker="activated" />
2. 事件綁定
2. 綁定無參函數(shù)不需要加 ()
e.g:
<!-- bad,括號多余 -->
<button @click="onClick()">按鈕</button>
<!-- good,隱式傳遞了 event 對象 -->
<button @click="onClick">按鈕</button>
2.2 只有一行代碼的事件函數(shù),可以直接寫在標簽上
e.g:
<button @click="visible = !visible">顯示/隱藏</button>
2.3 在監(jiān)聽原生DOM事件時,方法以 事件 為唯一的參數(shù)。如果使用內聯(lián)語句,語句可以訪問一個 $event 屬性:
e.g:
<button @click="handle($event, 1)">click me</button>
如果在父組件中想要給子組件拋出的事件添加自定義參數(shù),可利用此屬性:
e.g: https://jsfiddle.net/hysunny/eywraw8t/228187/
3. 修飾符
Vue 內置了許多常用的 修飾符 ,可以讓你少寫幾行代碼,提高開發(fā)效率。
e.g:
<!-- 阻止單擊事件繼續(xù)傳播 -->
<a v-on:click.stop="doThis"></a>
<!-- 提交事件不再重載頁面 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修飾符可以串聯(lián) -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 只有修飾符 -->
<form v-on:submit.prevent></form>
<!-- 添加事件監(jiān)聽器時使用事件捕獲模式 -->
<!-- 即元素自身觸發(fā)的事件先在此處理,然后才交由內部元素進行處理 -->
<div v-on:click.capture="doThis">...</div>
<!-- 只當在 event.target 是當前元素自身時觸發(fā)處理函數(shù) -->
<!-- 即事件不是從內部元素觸發(fā)的 -->
<div v-on:click.self="doThat">...</div>
4. 按需加載組件
一般配合 Vue-Router 使用,適用于大型應用,將應用分割成小的代碼塊,只在需要的時候才從服務器加載。
實現(xiàn)方式:
- 異步組件實現(xiàn)
- es6 import
好處:
- 按需加載,節(jié)省首次加載實踐,提高速度,也算是一個性能優(yōu)化;
- 組件只會加載一次,加載完成后會緩存下來,使用一個組件多次使用的場景。
e.g:
// 異步組件實現(xiàn)
export default new Router({
routes: [
{
path: '/test',
name: 'test',
component: resolve => require(['../components/Test'], resolve)
},
]
})
// ES6 import
const Test1 = () => import('../components/Test1')
const Test2 = () => import('../components/Test2')
export default new Router({
routes: [
{
path: '/test1',
name: 'test1',
component: Test1
},
{
path: '/test2',
name: 'test2',
component: Test2
}
]
})
5. 過濾器
用于一些常見的文本格式化,如展示發(fā)布時間。
e.g:
<template>
<!-- 在雙花括號中 -->
<span>{{ message | capitalize }}</span>
<!-- 在 `v-bind` 中 -->
<div :message="message | capitalize"></div>
</template>
<script>
export default {
data() {
return {
message:1
}
},
filters: {
capitalize: function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
}
}
}
</script>
6. 多個元素塊可以用template包裹
參考: Vue.js 在-lt-template-gt-元素上使用-v-if-條件渲染分組
e.g:
<template v-if="list.length">
<div>header</div>
<div>list</div>
<div>footer</div>
</template>
<template v-else>
<div>no list</div>
</template>
7. v-for 循環(huán)加 key
當 Vue.js 用 v-for 正在更新已渲染過的元素列表時,它默認用 就地復用 策略。如果數(shù)據項的順序被改變,Vue 將不會移動 DOM 元素來匹配數(shù)據項的順序,而是簡單復用此處每個元素,并且確保它在特定索引下顯示已被渲染過的每個元素。
稍微深入一點,加 key 的原因是為了給 virtualDom中 的 diff 做優(yōu)化,結果就是提高 virtualDom 更新效率。
patch參考: https://github.com/aooy/blog/issues/2
8. 使用頻率較高的方法掛載到Vue實例上
這樣做的好處是不需要每次使用都要 import,提高開發(fā)效率。
e.g:
Vue.prototype.$utils = {
cookie,
formatDate,
...vdom,
getQueryString
}
new Vue();
// 使用
this.$utils.getQueryString('from_url');
9. 多級組件傳遞數(shù)據使用 $attrs 和 $listeners
在 Vue 2.4 版本,配合 interitAttrs 選項,父組件中未被 props(v-on) 綁定的屬性(事件) 可以在子組件中,通過 $attrs, $listeners 獲取。個人認為好處是不用再每個組件都顯式綁定 props 或 事件,壞處是傳遞的屬性或事件不夠明確。一般情況下不需要使用,但是在創(chuàng)建更高層次的組件時非常有用。
參考:
$attrs: https://cn.vuejs.org/v2/api/#vm-attrs
$listeners: https://cn.vuejs.org/v2/api/#vm-listeners
常見的坑
1. 對象和數(shù)組的更新檢測
由于 JavaScript 的限制,Vue 不能檢測以下變動的數(shù)組:
- 當你利用索引直接設置一個項時,例如:
vm.items[indexOfItem] = newValue - 當你修改數(shù)組的長度時,例如:
vm.items.length = newLength
還是由于 JavaScript 的限制,Vue 不能檢測對象屬性的添加或刪除
解決方法: 對于數(shù)組來說可以使用 vm.$set或改用可觀察數(shù)組的變異方法,對于對象來說可以使用 vm.$set 或 Object.assign
e.g. https://jsfiddle.net/hysunny/eywraw8t/228152/
2. mixins同名選項混合問題
當我們想覆蓋一個組件的一些東西或想擴展某個組件時,可以用 Vue 的 mixins
不過要注意:
當組件和混合對象含有同名選項時,同名鉤子函數(shù)將混合為一個數(shù)組,都會被調用;混合對象的鉤子將在組件自身鉤子之前調用。
值為對象的選項,例如methods,components和directives,將被混合為同一個對象。兩個對象鍵名沖突時,取組件對象的鍵值對。
e.g: https://jsfiddle.net/hysunny/eywraw8t/228225/
3. v-if 與 v-for 的優(yōu)先級問題
v-if 與 v-for 一起使用時,v-for 具有比 v-if 更高的優(yōu)先級,因此如果想有條件的跳過循環(huán)的執(zhí)行,則需將 v-if 置于外層元素(或 template)上。如:
<ul v-if="todos.length">
<li
v-for="todo in todos"
:key="todo.id"
>
{{ todo.name }}
</li>
</ul>
<p v-else>No todos left!</p>
4. 遍歷對象順序不一致
使用 v-for 遍歷對象時,是按 Object.keys() 的結果遍歷,但是不能保證它的結果在不同的 JavaScript 引擎 下是一致的。
比如: 在 ios 下當對象的key為字母時,排序為降序,其他機型為升序。
解決方法: 如果要保證順序,可以加個排序的 filter 或者 改用數(shù)組。
參考: https://github.com/vuejs/vue/issues/1827
5. event bus 多次觸發(fā)
$on 的事件可在 created 或 mounted 注冊
需在 beforeDestroy 或 destoryed 的時候使用用 $off 銷毀
否則在某些情況下會被被多次觸發(fā)
e.g. https://jsfiddle.net/hysunny/eywraw8t/232163/
6. 變量命名
變量名不要以_、$開頭,因為名字以 _ 或 $ 開始的屬性不會被 Vue 實例代理,
因為它們可能與 Vue 的內置屬性與 API 方法沖突。
需要用 vm.$data._property 訪問它們。
e.g: https://jsfiddle.net/hysunny/eywraw8t/224835/
7. vue 2.0 給組件綁定事件無效
對于一般的 html 元素,綁定自定義事件使用 v-on即可,但是在某個組件的 根元素 上監(jiān)聽一個 原生事件 ,比如:
<my-component v-on:click="handleClick" />
我們會發(fā)現(xiàn)這樣是不起作用的,可以使用 .native 修飾符(某些情況) 或是 $listeners
<my-component v-on:click.native="handleClick" />
e.g. 用.native給自定義組件綁定事件
哦啦~
以上部分內容參考了: Vue最佳實踐,非常感謝!O(∩_∩)O~