First, component encapsulation involves knowledge points

  • Vue basic syntax
  • Component base syntax
  • Component communication (sync, provide, Inject)
  • Use of slots
  • Props check
  • Transitions and animation
  • Evaluate properties and listen properties
  • V – model syntactic sugar
  • Vue plug-in mechanism
  • NPM release

Second, component packaging practice harvest

  • Master the syntax and techniques of component encapsulation
  • Learn how to build wheels and how the Element-UI component library works
  • Build and accumulate your own component library

Create your own component packaging project

1. Use vuE-CLI to create a component package project

vue create hhz-components
Copy the code

2. After the project is created, delete the HelloWorld. Vue component under components folder, delete the static resources under Asset folder, and finally delete the Reference, use and style of HelloWorld component in app. vue. (Don’t forget to remove the component registration below Components.) Now you have a clean project ready, and start your component encapsulation journey!

I want to verify that the project is clean.

cd hhz-components
npm run serve
// If the project starts normally, a clean project preparation has been completed.
Copy the code

4. Encapsulate the first of its own components — Button

Vue = hhzbutton.vue = hhzbutton.vue = hhzbutton.vue = hhzbutton.vue = hhzbutton.vue = hhzbutton.vue = hhzbutton.vue

<template>
    <div>I am the button component of soul Zhang</div>
</template>

<script>
    export default {
        name: 'hhzbutton'
    }
</script>

<style scoped>

</style>
Copy the code

2. Register wrapped components as global components in the main.js configuration file

// Import components first
import hhzbutton from './components/hhzbutton/hhzbutton.vue'
The first parameter is registered as the name defined by the global component. The second parameter is registered as the component structure
// The component you imported above
Vue.component(hhzbutton.name,hhzbutton)
Copy the code

3. Use components in app.vue

<template>
  <div id="app">// Use the component here<hhzbutton>The button HHZ</hhzbutton>
  </div>
</template>

