add:添加新的地步按钮组件和说明,替代并简化原有按钮组件,降低页面状态管理的复杂度;
parent
f0c151ec9e
commit
0379cef6b4
67
README.md
67
README.md
|
|
@ -55,4 +55,71 @@ config.header['platform'] = 'APP'
|
|||
</has-authority>
|
||||
</view>
|
||||
</uni-td>
|
||||
```
|
||||
|
||||
# 以下为复杂页面的完整配置参数
|
||||
|
||||
```json
|
||||
{
|
||||
"path": "pages/index/index", // 首页
|
||||
"style": {
|
||||
"navigationBarTitleText": "首页", // 页面标题
|
||||
"enablePullDownRefresh": true, // 开启下拉刷新
|
||||
"backgroundColor": "#F8F8F8", // 导航栏背景颜色
|
||||
"onReachBottomDistance": 100, // 设置页面上拉触底事件触发时距离页面底部的距离,默认是50px
|
||||
"app-plus": { // 以下是App平台特有配置
|
||||
"titleNView": {
|
||||
"titleSize": "16px" // App端原生导航栏标题字体大小
|
||||
"titleColor": "#fff",
|
||||
"buttons": [{ // 导航栏右侧按钮,下面是使用icon展示的示例
|
||||
"text": "\ue60f",
|
||||
"fontSize": "30px",
|
||||
"fontSrc": "/static/iconfont.ttf"
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 以下为底部按钮列表的使用方式
|
||||
```js
|
||||
//按钮列表的引入
|
||||
import bottomBtnGroup from '@/components/bottomBtn/bottomBtnGroup.vue'
|
||||
//注册组件
|
||||
components: {
|
||||
bottomBtnGroup
|
||||
},
|
||||
//UI 引用
|
||||
<bottomBtnGroup :toolbar="bottomBtnList"></bottomBtnGroup>
|
||||
// vue Data定义
|
||||
data() {
|
||||
return {
|
||||
//form 底部按钮栏配置
|
||||
bottomBtnList: [{
|
||||
label: "新增",
|
||||
type: "primary",
|
||||
event: (done) => { // 接收 done 回调 // ✅ 箭头函数,this 指向组件
|
||||
setTimeout(() => {
|
||||
// // 在这里执行你想要延迟执行的函数或代码
|
||||
console.log("延时5秒") // 调用你的函数
|
||||
this.containCallMethods(done);//你需要执行的方法
|
||||
}, 5000);
|
||||
//this.containCallMethods(done);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: "取消",
|
||||
type: "primary",
|
||||
event: function() {
|
||||
//方式2:
|
||||
return new Promise(resolve => {
|
||||
console.log("取消方法完成")
|
||||
setTimeout(resolve, 5000);
|
||||
});
|
||||
}
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,299 @@
|
|||
<!-- PageBottom.vue -->
|
||||
<template>
|
||||
<view class="pageBottom" :style="{ position: position, bottom: isSubmit ? '60rpx' : '0' }">
|
||||
<view class="uni-flex uni-row buttons">
|
||||
<view class="flex-item " v-for="(item, index) in toolbar" :key="index" style="padding: 1ch;width: 100%;">
|
||||
<!-- 更多按钮:todo 1.按钮权限控制;2.动态宽度; -->
|
||||
<!-- type: 'primary' 蓝色(不同终端默认颜色不同),'default' 白色,'warn'红色 如想在多端统一颜色,请改用default,然后自行写样式 -->
|
||||
<!-- style: 支持自定义样式 -->
|
||||
<button :type="item.type && ['primary','default','warn'].includes(item.type) ? item.type : 'default'"
|
||||
@click="handleClick(item,index)" :style="item.style || ''" :loading="buttonStates[index]"
|
||||
:disabled="buttonStates[index]">
|
||||
{{ item.label }}{{ item.disable }}
|
||||
</button>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
propsToAttrMap
|
||||
} from '@vue/shared';
|
||||
|
||||
export default {
|
||||
name: 'bottomBtnGroup',
|
||||
// 接收的 props
|
||||
props: {
|
||||
/// 头工具栏
|
||||
toolbar: {
|
||||
type: Array,
|
||||
default () {
|
||||
return [{
|
||||
label: "新增",
|
||||
type: "primary",
|
||||
event: function(done) {
|
||||
//方式1: 接收 done 回调 在业务结束时手动触发回调
|
||||
setTimeout(() => {
|
||||
console.log("延时5秒 新增方法完成")
|
||||
done(); //
|
||||
}, 5000);
|
||||
}
|
||||
},
|
||||
{
|
||||
label: "删除",
|
||||
type: "default",
|
||||
event: function(done) {
|
||||
setTimeout(() => {
|
||||
console.log("延时5秒 删除方法完成")
|
||||
done();
|
||||
}, 5000);
|
||||
}
|
||||
},
|
||||
{
|
||||
label: "取消",
|
||||
type: "primary",
|
||||
event: function() {
|
||||
//方式2:
|
||||
return new Promise(resolve => {
|
||||
console.log("取消方法完成")
|
||||
setTimeout(resolve, 5000);
|
||||
});
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
//背景是否是白色
|
||||
backgroundWhite: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
//是否是提交表单的样式
|
||||
isSubmit: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
//按钮是否可点击的状态
|
||||
disable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
position: {
|
||||
type: String,
|
||||
default: 'fixed'
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// 初始化每个按钮的loading状态
|
||||
this.initButtonStates();
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
// 存储按钮的loading状态(与toolbar对应)
|
||||
buttonStates: []
|
||||
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
// 监听toolbar变化,重新初始化状态(适用于动态更新按钮列表的场景)
|
||||
toolbar: {
|
||||
handler() {
|
||||
this.initButtonStates();
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
|
||||
// 方法
|
||||
methods: {
|
||||
// 初始化按钮状态(为每个按钮添加loading属性)
|
||||
initButtonStates() {
|
||||
this.toolbar.map((item, index) => {
|
||||
//this.buttonStates.push(false)//vue3生效
|
||||
// 响应式更新
|
||||
this.$set(this.buttonStates, index, false); //vue2生效
|
||||
});
|
||||
},
|
||||
async handleClick(item, index) {
|
||||
try {
|
||||
this.$set(this.buttonStates, index, true);
|
||||
this.$modal.loading("请等待...")
|
||||
//方式1:注意:此处约定 item.event() 返回一个Promise 否则loding状态不生效
|
||||
//return new Promise(resolve => setTimeout(resolve, 5000));
|
||||
//方式2:把 resolve/reject 作为“完成信号”传给业务函数,像调用方法传递done 方法,在业务处理结后调用
|
||||
await new Promise((resolve, reject) => {
|
||||
// 把 resolve/reject 作为“完成信号”传给业务函数
|
||||
item.event(resolve, reject);
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('catch 按钮事件执行出错:', error);
|
||||
} finally {
|
||||
// 响应式更新
|
||||
console.info('finally 按钮事件执行');
|
||||
this.$set(this.buttonStates, index, false);
|
||||
this.$modal.closeLoading()
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.pageBottom {
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
z-index: 30;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
padding: 20rpx 0 20rpx;
|
||||
|
||||
.button {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 686rpx;
|
||||
height: 72rpx;
|
||||
font-weight: 400;
|
||||
font-size: 32rpx;
|
||||
color: #ffffff;
|
||||
border-radius: 16rpx;
|
||||
//background: rgb(22, 93, 255);
|
||||
}
|
||||
|
||||
.backgroundWhite {
|
||||
background: #fff;
|
||||
color: #165dff;
|
||||
border: 2rpx solid rgb(22, 93, 255);
|
||||
}
|
||||
|
||||
.buttons {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
padding: 24rpx 0 60rpx;
|
||||
background-color: #fff;
|
||||
//background-color: #165DFF;
|
||||
|
||||
.buttonOne {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 90rpx;
|
||||
width: 664rpx;
|
||||
box-sizing: border-box;
|
||||
//background: rgb(22, 93, 255);
|
||||
border-radius: 16rpx;
|
||||
color: #FFFFFF;
|
||||
font-weight: 400;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.buttonLeft {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 90rpx;
|
||||
width: 332rpx;
|
||||
box-sizing: border-box;
|
||||
background: rgb(22, 93, 255);
|
||||
border-radius: 16rpx;
|
||||
color: #FFFFFF;
|
||||
font-weight: 400;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.buttonRight {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 90rpx;
|
||||
width: 332rpx;
|
||||
border-radius: 16rpx;
|
||||
background: rgb(22, 93, 255);
|
||||
font-weight: 400;
|
||||
font-size: 32rpx;
|
||||
color: #FFFFFF;
|
||||
margin-left: 22rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.thirdbuttons {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
padding: 10rpx 0 60rpx;
|
||||
background-color: #fff;
|
||||
|
||||
.buttonLeft {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 72rpx;
|
||||
width: 232rpx;
|
||||
box-sizing: border-box;
|
||||
border: 2rpx solid rgb(22, 93, 255);
|
||||
border-radius: 16rpx;
|
||||
background: rgb(255, 255, 255);
|
||||
color: #165DFF;
|
||||
font-weight: 400;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.buttonMid {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 72rpx;
|
||||
width: 232rpx;
|
||||
box-sizing: border-box;
|
||||
border: 2rpx solid rgb(22, 93, 255);
|
||||
border-radius: 16rpx;
|
||||
background: rgb(255, 255, 255);
|
||||
color: #165DFF;
|
||||
font-weight: 400;
|
||||
font-size: 32rpx;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
|
||||
.buttonRight {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 72rpx;
|
||||
width: 232rpx;
|
||||
border-radius: 16rpx;
|
||||
background: rgb(22, 93, 255);
|
||||
font-weight: 400;
|
||||
font-size: 32rpx;
|
||||
color: #FFFFFF;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.contentWhite {
|
||||
content: '';
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 240rpx;
|
||||
background: linear-gradient(to bottom,
|
||||
#f3ece400 0%,
|
||||
#F2F3F5 100%);
|
||||
pointer-events: none;
|
||||
}
|
||||
</style>
|
||||
Loading…
Reference in New Issue