在使用vue的過程中,妳會遇到各種場景,正常使用時沒什麽感覺,但也許妳可以通過優化來更高效、更美觀地開發它。以下是我在日常開發中使用的壹些技巧,會不定期更新~
1.多圖表調整大小事件的分散化
1.1的總體情況
有時我們會遇到這樣的場景,壹個組件中有幾個圖表,我們希望在調整瀏覽器大小時調整圖表的大小,因此我們將在父容器組件中編寫:
已安裝(){
setTimeout(()= & gt;window . on resize =()= & gt;{
這個。$ refs . chart 1 . chartwrapperdom . resize()
這個。$ refs . chart 2 . chartwrapperdom . resize()
// ...
}, 200)
已銷毀(){window。onresize = null}這樣,如果圖表組件與父容器組件不在同壹頁面上,子組件的狀態將由父組件管理。為了維護的方便,我們自然希望子組件的事件和狀態由我們自己來維護,這樣我們就不需要在添加或刪除組件時去父組件逐個修改它們。
1.2優化
這裏使用了lodash的節流功能,也可以自行實現。本文也有throttle的實現供參考。以Echarts為例。在每個圖表組件中:
計算值:{
/**
*圖表DOM
*/
chartWrapperDom(){
const DOM = document . getelementbyid(‘consume-analy-chart-wrapper‘)
返回dom & amp& ampecharts . init(DOM)
},
/**
* Chart resize throttling,在使用lodash的地方,您也可以使用setTimout自己實現節流。
*/
chart resize(){
return _。throttle(()= & gt;this.chartWrapperDom & amp& ampthis.chartWrapperDom.resize(),400)
}
},
已安裝(){
window . addevent listener(‘resize‘,this.chartResize)
},
已銷毀(){
window . removeeventlistener(‘resize‘,this.chartResize)
}2.全局過濾器註冊
2.1總體情況
如何正式註冊過濾器:
導出默認值{
data(){ return { } },
過濾器:{
order by(){
// doSomething
},
大寫字母(){
// doSomething
}
}
但是當我們做壹個項目時,大多數過濾器應該是全局使用的,我們不會在每次使用它們時都將它們寫在組件中。最好把它們畫成全局的。官方登記總體情況的方式:
//寄存器
vue . filter(‘我的過濾器‘,函數(值){
//返回處理後的值。
})
// getter,它返回註冊的篩選器。
Varmyfilter = vue。filter(‘my-filter‘),但把它寫得零散不美觀,所以可以提取到壹個單獨的文件中。
2.2優化
我們可以解壓到壹個獨立的文件中,然後使用Object.keys在main.js入口註冊/src/common/filters.js。
let dateServer = value = & gtvalue . replace(/(\ d { 4 })(\ d { 2 })/g,“$1-$2-$3“)
導出{日期服務器}
/src/main.js
‘將*作為自定義從‘導入。/通用/篩選器/自定義‘
Object.keys(自定義)。forEach(key = & gt;vue . filter(key,custom【key】))然後我們就可以愉快地使用我們在other中定義的這些全局過濾器了。vue文件。
& lt模板& gt
& ltsection class =“content“& gt。
& ltp & gt{{時間|日期服務器} } & lt/p & gt;& lt!-2016-01-01-》;
& lt/section & gt;
& lt/template & gt;
& lt腳本& gt
導出默認值{
data(){
返回{
時間:20160101
}
}
}
& lt/script & gt;3.全球組件註冊
3.1總體情況
需要使用組件的場景:
& lt模板& gt
& ltbase input v-model =“search text“@ keydown . enter =“search“/& gt。
& ltbase button @ click =“search“& gt;
& ltbase icon name =“search“/& gt。
& lt/base button & gt;
& lt/template & gt;
& lt腳本& gt
從‘導入BaseButton。/baseButton
從‘導入BaseIcon。/baseIcon
從“”導入BaseInput。/baseInput
導出默認值{
組件:{ BaseButton、BaseIcon、BaseInput }
}
& lt/script & gt;我們寫了壹堆基本的UI組件,然後每次需要使用這些組件時,我們都要先導入它們,然後再聲明組件,這非常繁瑣。我們可以在這裏使用統壹註冊的形式。
3.2優化
我們需要使用工件webpack通過require.context()的方法創建自己的模塊上下文,從而實現自動動態require組件。該方法需要三個參數:要搜索的文件夾目錄、是否應該在其子目錄中搜索以及與文件匹配的正則表達式。我們將壹個名為componentRegister.js的文件添加到components文件夾中,並在webpack的幫助下將所有需要的基本組件動態打包到該文件中。/src/components/component register . js
從“vue”導入Vue
/**
*首字母大寫
* @param str字符串
* @示例呵呵哈哈
* @return {string}呵呵哈哈
*/
函數大寫首字母(str ){
返回str . charat(0)。toupper case()+str . slice(1)
}
/**
*符合‘xx/xx . vue‘組件格式的組件名稱。
* @param str文件名
* @示例abc/bcd/def/basicTable.vue
* @return {string} BasicTable
*/
函數驗證文件名(字符串){
返回/^\S+\.vue$/。測試與測試。& amp
str.replace(/^\S+\/(\w+)\.vue$/,(盧比,$ 1)= & gt;大寫首字母($1))
}
const require component = require . context(。/‘,true,/\。vue$/)
//查找名為的文件。組件文件夾下的vue。如果文件名是index,則將組件中的名稱作為註冊的組件名稱。
requireComponent.keys()。forEach(file path = & gt;{
const component config = require component(file path)
const fileName = validateFileName(文件路徑)
const component name = filename . tolower case()= = =‘index‘
?大寫首字母(componentConfig.default.name)
:文件名
Vue.component(組件名,組件配置。默認值||組件配置)
})文件夾結構如下:
成分
│ componentRegister.js
├─BasicTable
│ BasicTable.vue
├─MultiCondition
│ index.vue這裏對組件名稱進行判斷。如果是index,組件中的name屬性將被處理為註冊的組件名稱,因此最終註冊的組件是:多條件、基本表。最後我們在main.js中導入‘components/component register . js’,然後我們就可以隨時隨地使用這些基礎組件了,無需手動介紹~
4.不同路線的組件重用
4.1場景還原
當vue-router在某個場景中從/post-page/a跳轉到/post-page/b時。然後我們驚奇地發現頁面跳轉後數據沒有更新?!原因是vue-router“智能地”發現這是同壹個組件,然後它決定重用該組件,因此您在創建的函數中編寫的方法從未執行。通常的解決方案是監視$route的變化以初始化數據,如下所示:
data() {
返回{
加載:假,
錯誤:空,
帖子:空
}
},
觀察:{
$ route“:{//使用watch監視是否是同壹條路由。
處理程序:resetData,
即時:正確
}
},
方法:{
resetData(){
this.loading = false
this.error = null
this.post = null
this . get post(this。$route.params.id)
},
getPost(id){ }
}4.2優化
那麽如何才能達到這種效果呢?答案是給router-view添加壹個不同的鍵,這樣只要url改變,即使是公共組件也會被重新創建。
& ltrouter-view:key =“$ route . full path“& gt;& lt/router-view & gt;您還可以在其後添加++new Date()時間戳以確保唯壹性。
5.高階分量
5.1總體情況
//父組件
& ltBaseInput :value=“值“
Label=“密碼“
Placeholder=“請填寫密碼“
@ input =“handle input“
@ focus =“handle focus“& gt;
& lt/base input & gt;
//子組件
& lt模板& gt
& lt標簽& gt
{{ label }}
& lt輸入:value =“value“
:placeholder=“占位符“
@ focus =“$ emit(‘focus‘,$event)“
@ input =“$ emit(‘input‘,$ event . target . value)“& gt;
& lt/label & gt;
& lt/template & gt;5.2優化
1從父組件傳遞到子組件的每個props只有在子組件的Props中顯式聲明時才能使用。這樣,我們的子組件每次都需要聲明大量的props,我們實際上可以使用$attrs將類似placeholer的dom原生屬性直接從父級傳遞到子級,而無需聲明。該方法如下:
& lt輸入:value =“value“
v-bind =“$ attrs“
@ input =“$ emit(‘input‘,$ event . target . value)“& gt;$attrs包含父範圍中未被識別(和獲取)為正確的屬性綁定(類和樣式除外)。當壹個組件沒有聲明任何prop時,它將包含父作用域的所有綁定,並且它可以通過v-bind =“$ attrs”-傳遞到內部組件中,這在創建更高級別的組件時非常有用。
2.請註意,子組件@ focus =“$ emit(‘focus‘,$event)”實際上什麽也不做,只是將事件返回給父組件,這實際上與上面類似,並且絕對沒有必要顯式聲明:
& lt輸入:value =“value“
v-bind =“$ attrs“
v-on =“listeners“/& gt。
計算值:{
listeners(){
返回{
...這個。$聽眾,
輸入:event = & gt
這個。$ emit(‘輸入‘,event.target.value)
}
}
}$listeners包含父範圍中的v-on事件偵聽器(沒有。原生修飾符)。它可以通過v-on =“$ listeners”傳入內部組件-在創建更高級別的組件時非常有用。
需要註意的是,由於我們的輸入不是組件BaseInput的根節點,因此默認情況下,未被識別為props的父範圍的屬性綁定將“回退”並作為普通HTML屬性應用於子組件的根元素。所以我們需要設置inheritAttrs: false,這些默認行為將被刪除,這樣以上兩點的優化才能成功。
6.根據開發狀態延遲加載路線。
6.1總體情況
通常,當我們在路線中加載組件時:
從“@/views/login.vue”導入登錄
導出默認新路由器({
路由:【{ path:“/log in”,name:“log in”,component: Login}】
})當您需要延遲加載時,您需要將routes的組件更改為()= & gt導入(@/views/login.vue)非常麻煩。
當您擁有越來越多的項目頁面時,在開發環境中使用延遲加載將變得不合適,並且每次更改代碼以觸發熱更新時它都會變得非常慢。因此,建議僅在生產環境中使用路由延遲加載功能。
6.2優化
根據Vue的異步組件和Webpack的代碼拆分功能,可以輕松實現組件的惰性加載,例如:
const Foo =()= & gt;導入(。/foo . vue’)
在區分開發環境和生產環境時,可以在routing文件夾下創建兩個新文件:_ import _ production.js。
module.exports = file = & gt()= & gt導入(“@/views/“+file+“)。vue’)
_import_development.js,這個編寫版本的vue-loader至少是v13.0.0。
module.exports = file = & gt要求(“@/views/“+file+“)。vue)。系統默認值
在設置路由的router/index.js文件中:
const _import = require(。/_ import _‘+process . ENV . node _ ENV)
導出默認新路由器({
路由:【{ path:“/log in”,name:“log in”,component:_ import(‘log in/index’)}】
})這樣的組件不是懶於在開發環境中加載,而是懶於在生產環境中加載。
7個vue裝載機齒尖
Vue-loader是壹個webpack加載程序,可處理*。vue文件。它本身提供了豐富的API,其中壹些非常實用但很少為人所知。例如,下面將介紹preserveWhitespace和transformToRequire。
7.1使用preserveWhitespace減小文件大小
有時當我們編寫模板時,我們不希望元素之間有空格。我們可以這樣寫:
& ltul & gt
& lt李& gt1111 & lt;/李& gt& lt李& gt2222 & lt/李& gt& lt李& gt333 & lt/李& gt
& lt/ul & gt;當然,還有其他方法,例如設置字體的font-size: 0,然後單獨設置所需內容的字體大小,以消除元素之間的空格。事實上,我們完全可以通過配置vue-loader來實現這壹需求。
{
vue: {
preserveWhitespace: false
}
}它的作用是防止元素之間產生空白內容,在Vue模板編譯後用_v(““)表示。如果項目中有許多模板,它們仍然會占用壹些文件卷。例如,在元素配置此屬性後,文件卷在不壓縮的情況下減少了近30Kb。
7.2使用transformToRequire,您不必再將圖片編寫為變量。
以前寫Vue的時候,我經常會寫這樣壹段代碼:提前把圖片傳遞給壹個變量,然後再傳遞給組件。
& lt模板& gt
& ltp & gt
& ltAVATAR:DEFAULT-src =“DEFAULT _ AVATAR“& gt;& lt/avatar & gt;
& lt/p & gt;
& lt/template & gt;
& lt腳本& gt
導出默認值{
已創建(){
這個。DEFAULT_AVATAR = require(。/assets/default-avatar . png’)
}
}
& lt/script & gt;事實上,在配置transformToRequire後,可以直接配置它,這樣vue-loader將自動要求相應的屬性,然後將它們傳遞給組件。
{
vue: {
transformToRequire: {
頭像:【‘默認-src‘】
}
}
}所以我們的代碼可以簡化很多。
& lt模板& gt
& ltp & gt
& lt頭像默認-src=“。/assets/default-avatar . png“& gt;& lt/avatar & gt;
& lt/p & gt;
& lt/template & gt;在vue-cli的webpack模板下,默認配置為:
transformToRequire: {
視頻:【src,‘海報‘】,
來源:“src”,
img:“src”,
image:“xlink:href”
}您可以通過類比進行類似的配置。
Vue-loader也有許多實用的API,例如最近添加的自定義塊。感興趣的人可以在文檔中查找它們。
8.渲染功能
在某些場景中,您可能需要render渲染功能帶來的完整編程能力來解決不易解決的問題,尤其是在標簽和組件類型被動態選擇的場景中。
8.1動態標簽
1.概況
例如,根據道具生成標簽的場景。
& lt模板& gt
& ltp & gt
& ltp v-if =“level =