一、github地址
https://github.com/ElemeFE/element/blob/dev/packages/button/src/button.vue
二、文档地址
https://element.eleme.cn/#/zh-CN/component/button
三、解析过程(很多注释在源代码是不合法的,这里只是为了更直观的展示)
<template>
<button
class="el-button" // 注解1
@click="handleClick" // 注解2
:disabled="buttonDisabled || loading" // 注解3
:autofocus="autofocus"
:type="nativeType"
:class="[ // 注解4
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> // 注解5
<i :class="icon" v-if="icon && !loading"></i> // 注解6
<span v-if="$slots.default"><slot></slot></span> // 注解7
</button>
</template>
<script>
export default {
name: 'ElButton',
// 注解3
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;
},
// 注解3
buttonDisabled() {
return this.disabled || (this.elForm || {}).disabled;
}
},
methods: {
// 注解2
handleClick(evt) {
this.$emit('click', evt);
}
}
};
</script>
1. 基础样式.el-button
image.png
2. 点击事件,$emit
这里这么做真的是太聪明了,通过传递回给父组件,与vue原来的@click事件名字又一样,做到了无感传递了!Vue中点击子组件触发父组件调用事件的流程如下:
// 父组件Parent.vue
<children @emitName="parentFunc"></children>
...
parentFunc(event) {
console.log('点我干嘛');
}
// 子组件Children.vue
<button @click="handleClick">我是子组件的按钮</button>
...
handleClick(event) {
this.$emit('emitName', event);
}
3.HTML <button> 标签的disabled属性
// 当buttonDisabled即按钮设置了不可点击,或者loading即设置了loading且loading为true时禁止点击按钮
:disabled="buttonDisabled || loading"
buttonDisabled详解:
buttonDisabled() {
// this.disabled: 调用时设置的disabled,
// (this.elForm || {}).disabled: 获取到父组件注入返回的对象或返回一个对象的函数(没注入就为{},为了避免报错吧)里的disabled属性
return this.disabled || (this.elForm || {}).disabled;
}
Vue官方文档API的详解: inject
4. 动态class
这里用了第三种:class="[classA, { classB: isB, classC: isC }]"
<!-- class 绑定 -->
<div :class="{ red: isRed }"></div>
<div :class="[classA, classB]"></div>
<div :class="[classA, { classB: isB, classC: isC }]">
对应的就是红框里这几个参数,可去饿了么官方文档F12看具体样式
5. loading图标
image.png
image.png
6.icon
// 有传入icon属性且没有loading的时候
<i :class="icon" v-if="icon && !loading"></i>
DOM结构为
search样式有定义
7. 默认插槽
如果有默认插槽则提供插槽位置:
<span v-if="$slots.default"><slot></slot></span> // 注解7
// 对于这样的情况,<slot> 元素有一个特殊的特性:name。这个特性可以用来定义额外的插槽:
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot> // 这里!就为默认
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
一个不带 name 的 <slot> 出口会带有隐含的名字“default”。










网友评论