隨着js編程進入工程化紀元,代碼模塊化,組件化,成爲工程的具體落地方法。javascript
最近使用vue全家桶作了一個相似於iconfont的網站,在作的過程當中關於組件有了一些思考和總結,爲了鞏固,寫個小結。css
根據我已知的組件的編寫方式,有四種介紹給你們:html
最基本的組件由一個.vue文件構成,其中包含了基本的tempplate,script, style三大元素。前端
能夠經過props接收參數,$emit事件bus向父傳遞參數。vue
比較懶得我通常會在dev階段在components文件夾裏放置一個Demo.vue。寫好基本的元素以及組件註釋。java
import後在組件的compontents中聲明就能夠在模板裏標籤調用了。git
<template>
<!-- 指南中推薦組件名應該始終爲多個單詞的,根組件App,<transition>、<component>之類除外 -->
<Header></Header>
<shop-cart></shop-cart>
</template>
components: { Header, ShopCart }複製代碼
這裏比較注意的是組件命名規範應該嚴格參考vue風格指南。讓駝峯和短橫線在該使用的地方使用。github
構造類組件主要是用在想要經過js動態調用組件的場景裏,由一個該組件文件夾好比notice,中包含Notice.vue, index.js兩個文件組成。vuex
vue文件就是編寫基本的vue文件編程
index.js中
/** 項目添加模態框 */
import Vue from 'vue'
import proModal from './ProModal.vue'
import store from '@/store/index'
import router from '@/router/index'
let proModalInstance
export default {
open (modalType, packageInfoDatail) {
if (!proModalInstance) {
proModalInstance = new ProModalCreater({
el: document.createElement('div'),
store: store,
router: router
})
document.body.appendChild(proModalInstance.$el)
}
proModalInstance.$data.modalType = modalType
proModalInstance.$data.options4 = []
proModalInstance.visible = true
modalType === 'modify'
? (() => {
proModalInstance.$data.packageInfoDetailTemp = packageInfoDatail
proModalInstance.$data.headerName = '修改項目'
proModalInstance.$data.value9 = []
packageInfoDatail.coUsers.map((item) => {
proModalInstance.$data.value9.push(item)
proModalInstance.$data.options4.push(item)
})
})()
: proModalInstance.init()
if (modalType === 'create' && packageInfoDatail) {
proModalInstance.fromPath = packageInfoDatail
}
// proModalInstance.$data.callback = callback
}
}複製代碼
調用:
Vue.prototype._message = obj => {
obj.duration = messageDurationTime
ElementUI.Message(obj)
}
this._message.info('why so serious?')複製代碼
import ProModal from '@/components/common/proModal'
methods: {
createPro () {
// 打開模態框
ProModal.open('create')
},
}複製代碼
全局組件主要是用在一些通用組件想要在各處組件裏使用標籤調用的場景,組成與構建組件相同。
vue文件就是編寫基本的vue文件(該注意的點仍是多注意下,全局對通用,顆粒的要求更高一些
index.js中
import NoContentComponent from './NoContent.vue'
// 添加install方法 (插件方法)
const NoContent = {
install: function (Vue) {
Vue.component('NoContent', NoContentComponent)
}
}
// 導出Buttonexport
default NoContent複製代碼
在全局main.js中引入組件對象使用Vue.use()註冊該組件
Vue.use(NoContent)複製代碼
在各個組件中經過標籤直接調用
<no-content v-if="!Array.isArray(iconLibNowDetail.icons)">
<template slot="default"> <span>尚未上傳圖標哦</span> <upload-btn :toPath="'/upload?type=iconLib&id=' + libId"></upload-btn> </template> </no-content>複製代碼
指令類主要是使用Vue.directive方法註冊一個指令,在指令中bind的方法中去實例組件並添加到響應dom處。這裏很少說,由於我沒用到。(想看怎麼用的去看參考Vue組件的三種調用方式)
其結構相似於全局組件,只是調用是經過在某個元素上的指令屬性進行調用。
好了,知道怎麼寫一個基本的組件了,路程剛剛開始,那麼如何寫好一個組件呢。若是你寫的組件是爲了目的而寫不考慮設計原則,相信很快就會被你本身所拋棄,而後重構組件。(小夥伴說我這一節寫的步驟有些亂不太好,後面會改進)
先說下個人組件設計思路:
這一節起的有點節題黨,這裏只是分享一點點點總結,不敢談設計,後續有好的總結會更新上來,大佬們輕拍哈哈
組件在一些場景中會變得複雜,其複雜性分爲組件自己的複雜和被應用場景的複雜。
自己比較複雜的組件如dataTimerPicker,Form之類的擁有複雜的配置項屬性以及methods,events,而且其中會包含子組件,子組件的slot,attributes,methods也會不少。
這裏僅僅分享三個場景:
1. 我在作一個IconList,當時想要一次性在組件中所有作好,就不想再多抽出子組件,結果發現會寫的很冗餘。因而很快就抽出了icon組件,IconList接受icons數組數據,在v-for中將item對象再傳入icon組件,icon中經過props拿到iconData,最終用來渲染出最終顯示的icon。
固然還能夠再對icon進行子組件抽取的,我目前仍是採用配置參數iconModalType方式+v-if來區分項目中和圖標庫內在不一樣權限下,三種modal層的顯示。後面能夠繼續使用mixIn(IconModal.vue中使用)+調用時<icon-modal :modalType="icon.modalType">方式來加載。
組合大於繼承,不用一次性去寫一個龐然大物,這樣會在複用的時候束手束腳失去靈活性。
2. 我在作一個FilterGroup,肯定了其核心是InputSearch結果到了後面發現仍是會遇到核心不肯定場景。因而這個時候FilterGroup只爲ui服務,子元素能夠經過slot來加載,slot中經過name將子組件放置到對應位置。下面是個demo,我當時就將InputSearch和Sort只做爲了FilterGroup中的元素來處理了,致使了後續須要經過很長的配置項在group上去肯定groupElement上的屬性,使Group自己屬性被混淆減弱了自身含義,增長了複用時理解難度。
<!-- group合理設計應該爲使用slot插入須要的groupElement而不是直接去集成div,即便是很是固有化的元素,如其中的兩個元素:排序和搜索元素 -->
<btn-group inputPlaceVal="請搜索圖標" :useSort="true" @sort="proSort" :sortOptions="options" @search="searchIcon" >
<template slot="body">
<div class="radius-btn" v-if="_isProManager() >= 2" @click="createPro">
<img :src="iconAddLib" alt="">
</div>
</template>
</btn-group>複製代碼
正確的是應該去考衡抽出的必要性,假如該元素不復雜不須要傳遞數據自身無複雜方法,固定爲ui項,就能夠經過配置屬性來取決其是否顯示,好比element的input的icon,使用prefix-icon
和 suffix-icon
屬性在 input 組件首部和尾部增長顯示圖標,固然在句尾說清了:也能夠經過 slot 來放置圖標 。由於slot伴隨着子組件的編寫,也是有代價的,因此對於一些默認最小項,我的認爲能夠內置編寫好,經過配置屬性來顯示。
固然,能夠看到,slot對於一個組件是多麼的重要,一個複雜的子組件,一定不是一次性在組件內寫好的,而是通過提取優化思考獲得的一個組合結果,而且經得起復用和靈活擴展。
3. 我在作一個BatchOperate,批量操做組件時發現本身須要經過得到兄弟組件iconlist中被批量選擇的icon的id數據,而且將這些icon加入ShopCart,這個時候對於數據以及狀態的考量就來了。
最後選用了vuex加LocalStorage方式來解決了這個數據通訊的問題。(有點晚了,先不細說...)
這幾個場景事最想表達的是:
在模塊化思想的今天,這種抽出組合的思惟是很靈活的,能夠在寫組件的時候多去思考下模塊化,包括公共方法,公共樣式,vue的mixIn,scss的mixIn,公共變量倉庫store集中處理,組件最下化,讓重複性代碼模塊化抽出,再經過配置靈活組合。這種作法可讓代碼在後續的維護中很是清爽,一鍵修改專制各類公共改動,不再用跑到各個地方去作一下下的修改,而且避免了耦合帶來的深層代碼纏繞,能夠說真的很好用了。
今天先寫到這,第三節總結的不是很好,只是先羅列出本身以前想到的一些問題和處理,具體的優化想法會和組內小夥伴討論後再更新的。