之前需要對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
柒爸。
發(fā)現(xiàn)問題
在某個頁面,點擊經(jīng)過封裝的limit-button
會使頁面進行刷新
- 起初以為是點擊事件的冒泡產(chǎn)生的事扭,就把上層引用的
@click
去掉:
<limit-button
type="warning"
size="small"
buttonId="2345434fg"
>
點擊
</limit-button>
發(fā)現(xiàn)還是一樣會產(chǎn)生刷新的事件捎稚。
- 思考可能是
$listeners
的問題,在mounted
中打印也只有@click
事件求橄,就算去掉$listeners
也不管用今野。 - 后來在瀏覽器對dom結構的查看,發(fā)現(xiàn)
limit-button
編譯后變成:
可以看到編譯后的type
變成了warning
罐农,查element
的源碼可發(fā)現(xiàn)<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>
可發(fā)現(xiàn)是$attrs
覆蓋了el-button
的nativeType
問題簡化重現(xiàn)
<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>