近年來,vue越來越火,使用它的人也越來越多。vue基本用法很容易上手,但是還有很多優化的寫法你就不一定知道了。本文列舉了一些vue常用的開發技巧。
require.context()
在實際開發中,絕大部分人都是以組件化的方式進行開發。隨之而來就有了許多的組件需要引入。比如以下場景:
import outExperInfo from "@/components/userInfo/outExperInfo";
import baseUserInfo from "@/components/userInfo/baseUserInfo";
import technicalExperInfo from "@/components/userInfo/technicalExperInfo";
import skillExperInfo from "@/components/userInfo/skillExperInfo";
components:{
outExperInfo,
baseUserInfo,
technicalExperInfo,
skillExperInfo
}
這樣寫並沒有錯,但是仔細觀察發現寫了很多重複的代碼,這個時候利用require.context()可以寫成:
const path = require('path')
const files = require.context('@/components/userInfo', false, /\.vue$/)
const userComponents = {}
files.keys().forEach(key => {
const name = path.basename(key, '.vue')
userComponents[name] = files(key).default || files(key)
})
components:userComponents
這樣不管需要引入多少組件,都可以使用這一個方法。
路由的按需加載
隨着項目功能模塊的增加,引入的文件數量劇增。如果不做任何處理,那麼首屏加載會相當的緩慢,這個時候,路由按需加載就閃亮登場了。
webpack< 2.4 時
{
path:'/',
name:'home',
components:resolve=>require(['@/components/home'],resolve)
}
webpack> 2.4 時
{
path:'/',
name:'home',
components:()=>import('@/components/home')
}
import()方法是由es6提出的,動態加載返回一個Promise對象,then方法的參數是加載到的模塊。類似於Node.js的require方法,主要import()方法是異步加載的。
動態組件
場景:如果項目中有tab切換的需求,那麼就會涉及到組件動態加載,一般寫法如下:
<component v-bind:is="currentTab"></component>
這樣寫也沒有錯,但是如果這樣寫的話,每次切換的時候,當前組件都會銷燬並且重新加載下一個組件。會消耗大量的性能,所以 就起到了作用。
<keep-alive>
<component v-bind:is="currentTab"></component>
</keep-alive>
有的小夥伴會說,這樣切換雖然不消耗性能了,但是切換效果沒有動畫效果了,彆着急,這時可以利用內置的
<transition>
<keep-alive>
<component v-bind:is="currentTab"></component>
</keep-alive>
</transition>
components和vue.component
前者是局部註冊組件,用法如下:
export default{
components:{home}
}
後者是全局註冊組件,主要針對一些全局使用的組件,用法如下:
Vue.component('home',home)
Vue.nextTick
Vue.nextTick()方法在下次DOM更新循環結束之後執行延遲迴調,因此可以頁面更新加載完畢之後再執行回調函數。下面介紹幾個常用場景:
場景一
<template>
<div>
<div ref = "ref"/>
</div>
</template>
<script>
export default {
created(){
console.log(this.$refs.ref)
//undefined
})
}
}
</script>
因爲這個時候created階段dom並未完全渲染完成,所以獲取值爲undefined,我們對其改造一下:
<template>
<div>
<div ref = "ref"/>
</div>
</template>
<script>
export default {
created(){
Vue.nextTick(()=>{
console.log(this.$refs.ref)
})
//<div></div>
})
}
}
</script>
這樣就可以獲取到dom了。
場景二
<template>
<div>
<div v-if="visible" ref = "ref"/>
</div>
</template>
<script>
export default {
data() {
return {
visible: false
};
},
showRef() {
this.visible = true;
console.log(this.$refs.ref);
//undefined
},
}
}
</script>
因爲這個時候雖然visible的值爲true,但是頁面dom並沒有更新完成,所以獲取值爲undefined,我們對其改造一下:
<template>
<div>
<div v-if="visible" ref = "ref"/>
</div>
</template>
<script>
export default {
data() {
return {
visible: false
};
},
showRef() {
this.visible = true;
Vue.nextTick(()=>{
console.log(this.$refs.ref)
})
//<div></div>
},
}
}
</script>
這樣就可以獲取到dom了。
Vue.directive
場景:官方給我們提供了很多指令,但是我們如果想將文字變成指定的顏色定義成指令使用,這個時候就需要用到Vue.directive,示例如下:
// 全局定義
Vue.directive("change-color",function(el,binding,vnode){
el.style["color"]= binding.value;
})
// 使用
<template>
<div v-change-color>{{message}}
</div>
</template>
<script>
export default{
data(){
return{
color:'green'
}
}
}
</script>
Vue.set()
當在項目中直接設置數組的某一項的值,或者直接設置對象的某個屬性值,這個時候,你會發現頁面並沒有更新。這是因爲Object.defineprototype()限制,監聽不到變化。
解決方式:
- this.$set(你要改變的數組/對象,你要改變的位置/key,你要改成什麼value)
this.$set(this.arr, 0, "OBKoro1"); // 改變數組
this.$set(this.obj, "c", "OBKoro1"); // 改變對象
- 數組原生方法觸發視圖更新,vue可以監聽到數組原生方法導致的數據數據變化
splice()、 push()、pop()、shift()、unshift()、sort()、reverse()
意思是使用這些方法不用我們再進行額外的操作,視圖自動進行更新。
推薦使用splice方法會比較好自定義,因爲slice可以在數組的任何位置進行刪除/添加操作
事件修飾符
- .stop:阻止冒泡
- .prevent:阻止默認行爲
- .self:僅綁定元素自身觸發
- .once: 2.1.4 新增,只觸發一次
- passive: 2.3.0 新增,滾動事件的默認行爲 (即滾動行爲) 將會立即觸發,不能和.prevent 一起使用
- .sync 修飾符
從 2.3.0 起vue重新引入了 .sync 修飾符,但是這次它只是作爲一個編譯時的語法糖存在。它會被擴展爲一個自動更新父組件屬性的 v-on 監聽器。示例代碼如下:
<comp :foo.sync="bar"></comp>
會被擴展爲:
<comp :foo="bar" @update:foo="val => bar = val"></comp>
當子組件需要更新 foo 的值時,它需要顯式地觸發一個更新事件:
this.$emit('update:foo', newValue)
長列表性能優化(數據凍結)
衆所周知,vue會通過object.defineProperty對數據進行劫持,進而實現頁面實時相應數據的變化,然而我們有些時候,需要的僅僅就是純粹的展示數據,因爲數據不會有任何改變,我們就不需要vue來劫持我們的數據。在數據量很大的情況下,這可以很明顯的減少加載時間。
那麼如何實現禁止vue劫持我們的數據尼?可以通過object.freeze方法來凍結數據,凍結之後數據也就不能再修改了。示例如下:
let longList = [
{name:'monkeysoft'},
...
]
this.longList = Object.freeze(longList)
如果覺得還不錯,可以關注一波我的公衆號,不定期更新