feat(Tabbar): add before-change prop (#7081)

This commit is contained in:
neverland 2020-09-02 11:45:11 +08:00 committed by GitHub
parent b276fb5a78
commit d55585314f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 90 additions and 3 deletions

View File

@ -160,6 +160,7 @@ export default {
| route | Whether to enable route mode | _boolean_ | `false` |
| placeholder `v2.6.0` | Whether to generage a placeholder element when fixed | _boolean_ | `false` |
| safe-area-inset-bottom | Whether to enable bottom safe area adaptation | _boolean_ | `false` |
| before-change `v2.10.4` | Callback function before changing tabsreturn `false` to prevent changesupport return Promise | _(name) => boolean \| Promise_ | - |
### Tabbar Events

View File

@ -168,6 +168,7 @@ export default {
| route | 是否开启路由模式 | _boolean_ | `false` |
| placeholder `v2.6.0` | 固定在底部时,是否在标签位置生成一个等高的占位元素 | _boolean_ | `false` |
| safe-area-inset-bottom | 是否开启[底部安全区适配](#/zh-CN/quickstart#di-bu-an-quan-qu-gua-pei),设置 fixed 时默认开启 | _boolean_ | `false` |
| before-change `v2.10.4` | 切换标签前的回调函数,返回 `false` 可阻止切换,支持返回 Promise | _(name) => boolean \| Promise_ | - |
### Tabbar Events

View File

@ -1,6 +1,7 @@
import { createNamespace } from '../utils';
import { ParentMixin } from '../mixins/relation';
import { BORDER_TOP_BOTTOM } from '../utils/constant';
import { callInterceptor } from '../utils/interceptor';
import { ParentMixin } from '../mixins/relation';
const [createComponent, bem] = createNamespace('tabbar');
@ -12,6 +13,7 @@ export default createComponent({
zIndex: [Number, String],
placeholder: Boolean,
activeColor: String,
beforeChange: Function,
inactiveColor: String,
value: {
type: [Number, String],
@ -67,8 +69,14 @@ export default createComponent({
onChange(active) {
if (active !== this.value) {
this.$emit('input', active);
this.$emit('change', active);
callInterceptor({
interceptor: this.beforeChange,
args: [active],
done: () => {
this.$emit('input', active);
this.$emit('change', active);
},
});
}
},

27
src/utils/interceptor.ts Normal file
View File

@ -0,0 +1,27 @@
import { isPromise, noop } from '.';
export function callInterceptor(options: {
interceptor?: (...args: any[]) => Promise<boolean> | boolean;
done: () => void;
args: any[];
}) {
const { interceptor, args, done } = options;
if (interceptor) {
const returnVal = interceptor(...args);
if (isPromise(returnVal)) {
returnVal
.then((value) => {
if (value) {
done();
}
})
.catch(noop);
} else if (returnVal) {
done();
}
} else {
done();
}
}

View File

@ -0,0 +1,50 @@
import { later } from '../../../test';
import { callInterceptor } from '../interceptor';
test('#callInterceptor', async () => {
const done = jest.fn();
callInterceptor({ done });
expect(done).toHaveBeenCalledTimes(1);
callInterceptor({
interceptor: () => false,
done,
});
expect(done).toHaveBeenCalledTimes(1);
callInterceptor({
interceptor: () => true,
done,
});
expect(done).toHaveBeenCalledTimes(2);
callInterceptor({
interceptor: () => Promise.resolve(false),
done,
});
await later();
expect(done).toHaveBeenCalledTimes(2);
callInterceptor({
interceptor: () => Promise.resolve(true),
done,
});
await later();
expect(done).toHaveBeenCalledTimes(3);
callInterceptor({
interceptor: () => Promise.reject(),
done,
});
await later();
expect(done).toHaveBeenCalledTimes(3);
callInterceptor({
interceptor: (...args) => {
expect(args).toEqual(['foo']);
},
args: ['foo'],
done,
});
expect(done).toHaveBeenCalledTimes(3);
});