This is the 9th day of my participation in the August More Text Challenge

0 x00 profile

Component tags are mostly used for marking and sorting. This article will be an in-depth analysis of component source code, analysis of its implementation principle, patience to read, I believe will help you. Packages /tag/ SRC /tag.vue files are component source implementations. 🔗 Component documentation Tag 🔗 Github source Tag. Vue

For more component profiling see 👉 📚 Element 2 source profiling Component Overview.

0x01 Component source code

Use the render function to create the component with the following code structure 👇.

<script>
  export default {
    name: 'ElTag'./ / component prop
    props: {
      // ...
    },
    methods: {
      // The event triggered when the Tag is closed
      handleClose(event) {
        // ...
      },
      // The event triggered when a Tag is clicked
      handleClick(event) {
        // ...}},// Calculate attributes
    computed: {
      // Label size
      tagSize() {
        // ...}},// Render the tag virtual DOM
    render(h) {
      // ...}}; </script>Copy the code

The attributes property

The component defines eight prop.

props: {
  text: String.// is not used in the code
  closable: Boolean.// Can be closed
  type: String./ / type
  hit: Boolean.// Whether there is a border stroke
  disableTransitions: Boolean.// Whether to disable gradient animation
  color: String./ / the background color
  size: String./ / size
  / / theme
  effect: {
    type: String.default: 'light'.validator(val) {
      return ['dark'.'light'.'plain'].indexOf(val) ! = = -1; }}},Copy the code

Prop is described in detail as follows (there are only 7) :

parameter instructions type An optional value The default value
type type string success/info/warning/danger
closable Whether it can be closed boolean false
disable-transitions Whether to disable gradient animation boolean false
hit Whether there is a border stroke boolean false
color The background color string
size size string medium / small / mini
effect The theme string dark / light / plain light

Text is defined in prop but is not used in the code. If the values of type, size, and effect do not match the specified string, an invalid class is generated based on the values (the style rule is not defined).

Calculate attribute

TagSize dynamically calculates the tagSize based on size and $ELEMENT.

If the component defines prop size, the tagSize value is the value defined by size. If size is undefined and “”, the tagSize value is determined by the global $ELEMENT configuration.

If the $ELEMENT object is not empty and contains the size attribute, the tagSize value is the object’s attribute value $element.size. Otherwise, the tagSize value is undefined,

// Label size
tagSize() {
    return this.size || (this.$ELEMENT || {}).size;
}
Copy the code

As you know, the $ELEMENT global configuration is defined in the install method in the component entry file. Where the default size value for the component is “”.

// SRC /index.js component entry file
const install = function(Vue, opts = {}) {
  // ... 
  // The default size of the global configuration component size the initial z-index of the popbox
  Vue.prototype.$ELEMENT = {
    size: opts.size || ' '.zIndex: opts.zIndex || 2000
  };
  // ...
};
Copy the code

When a component is fully imported and registered with vue.use(), the install method is executed and the global attribute $ELEMENT is declared.

import Element from 'element-ui'; 
Vue.use(Element);

// Manually set the default size of the component
Vue.use(Element, { 
  size: "small"});Copy the code

Prototype $ELEMENT = {size: ‘small’, zIndex: 3000}; If $ELEMENT is not defined, Uncaught ReferenceError will be raised if $ELEMENT is not defined.

import { Tag } from 'element-ui' 
 
// Global configuration
Vue.prototype.$ELEMENT = { size: 'small'.zIndex: 3000 }; 

// Import components
Vue.use(Tag);
 
Copy the code

Expressions (enclosing $ELEMENT | | {}) to prevent $ELEMENT to prevent abnormal call undefined giving empty object.

Events event

Trigger the click event when a Tag is clicked.

// The event triggered when a Tag is clicked
handleClick(event) {
  // Triggers events on the current instance
  this.$emit('click', event);
}
Copy the code

The close event is emitted when the Tag is closed.

// The event triggered when the Tag is closed
handleClose(event) {
  // Prevents further propagation of current events in the capture and bubble phases.
  event.stopPropagation();
  // Triggers events on the current instance
  this.$emit('close', event);
},
Copy the code

Render () render function

The component will create a element VNode, add classes dynamically, set the background color using inline styles, and define the component click event. The element contains two child nodes

  1. Default slot;
  2. calledel-icon-closetheIconIcon that defines the click event when the Tag is closed. whenclosableA value oftrueWill render.

When the disableTransitions value is true, the zoom Zoom-in-Center effect is achieved by wrapping the element with the built-in component Transition.

// Render the tag virtual DOM
render(h) {
  const { type, tagSize, hit, effect } = this;
  // Add classes dynamically
  const classes = [
    'el-tag',
    type ? `el-tag--${type}` : ' ',
    tagSize ? `el-tag--${tagSize}` : ' ',
    effect ? `el-tag--${effect}` : ' ',
    hit && 'is-hit'
  ];
  / / the tag element
  const tagEl = (
    <span
      class={ classes }
      style={{ backgroundColor: this.color }}
      on-click={ this.handleClick} >
      { this.$slots.default }
      {
        this.closable && <i class="el-tag__close el-icon-close" on-click={ this.handleClose} ></i>
      }
    </span>
  );
  / / component VNode
  return this.disableTransitions ? tagEl : <transition name="el-zoom-in-center">{ tagEl }</transition>;
}
Copy the code

Dynamically add classes based on component Prop.

  • 'el-tag'Component default style.
  • type ? 'el-tag--${type}' : ''Sets the colors of different component types. iftypeValues are notsuccess/info/warning/dangerOne of them, setting invalid (generating invalid class).
  • tagSize ? 'el-tag--${tagSize}' : ''Set different sizes of components. iftagSizeValues are notmedium/small/miniOne of them, setting invalid (generating invalid class).
  • effect ? 'el-tag--${effect}' : ''Set different themes for components. ifeffectValues are notdark/light/plainOne of them, setting invalid (generating invalid class).effectThe default value islight, the correspondingel-tag--lightIs an invalid style, undefined.
  • hit && 'is-hit'Border stroke effect.

The color property defines the component’s inline style backgroundColor, with higher weights overwriting other styles of color.

0x02 Component Style

src/tag.scss

SCSS uses mixed instructions B, M, and genTheme to generate component styles.

GenTheme () Component theme

The genTheme hybrid directive is used to generate theme styles for components.

@mixin genTheme($backgroundColorWeight.$borderColorWeight.$fontColorWeight.$hoverColorWeight) {
  background-color: mix($--tag-primary-color.$--color-white.$backgroundColorWeight);
  // ...
  
  / / generated & is - hit
  @include when(hit) {
    // ...
  }

  .el-tag__close {
    // ...
    &:hover {
      // ...}}// info/success/warning/danger has the same structure
  &.el-tag--info {
    // ...
    
    / / generated & is - hit
    @include when(hit) {
      // ...
    }

    .el-tag__close {
      // ...
      &:hover {
        // ...}}}// success
  // warning
  // danger
  
}
Copy the code

The Mix function mixes two colors together in a certain proportion to produce another color. The first two arguments are the colors you want to mix (you can use color variables, hexadecimal, RGBA, RGB, HSL, or HSLA color values), and the third argument is the scale value of the first color.

mix($color1, $color2, $weight: 50%) //=> color 
Copy the code

The component theme default style is generated directly under el-Tag.

/ / generated. El - tag
@include b(tag) {
  // Theme rules default to light
  @include genTheme(10%.20%.100%.100%);
  // ...
 
  / / generated. El - tag -- -- dark
  @include m(dark) {
    // Theme rules
    @include genTheme(100%.100%.0.80%);
  }
  
  / / generated. El - tag -- -- plain
  @include m(plain) {
    // Theme rules
    @include genTheme(0.40%.100%.100%); }}Copy the code

The theme style generated by combining the above rules is as follows

// El-tag can be replaced with el-tag--dark el-tag--plain
.el-tag {
  // ...
}
.el-tag.is-hit {
  // ...
}
.el-tag .el-tag__close {
  // ...
}
.el-tag .el-tag__close:hover {
  // ...
}
// info/success/warning/danger has the same structure
.el-tag.el-tag--info {
  // ...
}
.el-tag.el-tag--info.is-hit {
  // ...
}
.el-tag.el-tag--info .el-tag__close {
  // ...
}
.el-tag.el-tag--info .el-tag__close:hover {
  // ...
}
// success ...
// warning ...
// danger ...

Copy the code

Component style

The component style logic is as follows.

/ / generated. El - tag
@include b(tag) {
  // The default light style
  // ...
  
  // Generate.el-tag. el-icon-close
  .el-icon-close {
    // ...
    // generate.el-tag. el-icon-close::before
    &::before {
      // ...}}// Dark style...
  // Plaink style...
  
  / / generated. El - tag - medium
  @include m(medium) {
    // ...
    // generate.el-tag--medium. El-icon -close
    .el-icon-close {
      // ...}}/ / generated. El - tag -- -- small
  @include m(small) {
    // ...
    // generate.el-tag--small. El-icon -close
    .el-icon-close {
      // ...}}/ / generated. El - tag -- -- mini
  @include m(mini) {
    // ...
    // generate.el-tag--mini. El-icon -close
    .el-icon-close {
      // ...}}}Copy the code

lib/tag.scss

Gulpfile. js is used to compile the SCSS file and convert it to CSS. After browser compatibility and format compression, packages\theme-chalk\lib\tag. SCSS is generated.

.el-tag{/ /... }.el-tag .el-tag__close{/ /... }.el-tag .el-tag__close:hover{/ /... }/* theme start -- el-tag / el-tag--dark / el-tag--plain -------------------------- */
.el-tag.is-hit{/ /... }.el-tag .el-icon-close{/ /... }.el-tag .el-icon-close::before{/ /... }/* type -- info / success / warning / danger -------------------------- */
.el-tag.el-tag--info{/ /... }.el-tag.el-tag--info.is-hit{/ /... }.el-tag.el-tag--info .el-tag__close{/ /... }.el-tag.el-tag--info .el-tag__close:hover{/ /... } // success ... // warning ... // danger .../* el-tag--dark
-------------------------- */
// ... 

/* el-tag--plain
-------------------------- */
// ... 


/* theme end -- el-tag / el-tag--dark / el-tag--plain -------------------------- */

 

/* size -- medium / small / mini -------------------------- */ 
.el-tag--medium{/ /... }.el-tag--medium .el-icon-close{/ /... }Copy the code

0 x03 📚 reference

“StopPropagation”, MDN “mix funciton color”, sass

0x04 Attention column

This article has been included in the column 👇, you can directly follow.