Part 4: Implementing a set of ui component library of vue on pc side from scratch (button component 2)

Keywords: Front-end Mobile Attribute github

Episode 4: Implementation from scratch (button component 2)

Location of this episode:
I've been busy with other things before, but now I'm finally free to write about this library.
The purpose of this article is to carry on the above and realize the function of button component.

1: Add icon to button
The icon of the button is very important. Now the general button has a pattern, because this is in line with the quick thinking of the human brain, easy to understand and remember.

 <button class="cc-button"
          @touchstart='touchstart($event)'
          :class="[ 
          sizeType,
          type ? 'cc-button--' + type : '',
    {
      'is-left':left,
      'is-right':right,
      'is-centre':centre,
      'is-disabled':disabled,
    }]"
          :type="nativeType"
          @click="click">
    <!-- Icon button -->
    <ccIcon v-if="icon"  // Do you have it or not?
            :name='icon' // What does it look like?
            :color="realyIconColor"  // What colour is it?
            style="margin-right:2px" />  // A little distance from words
    <slot />
  </button>

Calculate real IconColor
Icon has the default color, but if the button is disabled, icon should also be ashed accordingly

computed: {
    realyIconColor() {
      if (this.disabled) return "#bbbbbb";
      else return this.iconColor;
    }
  }

2: Location of Icon
It is rare to encounter icon s that require top-down or left-right layout, if necessary.
Scheme 1: Mobile < slot > label or named slot label
Solution 2: Write several more icon components to decide who to display by judging

3: hover effect
Programme 1:

  1. Grey masking effect appears in hover
  2. When clicked, the button reduces the animation
 &:not(.is-disabled) {
        &:active {
            box-shadow: none;
            opacity: 0.7;
            transform: translateX(2px) translateY(2px) scale(0.9);
        }
         &:hover {
            background-color:rgba(0,0,0,0.1)
         }
    }

Design sketch

Programme II:

  1. hover has metallic luster, bulingbuling, metallic luster.
  2. When clicked, the button reduces the animation

In summary, metal gloss passing may become a common property, so let me just write a common style, cc-bling.
My thoughts:

  1. Try using a gradient background color, and then use ackground-position-x to control the right shift of the background.
    This scheme is uncomfortable in practice and does not follow the design principle of'decoupling', so it is not necessary.
  2. Pseudo-element, with a pseudo-element plus background color, and then the element from left to right across, while using animation to tilt it 30 degrees.
    Although there are more elements, they are decoupled from their parents. It is worth mentioning that the height after tilting is not full enough, simple and rough.
    The way is to locate the height a little more, so that the rotation will not lead to a state of insufficient height.

let'go

<button class="cc-button"
  :class="[
    {
      'is-bling':bling, // Added an attribute of acceptance of metallic luster or not.
      'is-left':left,
      'is-right':right,
      'is-centre':centre,
      'is-disabled':disabled,
    }]"
  </button>
 bling:Boolean, // stripe

In button.scss; add

@at-root {
        @include commonType(cc-button--);
        .is-bling {
        //This property name is bling only when it is hover
            &:hover {
                @extend .cc-bling;
            }
        }
    };

animation.scss
Define an animation from left to right

  @keyframes bling{
    0% {
      left: 0;
    }
    100% {
      left: 300%;
    }
  }

extend.scss
Define specific styles

.cc-bling {
    &:after {
        content: '';
        position: absolute;
        background-image: linear-gradient(to right, rgb(232, 229, 229), white);
        left: 0;
        top: -20px; // Avoid spikes in the head when tilting
        width: 15px;
        height: calc(100% + 30px); // Avoid low altitude when rotating
        transform: rotate(-30deg);
        animation-name: bling;
        animation-duration: 1s; // Total time
        animation-iteration-count: infinite; // Infinite cycle
        animation-timing-function: linear; // Uniform velocity
    }
}

The rendering is dynamic, crossing from left to right.

