大前端刷级之路

关于element el-button使用$attrs的一个注意

2018-11-08  本文已影响0人  天驱丶

之前需要对el-button做二次封装,所以就用到vue$attrs$listeners属性,这两个属性在这不细说,可以在 这里 查看详情。

二次封装代码(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: {
    // 按钮唯一标识
    buttonId: {
      type: String,
      required: true,
    },
  },

  computed: {
    ...mapGetters(['getUserBtns']),
    validButton: function() {
      return env.debug ? true : this.getUserBtns[this.buttonId];
    },
  },
};
</script>

这样封装的好处就是不需要将上层每个属性都写一次prop定义,对listeners也不需要做一层中转emit

发现问题

在某个页面,点击经过封装的limit-button会使页面进行刷新

  1. 起初以为是点击事件的冒泡产生的,就把上层引用的@click去掉:
<limit-button
    type="warning"
    size="small"
    buttonId="2345434fg"
>
点击
</limit-button>

发现还是一样会产生刷新的事件。

  1. 思考可能是$listeners的问题,在mounted中打印也只有@click事件,就算去掉$listeners也不管用。
  2. 后来在浏览器对dom结构的查看,发现limit-button编译后变成:
    button
    可以看到编译后的type变成了warning,查element的源码可发现
    <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>
    

可发现是$attrs覆盖了el-button的nativeType

问题简化重现

<el-form ref="form" :model="form" label-width="80px">
  <el-form-item>
    <button type="primary">点击会刷新</button>
    <button type="button" @click="onSubmit">点击不会刷新</button>
  </el-form-item>
</el-form>

重现链接

解决方法

type分出来props,然后再通过 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: {
    // 按钮唯一标识
    buttonId: {
      type: String,
      required: true,
    },
    type: {
        type: String,
    }
  },

  computed: {
    ...mapGetters(['getUserBtns']),
    validButton: function() {
      return env.debug ? true : this.getUserBtns[this.buttonId];
    },
  },
};
</script>

上一篇下一篇

猜你喜欢

热点阅读