前言
在最近的項目開發中經常使用餓了麼開源的ui框架element,所以也藉此機會深入一下element源碼。
源碼目錄
瞭解一個開源項目先從它的目錄開始。
-
package文件中存放了所有component組件的代碼,其中theme-chalk存放了組件的樣式代碼
-
type文件中放的是ts的類型聲明文件
-
test文件中是各個組件的單元測試用例
-
example文件中是element組件的示例
-
src文件是element組件的入口,導入了所有組件
-
bulid文件是構建的配置腳本,包含webpack與deploy
-
其他單文件則是babel的配置 eslint配置 makefile編譯文件等
button-group
<template>
<div class="el-button-group">
<slot></slot>
</div>
</template>
<script>
export default {
name: 'ElButtonGroup'
};
</script>
button組的代碼還是很簡單的,就是一個button容器,內部包含一個匿名插槽
button
組件結構
template>
<button
class="el-button"
@click="handleClick"
:disabled="buttonDisabled || loading"
:autofocus="autofocus"
:type="nativeType"
:class="[
type ? 'el-button--' + type : '',
buttonSize ? 'el-button--' + buttonSize : '',
{
'is-disabled': buttonDisabled,
'is-loading': loading,
'is-plain': plain,
'is-round': round,
'is-circle': circle
}
]"
>
<i class="el-icon-loading" v-if="loading"></i>
<i :class="icon" v-if="icon && !loading"></i>
<span v-if="$slots.default"><slot></slot></span>
</button>
</template>
可以看到主要是button的屬性主要是class的構成。通過使用vue支持的對象數組class語法,很簡單就完成了class的組合構成,其中loading與disable有一個互斥的邏輯。
js邏輯
export default {
name: 'ElButton',
inject: {
elForm: {
default: ''
},
elFormItem: {
default: ''
}
},
props: {
type: {
type: String,
default: 'default'
},
size: String,
icon: {
type: String,
default: ''
},
nativeType: {
type: String,
default: 'button'
},
loading: Boolean,
disabled: Boolean,
plain: Boolean,
autofocus: Boolean,
round: Boolean,
circle: Boolean
},
computed: {
_elFormItemSize() {
return (this.elFormItem || {}).elFormItemSize;
},
buttonSize() {
return this.size || this._elFormItemSize || (this.$ELEMENT || {}).size;
},
buttonDisabled() {
return this.disabled || (this.elForm || {}).disabled;
}
},
methods: {
handleClick(evt) {
this.$emit('click', evt);
}
}
};
js的邏輯也不復雜,通過inject和props接受對應的屬性,其中inject是element實現的屬性用於跨級組件數據傳遞。 計算屬性計算了button的size和disabled屬性 其中size的計算引入了fromitem的size,算是對在from中使用button的一個優化吧,
結論
button主要是通過接受不同的屬性來組合class,不同的class渲染不同的樣式,主要了解vue的slot和對象數組組合的class語法,就可以很簡單的看懂button的源碼