"Build your own UI component library from 0 to 1" -- button component

Write before:

I am "boiling sheep"_ , the nickname comes from the abbreviation fyy of the name. The blog that worked hard before was cancelled due to the accident of hand injury. Now it runs this account.
I am a small dish, working hard in the direction of the whole stack of engineers, the article may not be high-yield, but also very basic, but every article is in the heart of summing up, please don't spray.
If you are interested in programming, please pay attention to my trends and study together.
Thank you!

Article catalog

preface

As the first article in this column, encapsulating the most commonly used button components, let's first look at the button style encapsulated by the element UI component library. After reading the whole article, you can have your own button component.

Knowledge points

  • Component communication
  • slot
  • props verification

Initialize project

New vue item current:

  • Ensure that nodeJs is installed, and enter the test command: node -v to test whether the installation is successful
  • Install Vue cli, input the installation command from the terminal: npm install -g vue cli, test command: vue --version

To ensure that the above steps are completed, we can create a new vue project. We use the webpack packaging tool, so the terminal input the command: vue init webpack FYy UI (project name), and select our project configuration according to the prompt information.

Encapsulate button components

File configuration

  • First, new button.vue file
  • App.vue And main.js The file Vue cli is generated for us. We just need to App.vue The default data in the file can be cleared.
  • At main.js File, import and mount button.vue Documents.
//main.js
import FyyButton from './components/button.vue'
Vue.use(ElementUI)

Button background color

effect:

// button.vue

<template>
  //: class = "[` FYy button -- ${type} `]": represents the type value passed by the parent component whose style is "FYy button --"
  <button class="fyy-button" :class="[`fyy-button--${type}`]">
    //Use slot for parent component to pass button name
    <slot></slot>
  </button>
</template>

export default {
  //Set component name, use this name when using
  name: "FyyButton",
  props: {
    //Receive parameter: type
    type: {
      //Parameter type: String
      type: String,
      //Default is default
      default: "default"
    }
  }
};

<style lang="scss" scoped>
	//button component encapsulation, mainly for style presentation, will publish the overall code structure of the project to github.
</style>
//Parent component-- App.vue
<template>
  <div id="app">
    <div class="row">
      //Type is the style type passed to the subcomponent
      <FyyButton @click="click">Button</FyyButton>
      <FyyButton type="primary">Button</FyyButton>
      <FyyButton type="success">Button</FyyButton>
      <FyyButton type="info">Button</FyyButton>
      <FyyButton type="warning">Button</FyyButton>
      <FyyButton type="danger">Button</FyyButton>
    </div>
  </div>
</template>

Simple button

effect:

//button.vue

<template>
  //The plain button adds the {'is plain': plain} class style to the normal button, which represents the plain attribute passed by the value as the parent component
  <button class="fyy-button" :class="[`fyy-button--${type}`,{'is-plain':plain}]">
    <slot></slot>
  </button>
</template>

export default {
  //Set component name, use this name when using
  name: "FyyButton",
  props: {
    //Receive parameter: type
    type: {
      //slightly
    },
    //Receiving parameter: plain
    plain: {
      type: Boolean,
      default: false
    }
  }
};
<style lang="scss" scoped>
	//Style omitted. button component encapsulation is mainly style display. The overall code structure of the project will be published to github.
</style>
//Parent component-- App.vue

<template>
  <div id="app">
    <div class="row">
      //Type is the style type passed to the subcomponent
      <FyyButton @click="click">Button</FyyButton>
      <FyyButton type="primary">Button</FyyButton>
      //Others
    </div>
    <div class="row">
      <FyyButton plain>Button</FyyButton>
      <FyyButton plain type="primary">Button</FyyButton>
      //Others
    </div>
  </div>
</template>

Fillet button

effect:

//button.vue

<button class="fyy-button" :class="[`fyy-button--${type}`,{'is-plain':plain,'is-round':round}]">
<script>
export default {
	props: {
		round: {
	      type: Boolean,
	      default: false
	    }
	}
}
//Parent component- App.vue

<div class="row">
  <FyyButton plain round>Button</FyyButton>
  <FyyButton plain round type="primary">Button</FyyButton>
</div>

Round button

effect:

//Code omitted

icon button

effect:

Some codes are omitted.

// Parent component App.vue 

<div class="row">
	<FyyButton plain class="fyy-icon-pencil" round>Button</FyyButton>
	<FyyButton plain class="fyy-icon-pencil" round type="primary">Button</FyyButton>
</div>

icon + text button

If users want button s with both icon and text, they will find that icon and text are next to each other. If a space is added in the middle, it will look better. How to ensure that there is a space between icon and text, and that there is no space when there is only text or icon? How to achieve this?

effect:

//button.vue

<template>
  <button
    class="fyy-button"
    :class="[`fyy-button--${type}`,{'is-plain':plain,'is-round':round,'is-circle':circle}]"
  >
    //If the parent component passes an icon
    <i v-if="icon" :class="icon"></i>
    //When the parent component does not have an incoming slot, the span tag is not displayed$ slots.default All slots can be obtained to determine whether the parent component passes slots
    <span v-if="$slots.default">
      <slot></slot>
    </span>
  </button>
</template>

<style lang="scss" scoped>
	// icon and text exist at the same time in button, set margin value
	.fyy-button [class*="fyy-icon-"] + span {
	  margin-left: 5px;
	}
</style>

click event

When we use the components of element or other component libraries, we will find that the click of other components can not be triggered by @ click except that the button can use @ click. Why?

Because element only encapsulates the click event of button component, because it is very common. The click events of other components are not encapsulated. If they are not, how can we use them? If you use encapsulated components, you need to add. Native after the event to trigger the native event. For example:@ click.native Click event can be triggered.

Let's now encapsulate a click event for the button.

//button.vue

<template>
  <button
    class="fyy-button"
    :class="[`fyy-button--${type}`,{'is-plain':plain,'is-round':round,'is-circle':circle}]"
    @click="handleClick()"
  >slightly</button>
</template>
<script>
	methods: {
    handleClick(e) {
      this.$emit("click", e);
    }
  }
</script>

In this way, @ click can be used in the parent component to trigger the click event.

Parameter support

Parameter name Parameter description type Default
type Button type (primary / success / warning / danger / info) string default
plain Is it a simple button boolean false
round Is it a fillet button boolean false
circle Is it a prototype button boolean false
icon Icon class name string nothing

Event support

Event name Event description
click Click event

github address

github address of FY UI button component

About icon

Element UI has its own font library. We can choose to pick up the source code to take down the font library of element UI. Because the small editor picked up the source code font library and reported an error, it is speculated that the url inside the element UI font library is the relative address. Anyway, the small editor did not solve the error after several hours of struggle. If the reader has picked up the source code font library, we can exchange. Here, I download the icomoon font library. Xiaobian has also placed the icomoon font library file in github hosting, and can go to clone if necessary.

last

There will be mistakes in the column series, please correct them! esteem it a favor. Finally, I hope this column is born smoothly!

Tags: Vue github Webpack Programming

Posted on Tue, 23 Jun 2020 22:30:51 -0400 by creativodev