Vue2/3封装按钮Loding
Vue2/3封装按钮Loding
1、Vue3
- 基于如下平常代码,我们可以发现,两个按钮逻辑中,有很多重复代码(
开启loding
,关闭loding
),并且正式项目中会有很多按钮会发送请求
<template>
<el-button @click="test" :loading="loading" type="primary">test</el-button>
<el-button @click="test" :loading="loading22" type="primary">test2</el-button>
</template>
<script setup>
import { ref } from "vue";
const loading1 = ref(false);
const loading2 = ref(false);
function test() {
loading1.value = true;
try {
fetch("http://localhost:8888/getUser?userName=''")
.then((res) => {
return res.json();
})
.then((res) => {
console.log(res);
});
} finally {
loading1.value = false;
}
}
function test() {
loading2.value = true;
try {
fetch("http://localhost:8888/getUser2?userName=")
.then((res) => {
return res.json();
})
.then((res) => {
console.log(res);
});
} finally {
loading2.value = false;
}
}
</script>
- 我们就可以把上面公共的部分提取出来一个组件
1.1、组件代码
<template>
<!-- 使用v-bind=$attrs 把按钮的其他属性绑定过来 -->
<el-button :loading="loading" v-bind="$attrs" @click="handleClick">
<slot></slot>
</el-button>
</template>
<script setup>
import { ref, useAttrs } from "vue";
const loading = ref(false);
const attrs = useAttrs();
// 使用defineProps定义的props的属性,不会在$attrs中存在了
const { onClick } = defineProps({
onClick: Function,
});
async function handleClick() {
console.log("click");
loading.value = true;
try {
// 这里就必须要求onClick的返回值为Promise类型 或者是async函数
await onClick?.();
} finally {
loading.value = false;
}
}
</script>
1.2、使用组件
<template>
<MyLoadingBtn @click="test" type="primary">test</MyLoadingBtn>
</template>
<script setup>
import { ref } from "vue";
import MyLoadingBtn from "./components/MyLoadingBtn.vue";
// 这里必须让test返回为一个promise,或者使用async/await
async function test() {
await fetch("http://localhost:8888/getUser?userName=")
.then((res) => {
return res.json();
})
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log(err);
});
}
</script>
1.3、效果
2、Vue2
Vue2
中和Vue3
中逻辑基本一致,不过要稍微麻烦一点- 因为
Vue2
中父组件传递的所有方法,并不会一起放到$attrs
中,而是会放到$listeners
中,使用不了**在props中声明, a t t r s 对象中不存在的特性 ∗ ∗ ,那么我们就需要对 ‘ attrs对象中不存在的特性**,那么我们就需要对` attrs对象中不存在的特性∗∗,那么我们就需要对‘listeners对象单独处理一下再绑定到
v-on=“xxx”`中- 如果不处理
$listeners.click
函数的话,那么父组件绑定的点击事件函数就会调用两遍!!
2.1、组件代码
<template>
<!-- 这里使用v-on="listeners" 绑定父组件传过来的所有函数 -->
<el-button
:loading="loading"
v-bind="$attrs"
v-on="listeners"
@click="handleClick"
>
<slot></slot>
</el-button>
</template>
<script>
export default {
name: "MyLoadingBtn",
data() {
return {
loading: false,
};
},
computed: {
// 需要单独对click事件进行处理
listeners() {
const copy = { ...this.$listeners };
delete copy.click;
return copy;
},
},
methods: {
async handleClick() {
console.log("click");
const fun = this.$listeners;
this.loading = true;
try {
// 同样,绑定的click函数也必须返回Promise或者async函数
await fun.click?.();
} finally {
this.loading = false;
}
},
},
};
</script>
2.2、使用组件
<template>
<div class="test1">
<MyLoadingBtn type="primary" @click="handleClick"> 测试 </MyLoadingBtn>
</div>
</template>
<script>
import MyLoadingBtn from "@/components/MyLoadingBtn.vue";
export default {
components: {
MyLoadingBtn,
},
methods: {
async handleClick() {
await fetch("http://localhost:8888/getUser?userName=")
.then((res) => {
return res.json();
})
.then((res) => {
console.log(res);
});
},
},
};
</script>
2.3、效果
原文地址:https://blog.csdn.net/qq_57404736/article/details/142528504
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!