4: Shake-proof and throttling
Introduction: This kind of throttling and anti-shaking are all made by users themselves. At least the button is the component library of this set of things.
Use scenarios:

  1. Once, I wrote the registration page. If the user clicked twice quickly when registering, although he jumped to the successful page of login, he would pop up a pop-up box. "The mobile phone has been registered." It was originally due to the first request to register the mobile phone, so the next click event of course returned to the background has been registered. So here we need to deal with it. Each click is invalid within n seconds after the click is valid, so as to prevent the connection point. (Preventing the gearshift gear, remembering the meteor butterfly sword);
  2. Our company has been engaged in a snap-up activity for 19 years. It may happen that the user keeps the snap-up button and clicks constantly. We need to ask the background's activity started when every user clicks?', and then play tosat to the user before entering the activity or order page. However, if the user is a golden finger and is crazy about snapping up keys, he will make a lot of requests.

Let me say:
First: Why not use the background return activity start time to compare with local events?

   The reason is that the user's local time is not a trustworthy quantity, which can be used as a reference in normal times, but the time synchronization between the user and the server is necessary for such things as snapping up.

Second: Why not record the timestamp after the first request and simulate the timing locally with a timer?

   The reason is that in some browser environments, users cut out programs and other operations, and he will kill the timer, resulting in inaccurate timing, and this problem can not be solved for the time being, nor can it be monitored, so in order to be safe.

Finally, you can only ask for it every time, so you need to let the user click only once every 600 milliseconds, for example.

We can't just write click events, we need to pull them out and ravage them.
dom

 <button class="cc-button"
     @click="click">
  </button>

Connection Value

props: {
    ...,
    shake: Number, // Anti-shaking seconds
    throttle: Number, // Throttle, please enter seconds
    clickId: [String, Number], // Components with the same id go through a set of timers.
}

Event

 click() {
    // According to the user's input, decide how to time.
    // It's worth mentioning that if clickId is the same, we're timing the same time. 
    // For example, three buttons, one of which is clicked, and the others are not clickable within a specified time.
      let clickType, num;
      if (this.throttle) {
        clickType = 1;
        num = this.throttle;
      } else if (this.shake && this.shake > 0) {
        clickType = 2;
        num = this.shake;
      } else if (this.shake && this.shake < 0) {
        clickType = 3;
        num = this.shake * -1;
      }
      prevent(
        this.clickId,
        () => {
          this.$emit("click");
        },
        num,
        clickType
      );
    },

In my previous work, I wrote a function of anti-shake and throttling, which I used directly this time.

let preventList = {}
const prevent = function(id, obj, time, model = 1) {
  switch (model) {
    case 1:
      model1(id, obj, time)
      break;
    case 2:
      model2(id, obj, time)
      break;
    case 3:
      model3(id, obj, time)
      break;
    default:
  }
}

// Mode 1 Triggers every second, regardless of the number of points.
function model1(id, obj, time) {
  if (preventList['can' + id]) return
  obj()
  preventList['can' + id] = true
  preventList['time' + id] = setTimeout(() => {
    preventList['can' + id] = false
  }, time)
}

// Mode 2 Each action has a time delay to execute, that is, to execute one when all clicks are finished.
function model2(id, obj, time) {
  clearTimeout(preventList['time' + id])
  preventList['time' + id] = setTimeout(() => {
    obj()
  }, time)
}

// Default mode, mode 3, first click trigger, then no trigger for a period of time
function model3(id, obj, time) {
  if (preventList['can' + id]) {
    clearTimeout(preventList['time' + id])
  } else {
    obj()
    preventList['can' + id] = true
  }
  preventList['time' + id] = setTimeout(() => {
    preventList['can' + id] = false
  }, time)

}

export default prevent

Specific use

// Subsequent events involving tremor prevention and throttling also follow this procedure.

Next article

  1. The packaging of toast, through the packaging of toast let me consolidate a lot of'cheese'.
  2. Another way to write components

end
During this period, the author resigned, concentrate on source code, practice algorithm, re-learn js, re-learn node, re-do their own packaging tools. Anyway, it's busy. The next time and energy mainly focus on this set of components, but also will produce some algorithms, experience and other articles. Welcome students to communicate and become better together.

github:Link Description
Personal website: Link Description

Posted by MishieMoo on Sat, 20 Jul 2019 23:03:52 -0700