在 Vue 中更優雅的封裝第三方組件
一、需求場景描述
實際開發的時候,為了減少重復造輪子,提高工作效率,節省開發時間成本, 免不了會使用ui組件庫,比如在web前端很受歡迎的element-ui。但有的時候,我們需要在原組件的基礎上做些改造,比如一個image組件, 我們需要統一在圖片加載失敗的時候展示的特定圖,每次使用組件都加一遍, 麻煩耗時,關鍵是維護成本高,當需要更新這個加載出錯的圖片時, 得再次一個個去找到使用該組件的地方修改。
再例如自定義分頁組件也很常見,組件的樣式,默認支持的每頁數目, 封裝之后再用,在可維護性和開發效率上都很有好處。
然而也不至于從0開始寫一個分頁組件,在原有基礎上封裝就好, 那么如何快速優雅的封裝一個第三方組件庫的組件呢?v-bind=attrs和v?on=attrs和v-on=attrs和v?on=listeners=$listeners,會給我們帶來驚喜。它們可以使得封裝后的組件, “繼承”原組件的幾乎所有v-bind屬性和v-on事件,且用法和作用與在原組件一樣。
封裝el-image為custom-image組件,所有使用custom-image展示圖片的地方, 圖片加載過程中都會統一展示“加載中...”的提示,且當加載出錯時,會展示統一的默認圖。下面是一個custom-image組件加載過程以及加載出錯的效果。

二、關鍵技術點介紹
1.v-bind=$attrs
v-bind=$attrs的妙用是在創建更高級別的組件,在封裝第三方組件時,
可以自動將在父作用域中使用的v-bind的屬性自動綁定,
并向下傳入被封裝的使用了v-bind=$attrs的組件。
一段摘自vue官網的介紹
包含了父作用域中不作為prop被識別 (且獲取) 的attribute, 綁定 (class和style除外)。當一個組件沒有聲明任何prop時, 這里會包含所有父作用域的綁定 (class和style除外), 并且可以通過v-bind=$attrs傳入內部組件——在創建高級別的組件時非常有用。例如我們封裝的custom-Image組件,使用了v-bind=$attrs之后,我們在custom-Image組件中,也擁有了el-image的幾乎所有屬性, 而且其作用效果和用法,是和我們使用el-image是一樣的,也就說我們可以看著el-image的文章去使用custom-Image。
2.v-on=$listeners
v-on=listeners的作用和用法與v?bind=listeners的作用和用法與v-bind=listeners的作用和用法與v?bind=attrs類似,它可以將父作用域中的使用v-on的時間監聽器向下傳入到使用了v-on=listeners組件中,和v?bind=listeners組件中,和v-bind=listeners組件中,和v?bind=attrs的功效類似,只不過一個屬性一個是事件。還是custom-Image組件為例,這時候custom-Image組件就擁有了el-image組件的幾乎所有事件。而且其作用效果和用法,是和我們使用el-image是一樣的。
包含了父作用域中的 (不含.native修飾器的)v-on事件監聽器。
它可以通過v-on=$listeners傳入內部組件——在創建更高層次的組件時非常有用。一段摘自 vue 官網的介紹
三、封裝el-image的代碼示例
使用custom-Image組件的示例
<custom-Image fit=fill class=icon-img :src=picPreview(expert)></custom-Image>
封裝el-image為custom-Image組件的示例
<template>
<div id=CustomImage>
<el-image v-bind=$attrs v-on=$listeners>
<div slot=error class=image-slot>
<img :src=require('image-f/icon-empty-img.png') alt=圖片加載失敗.png/>
</div>
<div slot=placeholder class=placeholder-slot>加載中...</div>
</el-image>
</div>
</template>
<script>
export default {
name: 'CustomImage'
}
</script>
<style scoped lang=scss>
#CustomImage {
.image-slot {
text-align: center;
}
.placeholder-slot {
text-align: center;
}
}
</style>