11import { use } from '../utils' ;
22import { TouchMixin } from '../mixins/touch' ;
33import { ParentMixin } from '../mixins/relation' ;
4+ import { on , off } from '../utils/event' ;
5+ import { getScrollTop , getElementTop , getScrollEventTarget } from '../utils/scroll' ;
46
57const [ sfc , bem ] = use ( 'index-bar' ) ;
68
79export default sfc ( {
810 mixins : [ TouchMixin , ParentMixin ( 'vanIndexBar' ) ] ,
911
1012 props : {
13+ sticky : {
14+ type : Boolean ,
15+ default : true
16+ } ,
1117 zIndex : {
1218 type : Number ,
1319 default : 1
@@ -27,13 +33,72 @@ export default sfc({
2733 }
2834 } ,
2935
36+ mounted ( ) {
37+ this . scroller = getScrollEventTarget ( this . $el ) ;
38+ this . handler ( true ) ;
39+ } ,
40+
41+ destroyed ( ) {
42+ this . handler ( false ) ;
43+ } ,
44+
45+ activated ( ) {
46+ this . handler ( true ) ;
47+ } ,
48+
49+ deactivated ( ) {
50+ this . handler ( false ) ;
51+ } ,
52+
3053 methods : {
31- onClick ( event ) {
32- this . scrollToElement ( event . target ) ;
54+ handler ( bind ) {
55+ /* istanbul ignore else */
56+ if ( this . binded !== bind ) {
57+ this . binded = bind ;
58+ ( bind ? on : off ) ( this . scroller , 'scroll' , this . onScroll ) ;
59+ }
3360 } ,
3461
35- onTouchStart ( event ) {
36- this . touchStart ( event ) ;
62+ onScroll ( ) {
63+ if ( ! this . sticky ) {
64+ return ;
65+ }
66+
67+ const scrollTop = getScrollTop ( this . scroller ) ;
68+ const rects = this . children . map ( item => ( {
69+ height : item . height ,
70+ top : getElementTop ( item . $el )
71+ } ) ) ;
72+
73+ const active = this . getActiveAnchorIndex ( scrollTop , rects ) ;
74+
75+ this . children . forEach ( ( item , index ) => {
76+ if ( index === active ) {
77+ item . active = true ;
78+ item . top = Math . max ( 0 , rects [ index ] . top - scrollTop ) ;
79+ } else if ( index === active - 1 ) {
80+ const activeItemTop = rects [ active ] . top - scrollTop ;
81+ item . active = activeItemTop > 0 ;
82+ item . top = activeItemTop - rects [ active ] . height ;
83+ } else {
84+ item . active = false ;
85+ }
86+ } ) ;
87+ } ,
88+
89+ getActiveAnchorIndex ( scrollTop , rects ) {
90+ for ( let i = this . children . length - 1 ; i >= 0 ; i -- ) {
91+ const prevHeight = i > 0 ? rects [ i - 1 ] . height : 0 ;
92+
93+ if ( scrollTop + prevHeight >= rects [ i ] . top ) {
94+ return i ;
95+ }
96+ }
97+ return - 1 ;
98+ } ,
99+
100+ onClick ( event ) {
101+ this . scrollToElement ( event . target ) ;
37102 } ,
38103
39104 onTouchMove ( event ) {
@@ -80,7 +145,7 @@ export default sfc({
80145 class = { bem ( 'sidebar' ) }
81146 style = { { zIndex : this . zIndex } }
82147 onClick = { this . onClick }
83- onTouchstart = { this . onTouchStart }
148+ onTouchstart = { this . touchStart }
84149 onTouchmove = { this . onTouchMove }
85150 onTouchend = { this . onTouchEnd }
86151 onTouchcancel = { this . onTouchEnd }
0 commit comments