<script>
// Import components
import hhzbutton from './components/hhzbutton/hhzbutton.vue'
export default {
  components: {
    hhzbutton // Register the component here}},</script>

<style>

</style>

Copy the code

4, run the project, if the successful operation and show that I am the soul soul zhang button component, that component packaging the first step, is also a key step, has been successful, the following formally open the component packaging journey!

Experience tells us to always turn off ESLint checking during development!! Or install the Prettier ESLint plugin to check and format yourself, don’t choose Standard, you’ll regret it!!

5. Now that you have a basic understanding of the steps for encapsulating and referencing components, let’s begin to encapsulate a real Button component from above. Write the button.vue file to the following code:

<template>
    <div>
        <button  class="hhz-button">
            <span>
                <slot></slot>
            </span>
        </button>
    </div>
</template>

<script>
    export default {
        name: 'hhzbutton'
    }
</script>

<style lang="scss" scoped>
  .hhz-button{
    display: inline-block;
    line-height: 1;
    white-space: nowrap;
    cursor: pointer;
    background: #ffffff;
    border: 1px solid #dcdfe6;
    color: # 606266;
    -webkit-appearance: none;
    text-align: center;
    box-sizing: border-box;
    outline: none;
    margin: 0;
    transition: 0.1 s;
    font-weight: 500;
    -moz-user-select: none;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    padding: 12px 20px;
    font-size: 14px;
    border-radius: 4px;
    &:hover,
    &:hover{
      color: #409eff;
      border-color: #c6e2ff;
      background-color: #ecf5ff; }}</style>
Copy the code

The entire component includes the HTML part of the Template tag, the JS part of the script (the component logic code), and finally the component style part. When you look at it, you’ll see that your component has a style, really just like a component in the component library, and of course the style can be customized according to your own preferences.

6. Add the type attribute to the button component, and make it choose different styles according to the different class names when using the HHzButton component and then change the style. This is a component of the same type that binds multiple properties and then gets the desired style of the component depending on the consumer’s choice.

To get non-styling components based on their types, you need guidance on how to perform component communication and how to use validation to improve security.

  • Props check

// When encapsulating components, props are checked to improve security

// props: ['type']
props:{
    type: {
        type: String,
        default: 'default'
    }
},
Copy the code
  • Parent-child component communication

Parent components communicate by defining the props property on the child component, and then using that variable as a property where the parent component uses the child component, so that the child component can get the property values passed by the parent component.

// The parent component uses this variable as a property and sets the property value
<hhzbutton type="info"< / > HHZ button hhzbutton ><hhzbutton type="danger">HHZ button</hhzbutton>
// The child component can receive data from the parent component, and can use it.
<button  class="hhz-button" :class="[`hhz-button-${type}`]">
            <span>
                <slot></slot>
            </span>
</button>
Copy the code
  • Child component variable property

According to the parent component passed the property value, the child component gets the property value after binding to the dynamic class property above, and then set the corresponding CSS property under the component file, you can change the style of the button according to the user’s Settings.

.hhz-button-primary{
    color:#fff;
    background-color: #409eff;
    border-color: #409eff;
    &:hover,
    &:focus{
    background: #66b1ff;
    background-color: #66b1ff;
    color: #fff;
    }
  }
  .hhz-button-success{
  color:#fff;
  background-color: #67c23a;
  border-color: #67c23a;
  &:hover,
  &:focus{
    background: #85ce61;
    background-color: #85ce61;
    color: #fff;
    }
  }
  .hhz-button-info{
  color:#fff;
  background-color: #909399;
  border-color: #909399;
  &:hover,
  &:focus{
    background: #a6a9ad;
    background-color: #a6a9ad;
    color: #fff;
    }
  }
  .hhz-button-warning{
  color:#fff;
  background-color: #e6a23c;
  border-color: #e6a23c;
  &:hover,
  &:focus{
    background: #ebb563;
    background-color: #ebb563;
    color: #fff;
    }
  }
  .hhz-button-danger{
  color:#fff;
  background-color: #f56c6c;
  border-color: #f56c6c;
  &:hover,
  &:focus{
    background: #f78989; background-color: #f78989; color: #fff; }}Copy the code

7. Plain type encapsulation, which means that when a component is used in a parent component, all buttons become plain when a plain attribute is used. For the same reason, when wrapping a component, you define the style first, and use the Boolean returned by the parent component to determine whether to enable naive style. When the child component receives plain, it also binds it to the class name, which uses objects on the class name binding because it returns a Boolean value. Finally, the plain data is defined in props.

  • Definition of a naive button style
// Plain style definition
.hhz-button.is-plain{
  &:hover,
  &:focus{
    background: #fff;
    border-color: #489eff;
    color: #409eff;
  }
}
.hhz-button-primary.is-plain{
  color: #409eff;
  background: #ecf5ff;
  &:hover,
  &:focus{
    background: #409eff;
    border-color: #409eff;
    color: #fff;
  }
}
.hhz-button-success.is-plain{
  color: #67c23a;
  background: #c2e7b0;
  &:hover,
  &:focus{
    background: #67c23a;
    border-color: #67c23a;
    color: #fff;
  }
}
.hhz-button-info.is-plain{
  color: #909399;
  background: #d3d4d6;
  &:hover,
  &:focus{
    background: #909399;
    border-color: #909399;
    color: #fff;
  }
}
.hhz-button-warning.is-plain{
  color: #e6a23c;
  background: #f5dab1;
  &:hover,
  &:focus{
    background: #e6a23c;
    border-color: #e6a23c;
    color: #fff;
  }
}
.hhz-button-danger.is-plain{
  color: #f56c6c;
  background: #fbc4c4;
  &:hover,
  &:focus{
    background: #f56c6c; border-color: #f56c6c; color: #fff; }}Copy the code
  • Add the variable plain to the props subcomponent
    props:{
            
            plain: {type: Boolean.default: false}},Copy the code
  • The parent component binds the plain property
    / / the parent component
    <hhzbutton plain  class="hhzbutton" type="info"< / > HHZ button hhzbutton ><hhzbutton plain  class="hhzbutton" type="danger">HHZ button</hhzbutton>
    <hhzbutton plain  class="hhzbutton" type="success">HHZ button</hhzbutton>
    <hhzbutton plain  class="hhzbutton" type="primary">HHZ button</hhzbutton>
    / / child component
    <button  class="hhz-button" :class="[`hhz-button-${type}`,{ 'is-plain':plain }]">
    Copy the code
  • Button event binding

Child in the parent components used in the components, and in the use of binding on the subcomponents of an event, if not to deal with child components, for the child components binding events, events that the parent component is invalid, so in summary, in the use of a component, want to let this component have ability to bind an event, you need to the binding event processing component itself. Take click event as the criterion. When the component is clicked in the parent component, the child component will receive the clicked signal, but the child component itself has no ability to process click event, so it needs to bind click event in the child component and write event function in methods, which is very critical. Because it needs to return this event to the parent component, the handler logic defined in the parent component is executed!

/ / the parent component
<hhzbutton @click="printABC" class="hhzbutton" type="info"</hhzbutton> methods:{printABC(){
     console.log(132); }}/ / child component
 <button  class="hhz-button" :class="[`hhz-button-${type}`,{ 'is-plain':plain }]"
       @click="handleClick"
       >
       
 methods:{
     // When the parent component registers a click event, the click event of the child component is triggered. The child component only needs the click event
     // Tell the click event and pass it back to the parent so that the parent owns the click event and executes its own defined click event
     handleClick(e){
       this.$emit('click',e); }},Copy the code
  • Disabled Attribute encapsulation

The wrapper for the Disabled property is almost identical to the wrapper for the plain property in that the parent component passes the value. The child component defines the default value of the disabled property as false, then defines the post-disabled property style, and finally binds the dynamic class! This property can be added to a child component as long as it is used in the parent component and the child component acquires the value.

//html
 <button  class="hhz-button" :class="[`hhz-button-${type}`,{ 'is-plain':plain, 'is-disabled': disabled } ]"
       :disabled="disabled"
       @click="handleClick"
       >
 //js
 props:{
       type: {
           type: String.default: 'default'
       },
       plain: {type: Boolean.default: false
       },
       disabled: {
         type: Boolean.default: false}},/ / the parent component<! -- disabled --><hhzbutton @click="printABC" class="hhzbutton" type="info" disabled>HHZ button</hhzbutton>
   <hhzbutton class="hhzbutton" type="danger" disabled>HHZ button</hhzbutton>
   <hhzbutton class="hhzbutton" type="success" disabled>HHZ button</hhzbutton>
   <hhzbutton class="hhzbutton" type="primary" disabled>HHZ button</hhzbutton>
Copy the code

5. Button component packaging is completed