preface
In order to practice the ability of packaging components, I plan to study Elment UI components and learn their design and code.
The research idea of this paper is to read Element source code, and then automatically write components step by step to improve their corresponding functions.
The first thing we want to study is the Button component, which is the most commonly used and most familiar. We will implement the Button features introduced in the official documentation one by one.
The preparatory work
Create a new empty project using vue-CLI
vue create my-element-ui
Copy the code
Create a Button folder under the Components folder in your project, create an index.vue, and write the code for the Button component. In the root directory, create the Views folder, create the ButtonShownPage folder, and create the index.vue folder to display the button components.
In ButtonShownPage I’ll write
<template> <el-button @click="handleClick"> </el-button> </template> <script> import ElButton from '.. /.. /components/Button/index' export default { name: 'ButtonShownPage', methods: { handleClick(evt) { console.log('handleClick', evt); } }, components: { ElButton } } </script>Copy the code
So we started to focus on coding the Button and getting it rendered properly
Write a basic Button
After some simple fumbling, I wrote the following code in the Button component:
<template>
<button
class="el-button"
@click="handleClick"
>
<span v-if="$slots.default"><slot></slot></span>
</button>
</template>
<script>
export default {
name: 'Button',
methods: {
handleClick(evt) {
this.$emit('click', evt);
}
}
}
</script>
<style>
.el-button {
display: inline-block;
line-height: 1;
white-space: nowrap;
cursor: pointer;
background: #fff;
border: 1px solid #dcdfe6;
color: #606266;
-webkit-appearance: none;
text-align: center;
box-sizing: border-box;
outline: none;
margin: 0;
transition: .1s;
font-weight: 500;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
padding: 12px 20px;
font-size: 14px;
border-radius: 4px;
}
.el-button:focus, .el-button:hover {
color: #409eff;
border-color: #c6e2ff;
background-color: #ecf5ff;
}
.el-button:active {
color:#3a8ee6;
border-color:#3a8ee6;
outline:none
}
</style>
Copy the code
Use the button tag as the base of the component to write styles that include default, focus, hover, and active states. With slot containing the button content, the click event is exposed. The basic buttons are there.
To increase type
Now let’s make our button support type: primary, success, Info, Warning, danger.
Write the test code in ButtonShownPage first:
<el-button @click="handleClick"> default button </el-button> <el-button type="primary"> Main button </el-button> <el-button </el-button> <el-button type="info"> </el-button> <el-button type="warning"> <el-button type="danger"> </el-button>Copy the code
Write logic code in Button:
<template>
<button
class="el-button"
:class="[type ? 'el-button--' + type : '']"
@click="handleClick"
>
<span v-if="$slots.default"><slot></slot></span>
</button>
</template>
<script>
export default {
name: 'Button',
props: {
type: {
type: String,
default: 'default',
},
},
methods: {
handleClick(evt) {
this.$emit('click', evt);
}
}
}
</script>
Copy the code
Add a prop named Type, default to default, and style the button label based on the value passed in. El-button –primary class = “primary”;
.el-button--primary {
color: #fff;
background-color: #409eff;
border-color: #409eff;
}
.el-button--primary:focus, .el-button--primary:hover {
background: #66b1ff;
border-color: #66b1ff;
color: #fff;
}
Copy the code
Add another style like this:
.el-button+.el-button {
margin-left: 10px;
}
Copy the code
You can increase the spacing of the buttons next to each other, as shown in the picture below:
Plain, round and circle
All three are the same as Type in that they add classes to control style
<template>
<button
class="el-button"
:class="[type ? 'el-button--' + type : '',
{
'is-plain': plain,
'is-round': round,
'is-circle': circle
}]"
@click="handleClick"
>
<span v-if="$slots.default"><slot></slot></span>
</button>
</template>
Copy the code
Add the plain, round, and circle properties to props.
props: {
type: {
type: String,
default: 'default',
},
plain: Boolean,
round: Boolean,
circle: Boolean
},
Copy the code
Because there are so many styles to reference and the principle is the same, I use the browser developer tools to copy the elementUI styles directly into assets.
In this way, the effect is as follows:
Our buttons now support multiple forms.
Here, we have copied all the styles of Elemnnt, so we do not need to care about the style writing in the future, but only care about the logic of tags and JS to realize the corresponding functions. However, we can use browser tools to continue to study the style details in the presentation results.
Support icon
Add an Icon component:
<template>
<i :class="'el-icon-' + name"></i>
</template>
<script>
export default {
name: 'ElIcon',
props: {
name: String
}
};
</script>
Copy the code
Introduce the Icon component into the Button,
<template>
<button
class="el-button"
:class="[type ? 'el-button--' + type : '',
{
'is-plain': plain,
'is-round': round,
'is-circle': circle
}]"
@click="handleClick"
>
<el-i :class="icon" v-if="icon"></el-i>
<span v-if="$slots.default"><slot></slot></span>
</button>
</template>
Copy the code
This works:
Disabled state
- Add a property disabled to the component
- Bind the disabled component to the button tag property to ensure that the click event does not take effect
- Add ‘IS-disabled’ to :class: disabled.
The effect is as follows:
Text button, icon button
Our component now supports both styles of buttons.
Button group
Add a ButtonGroup component. Again, the key is the control style
<template>
<div class="el-button-group">
<slot></slot>
</div>
</template>
<script>
export default {
name: 'ElButtonGroup'
};
</script>
Copy the code
Use as follows:
<el-button-group> <el-button type="primary" icon="el-icon-arrow-left"> </el-button> <el-button type="primary"> next < I class="el-icon-arrow-right el-icon--right"></i></el-button> </el-button-group>Copy the code
The rendering looks like this:
In the load
- Add a property loading to the component
- To give the class a ‘is – loading: loading, make disabled, disabled = “disabled | | loading”
<el-i class="el-icon-loading" v-if="loading"></el-i> <el-i :class="icon" v-if="icon && ! loading"></el-i>Copy the code
The effect is as follows:
Size of the button
Same routine as type, add a size attribute, control class.
conclusion
So much for the basic button components. All examples are as follows:
All code for this article has been uploaded to the code cloud: gitee.com/DaBuChen/my…
Other component source code study:
Element component source research -Button
Element component source research -Input Input box
Element component source research -Layout, Link, Radio
Element component source research -Checkbox multi-checkbox
Element component source research -InputNumber counter
Element component source code study -Loading component
Element component source research -Message component