UNPKG

taro-material

Version:

Mini Program components that implement Google's Material Design.

239 lines (213 loc) 5.83 kB
import Taro from '@tarojs/taro' import PropTypes from 'prop-types' import { View, ScrollView } from '@tarojs/components' import classNames from 'classnames' import AtComponent from '../../common/component' import AtList from '../../components/list/index' import AtListItem from '../../components/list/item/index' import AtToast from '../../components/toast/index' import { delayQuerySelector, uuid, initTestEnv, isTest } from '../../common/utils' initTestEnv() const ENV = Taro.getEnv() class AtIndexes extends AtComponent { constructor () { super(...arguments) this.state = { _scrollIntoView: '', _scrollTop: 0, _tipText: '', _isShowToast: false } // 右侧导航高度 this.menuHeight = 0 // 右侧导航距离顶部高度 this.startTop = 0 // 右侧导航元素高度 this.itemHeight = 0 // 当前索引 this.currentIndex = -1 this.listId = isTest() ? 'indexes-list-AOTU2018' : `list-${uuid()}` } handleClick = (...arg) => this.props.onClick(...arg) handleTouchMove = event => { event.stopPropagation() event.preventDefault() const { list } = this.props const pageY = event.touches[0].pageY const index = Math.floor((pageY - this.startTop) / this.itemHeight) if (index >= 0 && index <= list.length && this.currentIndex !== index ) { this.currentIndex = index const key = index > 0 ? list[index - 1].key : 'top' const touchView = `at-indexes__list-${key}` this.jumpTarget(touchView, index) } } handleTouchEnd = () => { this.currentIndex = -1 } jumpTarget (_scrollIntoView, idx) { const { topKey, list } = this.props const _tipText = idx === 0 ? topKey : list[idx - 1].key if (ENV === Taro.ENV_TYPE.WEB) { delayQuerySelector(this, '.at-indexes', 0) .then(rect => { const targetOffsetTop = this.listRef.childNodes[idx].offsetTop const _scrollTop = targetOffsetTop - rect[0].top this.updateState({ _scrollTop, _scrollIntoView, _tipText, }) }) return } this.updateState({ _scrollIntoView, _tipText }) } updateState (state) { const { isShowToast, isVibrate } = this.props const { _scrollIntoView, _tipText, _scrollTop } = state this.setState({ _scrollIntoView, _tipText, _scrollTop, _isShowToast: isShowToast }) if (isVibrate) { Taro.vibrateShort() } } initData () { delayQuerySelector(this, '.at-indexes__menu') .then(rect => { const len = this.props.list.length this.menuHeight = rect[0].height this.startTop = rect[0].top this.itemHeight = Math.floor((this.menuHeight) / (len + 1)) }) } componentWillReceiveProps (nextProps) { if (nextProps.list.length !== this.props.list.length) { this.initData() } } componentDidMount () { if (ENV === Taro.ENV_TYPE.WEB) { this.listRef = document.getElementById(this.listId) } this.initData() } render () { const { className, customStyle, animation, topKey, list } = this.props const { _scrollTop, _scrollIntoView, _tipText, _isShowToast } = this.state const toastStyle = { minWidth: Taro.pxTransform(100) } const rootCls = classNames('at-indexes', className) const menuList = list.map((dataList, i) => { const { key } = dataList const targetView = `at-indexes__list-${key}` return <View className='at-indexes__menu-item' key={key} onClick={this.jumpTarget.bind(this, targetView, i + 1)} > {key} </View> }) const indexesList = list.map(dataList => ( <View id={`at-indexes__list-${dataList.key}`} className='at-indexes__list' key={dataList.key} > <View className='at-indexes__list-title'> {dataList.title} </View> <AtList> {dataList.items && dataList.items.map(item => ( <AtListItem key={item.name} title={item.name} onClick={this.handleClick.bind(this, item)} /> ))} </AtList> </View> )) return <View className={rootCls} style={customStyle}> <AtToast customStyle={toastStyle} isOpened={_isShowToast} text={_tipText} duration={2000} /> <View className='at-indexes__menu' onTouchMove={this.handleTouchMove} onTouchEnd={this.handleTouchEnd} > <View className='at-indexes__menu-item' onClick={this.jumpTarget.bind(this, 'at-indexes__top', 0)} > {topKey} </View> {menuList} </View> <ScrollView className='at-indexes__body' id={this.listId} scrollY scrollWithAnimation={animation} scrollTop={_scrollTop} scrollIntoView={_scrollIntoView} > <View className='at-indexes__content' id='at-indexes__top'> {this.props.children} </View> {indexesList} </ScrollView> </View> } } AtIndexes.propTypes = { customStyle: PropTypes.oneOfType([ PropTypes.object, PropTypes.string ]), className: PropTypes.oneOfType([ PropTypes.array, PropTypes.string ]), animation: PropTypes.bool, isVibrate: PropTypes.bool, isShowToast: PropTypes.bool, topKey: PropTypes.string, list: PropTypes.array, onClick: PropTypes.func } AtIndexes.defaultProps = { isTest: false, customStyle: '', className: '', animation: false, topKey: 'Top', isVibrate: true, isShowToast: true, list: [], onClick: () => { } } export default AtIndexes