UNPKG

weex-nuke

Version:

基于 Rax 、Weex 的高性能组件体系 ~~

178 lines (165 loc) 4.86 kB
/** @jsx createElement */ 'use strict'; import { createElement, Component, findDOMNode } from 'rax'; import View from 'nuke-view'; import Touchable from 'nuke-touchable'; import ScrollView from 'nuke-scroll-view'; import { Detection } from 'nuke-ep-utils'; import { connectStyle } from 'nuke-theme-provider'; import stylesProvider from '../styles/index'; // const ratio = window.devicePixelRatio; class Nav extends Component { constructor(props) { super(props); // 每个item的宽度 itemWidthList 可以是定值也可以是数组,如果不存在则使用flex均分渲染 if (props.dataSource instanceof Array) { this.itemWidthList = props.dataSource.map( item => (item.style && item.style.width) || 750 / props.dataSource.length ); } // @todo what's maxWidth for // this.maxWidth = 750; if (this.itemWidthList.length) { this.maxWidth = this.itemWidthList.reduce((pre, cur) => pre + cur); } this.state = { transform: 0, curIndex: props.curIndex ? props.curIndex : 0, }; } shouldComponentUpdate(nextProps, nextState) { if (nextState.curIndex !== this.state.curIndex || nextProps.forceRender) { return true; } if (nextState.transform !== this.state.transform) { return true; } return false; } onTabItemClick = (itemData, index) => { const { curIndex } = this.state; if (curIndex !== index) { const { slideTo } = this.props; slideTo(index, 'clk', this); } }; /** * @description scroll to witch element base on index */ scrollTo = (index) => { const { navStyle } = this.props; const tabElement = this.refs.nav; const itemWidthList = this.itemWidthList; const selectedItemWidth = itemWidthList[index]; let screenWidth = 750; let selectedItemOffset = 0; let dist; if (navStyle && navStyle.width) { screenWidth = parseInt(navStyle.width, 10); } itemWidthList.forEach((itemData, i) => { if (i < index) { selectedItemOffset += itemData; } }); dist = selectedItemOffset - screenWidth / 2 + selectedItemWidth / 2; // @note: weex android下计算误差 // if (Detection.isWeex && Detection.Android && !isNew) { // dist /= ratio; // } if (this.maxWidth < screenWidth) { return; } if (dist < 0) { dist = 0; } else if (dist > this.maxWidth) { dist = this.maxWidth; } tabElement.scrollTo({ x: dist, }); }; /** * @description 选中态动效滚动样式 */ focusMove = (index) => { if (this.props.navFocusStyle) { let left = 0; const itemWidthList = this.itemWidthList; if (index === 1) { left = itemWidthList[0]; } else if (index > 1) { itemWidthList.map((item, i) => { if (i < index) { left += itemWidthList[i]; } else { return; } }); } if (Detection.epEnable) { const animation = require('@weex-module/animation'); // 高版本系统的手机才使用transform动画 const tabElement = findDOMNode(this.refs.tabFocus); // const dist = 750 * index; animation.transition( tabElement, { styles: { transform: `translateX(${left})`, }, delay: 0, duration: Detection.iOS ? 300 : 250, // ms timingFunction: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)', // ['cubic-bezier(0.25, 0.46, 0.45, 0.94)', 'cubic-bezier(0,0,0.25,1)'] }, () => { } ); } else { this.setState({ transform: left, }); } } }; render() { const { dataSource, style, navFocusStyle, renderNavItem, themeStyle, navContentStyle, } = this.props; const { curIndex, transform } = this.state; const tabFocusLeft = navFocusStyle && navFocusStyle.left ? parseInt(navFocusStyle.left) : 0; return ( <ScrollView ref={'nav'} style={[themeStyle.nav, style]} contentContainerStyle={[themeStyle.navContent, navContentStyle]} horizontal showsHorizontalScrollIndicator={false} > {navFocusStyle ? ( <View ref="tabFocus" style={[navFocusStyle, { left: tabFocusLeft + transform }]} /> ) : null} {dataSource.map((itemData, index) => ( <Touchable key={index} ref={`TabItem${index}`} onPress={() => this.onTabItemClick(itemData, index)} > {renderNavItem(itemData, index, curIndex)} </Touchable> ))} </ScrollView> ); } } Nav.displayName = 'Ep-Tabbar'; export default connectStyle(stylesProvider)(Nav);