weex-nuke
Version:
基于 Rax 、Weex 的高性能组件体系 ~~
178 lines (165 loc) • 4.86 kB
JSX
/** @jsx createElement */
;
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);