美文网首页大前端刷级之路
关于element el-button使用$attrs的一个注意

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

作者: 天驱丶 | 来源:发表于2018-11-08 14:33 被阅读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>
    
    

    相关文章

      网友评论

        本文标题:关于element el-button使用$attrs的一个注意

        本文链接:https://www.haomeiwen.com/subject/oprwxqtx.html