[new feature] add sticky component (#3888)

This commit is contained in:
neverland
2019-07-18 17:48:18 +08:00
committed by GitHub
parent e1021e70ba
commit b273c89b3a
23 changed files with 651 additions and 124 deletions
+37 -82
View File
@@ -1,24 +1,18 @@
import { createNamespace, isDef, addUnit } from '../utils';
import { scrollLeftTo } from './utils';
import { on, off } from '../utils/dom/event';
import { ParentMixin } from '../mixins/relation';
import { BindEventMixin } from '../mixins/bind-event';
import {
setRootScrollTop,
getScrollTop,
getElementTop,
getScrollEventTarget
} from '../utils/dom/scroll';
import { setRootScrollTop, getElementTop } from '../utils/dom/scroll';
import Title from './Title';
import Content from './Content';
import Sticky from '../sticky';
const [createComponent, bem] = createNamespace('tabs');
export default createComponent({
mixins: [
ParentMixin('vanTabs'),
BindEventMixin(function (bind, isBind) {
this.bindScrollEvent(isBind);
BindEventMixin(function (bind) {
bind(window, 'resize', this.setLine, true);
})
],
@@ -72,8 +66,6 @@ export default createComponent({
},
data() {
this.scrollEvent = false;
return {
position: '',
currentIndex: null,
@@ -89,23 +81,6 @@ export default createComponent({
return this.children.length > this.swipeThreshold || !this.ellipsis;
},
wrapStyle() {
switch (this.position) {
case 'top':
return {
top: this.offsetTop + 'px',
position: 'fixed'
};
case 'bottom':
return {
top: 'auto',
bottom: 0
};
default:
return null;
}
},
navStyle() {
return {
borderColor: this.color,
@@ -144,13 +119,9 @@ export default createComponent({
this.setLine();
// scroll to correct position
if (this.position === 'top' || this.position === 'bottom') {
if (this.stickyFixed) {
setRootScrollTop(getElementTop(this.$el) - this.offsetTop);
}
},
sticky(val) {
this.bindScrollEvent(val);
}
},
@@ -171,40 +142,6 @@ export default createComponent({
});
},
bindScrollEvent(isBind) {
const sticky = this.sticky && isBind;
if (this.scrollEvent !== sticky) {
this.scrollEvent = sticky;
this.scrollEl = this.scrollEl || getScrollEventTarget(this.$el);
(sticky ? on : off)(this.scrollEl, 'scroll', this.onScroll, true);
this.onScroll();
}
},
// adjust tab position
onScroll() {
const scrollTop = getScrollTop(this.scrollEl) + this.offsetTop;
const elTopToPageTop = getElementTop(this.$el);
const elBottomToPageTop =
elTopToPageTop + this.$el.offsetHeight - this.$refs.wrap.offsetHeight;
if (scrollTop > elBottomToPageTop) {
this.position = 'bottom';
} else if (scrollTop > elTopToPageTop) {
this.position = 'top';
} else {
this.position = '';
}
const scrollParams = {
scrollTop,
isFixed: this.position === 'top'
};
this.$emit('scroll', scrollParams);
},
// update nav bar style
setLine() {
const shouldAnimate = this.inited;
@@ -305,6 +242,11 @@ export default createComponent({
this.$nextTick(() => {
this.$refs.titles[index].renderTitle(el);
});
},
onScroll(params) {
this.stickyFixed = params.isFixed;
this.$emit('scroll', params);
}
},
@@ -331,23 +273,36 @@ export default createComponent({
/>
));
const Wrap = (
<div
ref="wrap"
class={[
bem('wrap', { scrollable }),
{ 'van-hairline--top-bottom': type === 'line' && this.border }
]}
>
<div ref="nav" role="tablist" class={bem('nav', [type])} style={this.navStyle}>
{this.slots('nav-left')}
{Nav}
{type === 'line' && <div class={bem('line')} style={this.lineStyle} />}
{this.slots('nav-right')}
</div>
</div>
);
return (
<div class={bem([type])}>
<div
ref="wrap"
style={this.wrapStyle}
class={[
bem('wrap', { scrollable }),
{ 'van-hairline--top-bottom': type === 'line' && this.border }
]}
>
<div ref="nav" role="tablist" class={bem('nav', [type])} style={this.navStyle}>
{this.slots('nav-left')}
{Nav}
{type === 'line' && <div class={bem('line')} style={this.lineStyle} />}
{this.slots('nav-right')}
</div>
</div>
{this.sticky ? (
<Sticky
container={this.$el}
offsetTop={this.offsetTop}
onScroll={this.onScroll}
>
{Wrap}
</Sticky>
) : (
Wrap
)}
<Content
count={this.children.length}
animated={animated}
-7
View File
@@ -30,11 +30,6 @@
position: relative;
&__wrap {
position: absolute;
top: 0;
right: 0;
left: 0;
z-index: 99;
overflow: hidden;
&--page-top {
@@ -132,8 +127,6 @@
}
&--line {
padding-top: @tabs-line-height;
.van-tabs__wrap {
height: @tabs-line-height;
}