mp-colorui
Version:
MP ColorUI 是一款基于 Taro 框架并且联合 Color-UI CSS 库开发的多端 UI 组件库(支持小程序端和H5端)
137 lines (135 loc) • 5.11 kB
JavaScript
import Nerv from "nervjs";
import Taro, { createSelectorQuery as _createSelectorQuery } from "@tarojs/taro-h5";
import { ScrollView, View } from "@tarojs/components";
import { screenPercent, generateId, getRectNumber, isAliPay, classNames } from "../../lib/index";
import "./index.scss";
let scrollTimer = undefined;
export default class ClVerticalTab extends Taro.Component {
render() {
const props = this.props;
let scrollTab = false;
let id = "";
const [tabsState, setTabsState] = Taro.useState(props.tabs || []);
const currentId = props.current ? props.current : props.tabs[0].id;
const [current, setCurrent] = Taro.useState(currentId);
const [verticalNavTop, setVerticalNavTop] = Taro.useState(tabsState.findIndex(item => item.name === props.tabs[0].name));
const [scrollId, setScrollId] = Taro.useState(currentId);
const [scrollContent, setScrollContent] = Taro.useState(0);
const [clickTab, setClickTab] = Taro.useState(false);
Taro.useEffect(() => {
const list = props.tabs || [];
setTabsState(list.map(item => {
item.cu_vertical_tab_id = generateId();
return item;
}));
}, [props.tabs]);
const tabs = tabsState || [];
// const [scrollTimer, setScrollTimer] = useState(0);
const isH5 = Taro.getEnv() === Taro.ENV_TYPE.WEB;
const onScroll = e => {
if (clickTab) return;
let tabHeight = 0;
for (let i = 0; i < tabs.length; i++) {
const query = _createSelectorQuery();
const view = query.select("#" + tabs[i].id);
view.boundingClientRect().exec(res => {
const data = res[0];
tabs[i].top = tabHeight;
tabHeight = tabHeight + data.height;
tabs[i].bottom = tabHeight;
});
}
let scrollTop = e.detail.scrollTop + 20;
isH5 && setScrollContent(e.detail.scrollTop);
if (!scrollTab) {
for (let i = 0; i < tabs.length; i++) {
if (scrollTop > (tabs[i].top || 0) && scrollTop < (tabs[i].bottom || 0)) {
// console.log(i)
setVerticalNavTop(i);
setCurrent(tabs[i].id);
return false;
}
}
}
};
const onH5Scroll = e => {
if (clickTab) return;
if (scrollTimer) clearTimeout(scrollTimer);
scrollTimer = setTimeout(() => {
onScroll(e);
clearTimeout(scrollTimer);
}, 300);
};
const tabsComponent = tabs.map(item => <View key={item.cu_vertical_tab_id} className={`cu-item ${current === item.id ? "cur" : ""}`} onClick={() => {
id = item.id;
scrollTab = true;
changeTop(id);
setCurrent(item.id);
setVerticalNavTop(tabs.findIndex(tab => tab.name === item.name));
setClickTab(true);
!isH5 && setScrollId(item.id);
setTimeout(() => {
setClickTab(false);
}, 800);
}}>
{item.name}
</View>);
const changeTop = id => {
const query = _createSelectorQuery();
const view = query.select("#" + id);
const topView = query.select("#" + tabs[0].id);
let top = 0;
new Promise(resolve => {
topView.boundingClientRect().exec(res => {
const data = res[0];
resolve(data.top);
});
}).then(res => {
top = res;
new Promise(resolve => {
view.boundingClientRect().exec(res => {
const data = res[getRectNumber()];
setTimeout(() => {
const endTop = Math.abs(top - data.top);
setScrollContent(endTop);
scrollTab = false;
resolve();
}, 300);
});
});
});
};
const weappComponent = <ScrollView scrollY scrollWithAnimation scrollAnimationDuration={200} style={{
height: props.height === "full" ? "100%" : Taro.pxTransform(props.height),
maxHeight: "100vh",
width: "100%"
}} scrollIntoView={scrollId} onScroll={onScroll} scrollTop={isAliPay ? undefined : scrollContent} enableBackToTop={props.backTop}>
{this.props.children}
</ScrollView>;
const h5Component = <ScrollView scrollY scrollWithAnimation scrollAnimationDuration={200} style={{
height: props.height === "full" ? "100%" : Taro.pxTransform(props.height),
maxHeight: "100vh",
width: "100%"
}} onScroll={onH5Scroll} scrollTop={scrollContent} enableBackToTop={props.backTop}>
{this.props.children}
</ScrollView>;
return <View className={classNames("flex", props.className)} style={Object.assign({}, props.style)}>
<ScrollView scrollY scrollWithAnimation className="VerticalNav nav" style={{
height: props.height === "full" ? "100%" : Taro.pxTransform(props.height),
maxHeight: "100vh"
}} scrollTop={(verticalNavTop - 1) * screenPercent * 100} enableBackToTop={props.backTop}>
{tabsComponent}
</ScrollView>
{isH5 ? h5Component : weappComponent}
</View>;
}
}
ClVerticalTab.options = {
addGlobalClass: true
};
ClVerticalTab.defaultProps = {
tabs: [{ name: "", id: "" }],
height: 0,
current: "",
backTop: false
};