自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Vue 這個透傳技巧,治好了我的重度代碼潔癖

開發(fā) 前端
今天就用一個Vue基礎組件封裝的過程為例,來簡單聊聊什么是透傳。

 背景介紹

透傳是一個通訊層面的概念,指的是在通訊中不管傳輸的業(yè)務內容如何,只負責將傳輸的內容由源地址傳輸到目的地址,而不對業(yè)務數據內容做任何改變。

其實透傳這個概念,我最早是從上面一個領導那里聽到的,由于他是電氣工程師出身,而硬件通訊這塊用到透傳還是挺多的。

對于透傳,我感覺有那么一點熟悉感,仔細想想后我發(fā)現,其實我們前端也一直在使用透傳,特別是在做基礎封裝時。

透傳在前端的應用

今天就用一個Vue基礎組件封裝的過程為例,來簡單聊聊什么是透傳。

相信不少前端er做項目都會用到組件庫,是ElementUI還是Ant Design,這都不重要。然后我們又希望在第三方組件庫的基礎上再做一點點定制。

舉個例子,el-button有個屬性是size,用于控制按鈕組件的尺寸。

屬性 說明 類型 可選值 默認值
size 尺寸 String medium / small / mini -


可以看到,默認size是比較大的。然而我們設計師基于組件庫出自己的設計方案時,其實選擇的默認按鈕尺寸可能恰好對應ElButton的medium尺寸,或者是其他值。這樣一來,如果我不對el-button做封裝,每個使用el-button的地方都要多寫一個屬性size,類似于這樣: 

  1. // pageA.vue  
  2. <el-button size="medium">按鈕1</el-button>  
  3. <el-button size="medium">按鈕2</el-button>  
  4. // pageB.vue  
  5. <el-button size="medium">按鈕3</el-button>  
  6. <el-button size="medium">按鈕4</el-button> 

很明顯,每使用一次el-button,我就要寫一個size屬性,好煩??!

是的,確實很煩,那么怎么解決呢?答案是提供一個編程接口,去改變組件的默認值。有這方面考慮的組件設計者一般會提供一個設置默認值的接口,比如xxx.setDefault(options)。

那么ElementUI和Ant Design有沒有提供這樣的能力呢?據我觀察好像是沒有,其實主要是因為Vue沒有一個方便的途徑去修改prop的default屬性。但是沒有方便的途徑并不代表沒有途徑...

由于本文的主題是透傳,所以就不說那個途徑(或者說方法)了,有點跑偏了。

網友小王說:“好,那就硬上,封裝一個組件!”

