从三个方面着手:DOM结构,数据传递,事件触发
1.DOM结构:
<button></button>
2.数据属性
- props获取父组件传递过来的数据
- 引用computed计算出相关的数据变化
- 事件: 父子组件通信,子组件向父组件发消息可以用$emit实现,父组件监听$on即可
1)样式绑定
:class="[
type ? 'el-button--' + type : '',
buttonSize ? 'el-button--' + buttonSize : '',
{
'is-disabled': buttonDisabled,
'is-loading': loading,
'is-plain': plain,
'is-round': round,
'is-circle': circle
}
]"
class与style的绑定使用vue的数组语法可以将多个样式对象应用到同一个元素上
2)插槽
插槽就是子组件中的提供给父组件使用的一个占位符,用<slot></slot>
表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的<slot></slot>
标签。
<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有一个互斥的逻辑。
<script>
export default {
name: 'ElButton',
inject: {
elForm: {
default: ''
},
elFormItem: {
default: ''
}
},
props: {
type: {
type: String,
default: 'default' //类型 string primary / success / warning / danger / info / text
},
size: String, //尺寸 string medium / small / mini
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);
}
}
}
</script>
通过inject和props接收对应的属性数据,我们知道project / inject用于高阶组件的编写,可以跨组件传递数据,
computed计算button的size和disabled属性 其中size的计算引入了formItem的size
总结
button主要是通过接收不同的class属性数据来组合class,不同的class渲染不同的样式,了解了vue的slot和对象数组语法,就很容易了解button的源码内容。