El-button needs to be wrapped twice, so we use the $listeners and $attrs properties of Vue. We won’t go into detail on these two properties, but you can see them here.

Secondary wrapping code (limit-button)

<template>
  <el-button
      v-show="validButton"
      v-bind="$attrs"
      v-on="$listeners"
  >
    <slot></slot>
  </el-button>
</template>

<script>
import { mapGetters } from 'vuex';
import env from '@/config/env';

export default {
  props: {
    // Unique identifier of the button
    buttonId: {
      type: String.required: true,}},computed: {
    ...mapGetters(['getUserBtns']),
    validButton: function() {
      return env.debug ? true : this.getUserBtns[this.buttonId]; ,}}};</script>

Copy the code

The advantage of this encapsulation is that you don’t need to write a prop definition for each of the upper properties, nor do you need to emit a layer of listeners.

Found the problem

On a page, clicking a wrapped limit-button causes the page to refresh

  1. At first thought it was the bubbling of the click event, the upper referenced@clickRemove:
<limit-button
    type="warning"
    size="small"
    buttonId="2345434fg"
>Click on the</limit-button>
Copy the code

Discovery still generates a refresh event.

  1. Thinking might be$listenersThe problem ofmountedIn print also only@clickEvents, let’s get rid of them$listenersIt didn’t work.
  2. Later in the browser to view the DOM structure, foundlimit-buttonAfter compiling, it becomes:

    You can see the compiled versiontypeTurned out to bewarningCheck,elementThe source code can be found

    <button
        class="el-button"
        @click="handleClick"
        :disabled="buttonDisabled || loading"
        :autofocus="autofocus"
        :type="nativeType"
        .
      >
        <i class="el-icon-loading" v-if="loading"></i>
        <i :class="icon" v-if="icon && ! loading"></i>
        <span v-if="$slots.default"><slot></slot></span>
    </button>
    Copy the code

$attrs overrides the nativeType of el-Button

Problem reduction and recurrence

<el-form ref="form" :model="form" label-width="80px">
  <el-form-item>
    <button type="primary">Click on it and it will refresh</button>
    <button type="button" @click="onSubmit">Clicking won't refresh</button>
  </el-form-item>
</el-form>
Copy the code

Back links

The solution

Break out the type as props and reference it through prop

<template>
  <el-button
      :type="type"
      v-show="validButton"
      v-bind="$attrs"
      v-on="$listeners"
  >
    <slot></slot>
  </el-button>
</template>

<script>
import { mapGetters } from 'vuex';
import env from '@/config/env';

export default {
  props: {
    // Unique identifier of the button
    buttonId: {
      type: String.required: true,},type: {
        type: String,}},computed: {
    ...mapGetters(['getUserBtns']),
    validButton: function() {
      return env.debug ? true : this.getUserBtns[this.buttonId]; ,}}};</script>

Copy the code