好的,馬上安排!基本思路是封裝一個自定義組件,組件里面再調用el-button,并且強行給el-button安排上默認屬性size="medium"。 

  1. <template>  
  2.     <el-button :size="size">  
  3.         <slot />  
  4.     </el-button>  
  5. </template>  
  6. <script>  
  7. export default {  
  8.     name: "MyButton",  
  9.     props: {  
  10.         size: {  
  11.             type: String,  
  12.             default: 'medium'  
  13.         }  
  14.     }  
  15.  
  16. </script> 

聰明的讀者一看就發(fā)現了,這個組件問題很大,除了size屬性,其他屬性和事件怎么處理完全沒

小王說:“沒事,您需要什么?我給安排上!”

于是,這個組件最后就慢慢變成了: 

  1. <template>  
  2.     <el-button  
  3.         :size="size"  
  4.         :type="type"  
  5.         :disabled="disabled"  
  6.         @click="onClick"  
  7.     >  
  8.         <slot />  
  9.     </el-button>  
  10. </template>  
  11. <script>  
  12. export default {  
  13.     name: "MyButton", 
  14.     props: {  
  15.         size: {  
  16.             type: String,  
  17.             default: "medium",  
  18.         },  
  19.         type: {  
  20.             type: String,  
  21.             default: "primary",  
  22.         },  
  23.         disabled: Boolean,  
  24.     },  
  25.     methods: {  
  26.         onClick() {  
  27.             this.$emit("click");  
  28.         },  
  29.     },  
  30. };  
  31. </script> 

看起來有點糟心,這組件甚至會更冗余,更復雜,因為我這里只加了3個prop和1個event。對于稍微復雜一點的組件來說,prop加上event一共幾十個是隨隨便便的吧!你適配得過來嗎?而且,不少人還有代碼潔癖吧,這簡直受不了!

淡定淡定!這當然是有辦法解決的。強如框架的設計者尤小右自然早已想到了這個場景,所以你應該在Vue官網文檔中關注到inheritAttrs[1]。

如何理解inheritAttrs(默認值為true)這個選項呢?我們知道,一個組件如果要接受父組件傳來的屬性,是需要先在props里面預定義好的。比如前面的例子,我在MyButton預定義了3個屬性,分別是size,type,disabled,意思是MyButton這里只接受3個prop。

那么假設父組件傳了4個或者更多prop過來呢,會怎么樣?看下面這個例子: 

  1. <template>  
  2.     <my-button  
  3.         type="success"  
  4.         disabled  
  5.         round  
  6.         native-type="submit"  
  7.     >測試</my-button>  
  8. </template> 

實際上,round和autofocus都不是MyButton組件支持的prop,所以反映到HTML上是這么一個效果:

作為使用者,我們應該是希望round和native-type="submit"能夠傳到el-button,產生應有的效果。然而,round和native-type="submit"僅僅是掛在了根元素的attribute上,并沒有真正起到應有的作用!

PS:舉個例子,round屬性作用到el-button能讓button帶一個is-round的class,從而產生圓角效果!

也就是說,inheritAttrs的作用是:使那些沒有在props中定義的屬性,直接以attribute的形式作用在組件的根元素上!

那么round和native-type="submit"如何透傳下去呢?

首先,不能讓那些未被props標識的屬性直接落到根元素上,所以需要設置inheritAttrs為false。

然后,要獲取到那些未被props標識的屬性,并直接綁定到el-button。恰好,Vue提供了$attrs[2]用于獲取這些屬性,而v-bind本身就能綁定一個對象,這是容易被我們忽略的!

處理完屬性透傳,接下來我們還要處理事件,類似于$attrs,$listeners也能把父組件中對子組件的事件監(jiān)聽全部拿到,這樣我們就能用一個v-on把這些來自于父組件的事件監(jiān)聽傳遞到下一級組件。

看圖可能會更好理解!

相當于MyButton是一個不賺差價的中間商,直接透傳消息!直觀上看,組件代碼量有一個明顯的減少,更重要的是擴展性和可維護性變得更強! 

  1. <template>  
  2.     <el-button  
  3.         v-bind="customizedAttrs"  
  4.         v-on="$listeners"  
  5.     >  
  6.         <slot />  
  7.     </el-button>  
  8. </template>  
  9. <script>  
  10. export default {  
  11.     name: "MyButton",inheritAttrs:false,  
  12.     props: {  
  13.         size: {  
  14.             type: String, 
  15.             default: "medium",  
  16.         },  
  17.     },  
  18.     computed: {  
  19.         customizedAttrs() {  
  20.             return {  
  21.                 size: "medium",  
  22.                 // 支持傳過來的size覆蓋默認的size  
  23.                 ...this.$attrs,  
  24.             };  
  25.         },  
  26.     },  
  27. };  
  28. </script> 

對于調用者來說,使用體驗是完全沒有被影響的,他的感覺就好像仍然在直接使用el-button,屬性傳遞和事件監(jiān)聽的使用體驗都沒有任何變化! 

  1. <template>  
  2.     <my-button  
  3.         type="success"  
  4.         round  
  5.         autofocus  
  6.         @click="handleClick"  
  7.     />  
  8. </template> 

總結

結合inheritAttrs,v-bind以及v-on,我們就實現了一個支持透傳的基礎組件!本文是以Button組件為例,做的關于透傳的入門介紹。實際上,透傳的應用范圍遠遠不止Button組件,利用透傳的技巧,我們能做更多漂亮的事情!現在,你的代碼潔癖還好嗎? 

 

責任編輯:龐桂玉 來源: 前端大全
相關推薦

2025-04-17 04:22:00

Log插件日志管理

2022-08-31 15:57:11

程序員

2022-09-17 08:10:20

HSV飽和度圖像

2023-07-10 09:53:59

console開發(fā)插件

2025-04-23 08:02:44

2020-05-09 08:09:36

中臺阿里平臺

2020-10-23 09:50:20

鏈表Java代碼

2019-01-16 10:55:08

Python 開發(fā)編程語言

2019-06-26 09:20:38

Java工具Lombok

2019-08-22 15:06:56

線程Java透傳

2021-06-18 13:58:28

ESLint Vue 項目

2019-10-28 11:53:34

戴爾

2019-05-05 11:02:07

vscodevue前端

2024-01-26 08:36:07

OpenAIGPT-4?人工智能

2024-12-27 15:28:10

HBAFC-SAN存儲

2019-08-01 12:56:00

Python代碼記錄

2009-11-23 19:47:57

ibmdwLinux

2021-02-23 09:06:00

MVCC版本并發(fā)

2019-09-29 10:04:26

技術編程開發(fā)
點贊
收藏

51CTO技術棧公眾號