feat(Tab): improve scrollLeftTo performance

This commit is contained in:
陈嘉涵 2019-12-16 20:57:13 +08:00
parent e9369acf26
commit f8a3669f2d
5 changed files with 35 additions and 28 deletions

View File

@ -205,7 +205,7 @@ In scrollspy mode, the list of content will be tiled
| sticky | Whether to use sticky mode | *boolean* | `false` | - |
| swipeable | Whether to switch tabs with swipe gestrue in the content | *boolean* | `false` | - |
| lazy-render | Whether to enable tab content lazy render | *boolean* | `true` | - |
| scrollspy | Whether to use scrollspy mode | *boolean* | `false` | - |
| scrollspy | Whether to use scrollspy mode | *boolean* | `false` | 2.3.0 |
### Tab Props

View File

@ -209,7 +209,7 @@ export default {
| sticky | 是否使用粘性定位布局 | *boolean* | `false` | - |
| swipeable | 是否开启手势滑动切换 | *boolean* | `false` | - |
| lazy-render | 是否开启标签页内容延迟渲染 | *boolean* | `true` | - |
| scrollspy | 是否开启滚动导航 | *boolean* | `false` | - |
| scrollspy | 是否开启滚动导航 | *boolean* | `false` | 2.3.0 |
### Tab Props

View File

@ -45,12 +45,12 @@ export default createComponent({
},
render(h) {
const { slots, isActive } = this;
const shouldRender = this.inited || this.parent.scrollspy || !this.parent.lazyRender;
const show = this.parent.scrollspy || isActive;
const { slots, parent, isActive } = this;
const shouldRender = this.inited || parent.scrollspy || !parent.lazyRender;
const show = parent.scrollspy || isActive;
const Content = shouldRender ? slots() : h();
if (this.parent.animated) {
if (parent.animated) {
return (
<div
role="tabpanel"

View File

@ -6,7 +6,13 @@ import { on, off } from '../utils/dom/event';
import { ParentMixin } from '../mixins/relation';
import { BindEventMixin } from '../mixins/bind-event';
import { BORDER_TOP_BOTTOM } from '../utils/constant';
import { setRootScrollTop, getElementTop, getVisibleHeight, getVisibleTop } from '../utils/dom/scroll';
import {
setRootScrollTop,
getElementTop,
getVisibleHeight,
getVisibleTop
} from '../utils/dom/scroll';
import Title from './Title';
import Content from './Content';
import Sticky from '../sticky';
@ -19,7 +25,7 @@ export default createComponent({
BindEventMixin(function(bind) {
bind(window, 'resize', this.resize, true);
if (this.scrollspy) {
bind(window, 'scroll', this.onScrollspyScroll, true);
bind(window, 'scroll', this.onScroll, true);
}
})
],
@ -142,9 +148,9 @@ export default createComponent({
scrollspy(val) {
if (val) {
on(window, 'scroll', this.onScrollspyScroll, true);
on(window, 'scroll', this.onScroll, true);
} else {
off(window, 'scroll', this.onScrollspyScroll);
off(window, 'scroll', this.onScroll);
}
}
},
@ -277,7 +283,7 @@ export default createComponent({
scrollLeftTo(nav, to, immediate ? 0 : this.duration);
},
onScroll(params) {
onSticktScroll(params) {
this.stickyFixed = params.isFixed;
this.$emit('scroll', params);
},
@ -296,7 +302,7 @@ export default createComponent({
}
},
onScrollspyScroll() {
onScroll() {
if (this.scrollspy && !this.clickedScroll) {
const index = this.getCurrentIndexOnScroll();
this.setCurrentIndex(index);
@ -304,20 +310,17 @@ export default createComponent({
},
getCurrentIndexOnScroll() {
let i;
const { children } = this;
for (i = 0; i < this.children.length; i++) {
const top = getVisibleTop(this.children[i].$el);
for (let index = 0; index < children.length; index++) {
const top = getVisibleTop(children[index].$el);
if (top > this.scrollOffset) {
if (i === 0) {
return 0;
}
return i - 1;
return index === 0 ? 0 : index - 1;
}
}
return i - 1;
return children.length - 1;
}
},
@ -381,7 +384,7 @@ export default createComponent({
<Sticky
container={this.$el}
offsetTop={this.offsetTop}
onScroll={this.onScroll}
onScroll={this.onSticktScroll}
>
{Wrap}
</Sticky>

View File

@ -1,7 +1,11 @@
import { raf } from '../utils/dom/raf';
import { raf, cancelRaf } from '../utils/dom/raf';
import { getRootScrollTop, setRootScrollTop } from '../utils/dom/scroll';
let scrollLeftRafId: number;
export function scrollLeftTo(el: HTMLElement, to: number, duration: number) {
cancelRaf(scrollLeftRafId);
let count = 0;
const from = el.scrollLeft;
const frames = duration === 0 ? 1 : Math.round((duration * 1000) / 16);
@ -10,7 +14,7 @@ export function scrollLeftTo(el: HTMLElement, to: number, duration: number) {
el.scrollLeft += (to - from) / frames;
if (++count < frames) {
raf(animate);
scrollLeftRafId = raf(animate);
}
}
@ -19,20 +23,20 @@ export function scrollLeftTo(el: HTMLElement, to: number, duration: number) {
export function scrollTopTo(to: number, duration: number, cb: Function) {
let current = getRootScrollTop();
const toDown = current < to;
const isDown = current < to;
const frames = duration === 0 ? 1 : Math.round((duration * 1000) / 16);
const pxPerFrames = (to - current) / frames;
const step = (to - current) / frames;
function animate() {
current += pxPerFrames;
current += step;
if ((toDown && current > to) || (!toDown && current < to)) {
if ((isDown && current > to) || (!isDown && current < to)) {
current = to;
}
setRootScrollTop(current);
if ((toDown && current < to) || (!toDown && current > to)) {
if ((isDown && current < to) || (!isDown && current > to)) {
raf(animate);
} else {
cb && cb();