perf(collapse): use animate to improve performance (#3826)

fix #3820
This commit is contained in:
rex 2020-12-09 11:14:58 +08:00 committed by GitHub
parent bbbbbe3961
commit 1104e07fd7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 117 additions and 64 deletions

View File

@ -0,0 +1,94 @@
import { canIUseAnimate } from '../common/version';
import { getRect } from '../common/utils';
function useAnimate(
context: WechatMiniprogram.Component.TrivialInstance,
expanded: boolean,
mounted: boolean,
height: number
) {
const selector = '.van-collapse-item__wrapper';
if (expanded) {
context.animate(
selector,
[
{ height: 0, ease: 'ease-in-out', offset: 0 },
{ height: `${height}px`, ease: 'ease-in-out', offset: 1 },
{ height: `auto`, ease: 'ease-in-out', offset: 1 },
],
mounted ? 300 : 0,
() => {
context.clearAnimation(selector);
}
);
return;
}
context.animate(
selector,
[
{ height: `${height}px`, ease: 'ease-in-out', offset: 0 },
{ height: 0, ease: 'ease-in-out', offset: 1 },
],
300,
() => {
context.clearAnimation(selector);
}
);
}
function useAnimation(
context: WechatMiniprogram.Component.TrivialInstance,
expanded: boolean,
mounted: boolean,
height: number
) {
const animation = wx.createAnimation({
duration: 0,
timingFunction: 'ease-in-out',
});
if (expanded) {
if (height === 0) {
animation.height('auto').top(1).step();
} else {
animation
.height(height)
.top(1)
.step({
duration: mounted ? 300 : 1,
})
.height('auto')
.step();
}
context.setData({
animation: animation.export(),
});
return;
}
animation.height(height).top(0).step({ duration: 1 }).height(0).step({
duration: 300,
});
context.setData({
animation: animation.export(),
});
}
export function setContentAnimate(
context: WechatMiniprogram.Component.TrivialInstance,
expanded: boolean,
mounted: boolean
) {
getRect
.call(context, '.van-collapse-item__content')
.then((rect) => rect.height)
.then((height: number) => {
canIUseAnimate()
? useAnimate(context, expanded, mounted, height)
: useAnimation(context, expanded, mounted, height);
});
}

View File

@ -1,5 +1,5 @@
import { getRect } from '../common/utils';
import { VantComponent } from '../common/component'; import { VantComponent } from '../common/component';
import { setContentAnimate } from './animate';
VantComponent({ VantComponent({
classes: ['title-class', 'content-class'], classes: ['title-class', 'content-class'],
@ -32,23 +32,15 @@ VantComponent({
expanded: false, expanded: false,
}, },
created() {
this.animation = wx.createAnimation({
duration: 0,
timingFunction: 'ease-in-out',
});
},
mounted() { mounted() {
this.updateExpanded(); this.updateExpanded();
this.mounted = true;
this.inited = true;
}, },
methods: { methods: {
updateExpanded() { updateExpanded() {
if (!this.parent) { if (!this.parent) {
return Promise.resolve(); return;
} }
const { value, accordion } = this.parent.data; const { value, accordion } = this.parent.data;
@ -63,50 +55,12 @@ VantComponent({
: (value || []).some((name: string | number) => name === currentName); : (value || []).some((name: string | number) => name === currentName);
if (expanded !== this.data.expanded) { if (expanded !== this.data.expanded) {
this.updateStyle(expanded); setContentAnimate(this, expanded, this.mounted);
} }
this.setData({ index, expanded }); this.setData({ index, expanded });
}, },
updateStyle(expanded: boolean) {
const { inited } = this;
getRect
.call(this, '.van-collapse-item__content')
.then((rect) => rect.height)
.then((height: number) => {
const { animation } = this;
if (expanded) {
if (height === 0) {
animation.height('auto').top(1).step();
} else {
animation
.height(height)
.top(1)
.step({
duration: inited ? 300 : 1,
})
.height('auto')
.step();
}
this.setData({
animation: animation.export(),
});
return;
}
animation.height(height).top(0).step({ duration: 1 }).height(0).step({
duration: 300,
});
this.setData({
animation: animation.export(),
});
});
},
onClick() { onClick() {
if (this.data.disabled) { if (this.data.disabled) {
return; return;

View File

@ -1,34 +1,34 @@
import { VantComponent } from '../common/component'; import { VantComponent } from '../common/component';
type TrivialInstance = WechatMiniprogram.Component.TrivialInstance;
VantComponent({ VantComponent({
relation: { relation: {
name: 'collapse-item', name: 'collapse-item',
type: 'descendant', type: 'descendant',
current: 'collapse' current: 'collapse',
}, },
props: { props: {
value: { value: {
type: null, type: null,
observer: 'updateExpanded' observer: 'updateExpanded',
}, },
accordion: { accordion: {
type: Boolean, type: Boolean,
observer: 'updateExpanded' observer: 'updateExpanded',
}, },
border: { border: {
type: Boolean, type: Boolean,
value: true value: true,
} },
}, },
methods: { methods: {
updateExpanded() { updateExpanded() {
this.children.forEach((child: TrivialInstance) => { this.children.forEach(
(child: WechatMiniprogram.Component.TrivialInstance) => {
child.updateExpanded(); child.updateExpanded();
}); }
);
}, },
switch(name: string | number, expanded: boolean) { switch(name: string | number, expanded: boolean) {
@ -52,6 +52,6 @@ VantComponent({
this.$emit('change', name); this.$emit('change', name);
this.$emit('input', name); this.$emit('input', name);
} },
} },
}); });

View File

@ -36,3 +36,8 @@ export function canIUseFormFieldButton() {
const system = getSystemInfoSync(); const system = getSystemInfoSync();
return compareVersion(system.SDKVersion, '2.10.3') >= 0; return compareVersion(system.SDKVersion, '2.10.3') >= 0;
} }
export function canIUseAnimate() {
const system = getSystemInfoSync();
return compareVersion(system.SDKVersion, '2.9.0') >= 0;
}