UNPKG

taro-ui-vue3

Version:

Taro UI Rewritten in Vue 3.0

225 lines (224 loc) 6.93 kB
var __defProp = Object.defineProperty; var __hasOwnProp = Object.prototype.hasOwnProperty; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, {enumerable: true, configurable: true, writable: true, value}) : obj[key] = value; var __objSpread = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; import { h, computed, defineComponent, mergeProps, onMounted, ref, reactive, watch } from "vue"; import {ScrollView, View, Text} from "@tarojs/components"; import Taro from "@tarojs/taro"; import {uuid} from "../utils/common"; const ENV = Taro.getEnv(); const MIN_DISTANCE = 100; const MAX_INTERVAL = 10; const AtTabs = defineComponent({ name: "AtTabs", props: { tabDirection: { type: String, default: "horizontal" }, height: { type: String, default: "" }, current: { type: Number, default: 0 }, scroll: Boolean, animated: { type: Boolean, default: true }, swipeable: { type: Boolean, default: true }, tabList: { type: Array, default: [] }, onClick: { type: Function, default: () => (index, event) => { } } }, setup(props, {attrs, slots}) { const _tabId = ref(uuid()); const _touchDot = ref(0); const _timer = ref(null); const _interval = ref(0); const _isMoving = ref(false); const tabHeaderRef = ref(null); const state = reactive({ _scrollLeft: 0, _scrollTop: 0, _scrollIntoView: "" }); const scrollX = computed(() => props.tabDirection === "horizontal"); const scrollY = computed(() => props.tabDirection === "vertical"); const rootClass = computed(() => ({ "at-tabs": true, "at-tabs--scroll": props.scroll, [`at-tabs--${props.tabDirection}`]: true, [`at-tabs--${ENV}`]: true })); const heightStyle = computed(() => ({height: props.height})); const underlineStyle = computed(() => ({ height: props.tabDirection === "vertical" ? `${props.tabList.length * 100}%` : "1PX", width: props.tabDirection === "horizontal" ? `${props.tabList.length * 100}%` : "1PX" })); const bodyStyle = computed(() => { const bodyStyle2 = __objSpread({}, heightStyle.value); let transformStyle = `translate3d(0px, -${props.current * 100}%, 0px)`; if (props.tabDirection === "horizontal") { transformStyle = `translate3d(-${props.current * 100}%, 0px, 0px)`; } Object.assign(bodyStyle2, { transform: transformStyle, "-webkit-transform": transformStyle }); if (!props.animated) { bodyStyle2.transition = "unset"; } return bodyStyle2; }); const tabItemClass = computed(() => (idx) => ({ "at-tabs__item": true, "at-tabs__item--active": props.current === idx })); function updateState(idx) { if (props.scroll) { if (ENV !== Taro.ENV_TYPE.WEB) { const index = Math.max(idx - 1, 0); state._scrollIntoView = `tab${_tabId.value}${index}`; } else { const index = Math.max(idx - 1, 0); const prevTabItem = tabHeaderRef.value.$el.children[index]; if (prevTabItem) { state._scrollTop = prevTabItem.offsetTop; state._scrollLeft = prevTabItem.offsetLeft; } } } } function handleClick(index, event) { props.onClick(index, event); } function handleTouchStart(e) { if (!props.swipeable || props.tabDirection === "vertical") return; _touchDot.value = e.touches[0].pageX; _timer.value = setInterval(() => { _interval.value++; }, 100); } function handleTouchMove(e) { if (!props.swipeable || props.tabDirection === "vertical") return; const touchMove = e.touches[0].pageX; const moveDistance = touchMove - _touchDot.value; const maxIndex = props.tabList.length; if (!_isMoving.value && _interval.value < MAX_INTERVAL && _touchDot.value > 20) { if (props.current + 1 < maxIndex && moveDistance <= -MIN_DISTANCE) { _isMoving.value = true; handleClick(props.current + 1, e); } else if (props.current - 1 >= 0 && moveDistance >= MIN_DISTANCE) { _isMoving.value = true; handleClick(props.current - 1, e); } } } function handleTouchEnd() { if (!props.swipeable || props.tabDirection === "vertical") return; clearInterval(_timer.value); _interval.value = 0; _isMoving.value = false; } watch(() => props.current, (current) => { updateState(current); }); onMounted(() => { updateState(props.current); }); return () => { const tabItems = props.tabList.map((item, idx) => h(View, { id: `tab${_tabId.value}${idx}`, key: item.title, class: tabItemClass.value(idx), onTap: handleClick.bind(this, idx) }, { default: () => [ h(Text, { style: "white-space: nowrap;" }, {default: () => item.title}), h(View, {class: "at-tabs__item-underline"}) ] })); return h(View, mergeProps(attrs, { class: rootClass.value, style: heightStyle.value }), { default: () => [ props.scroll ? h(ScrollView, mergeProps(ENV === Taro.ENV_TYPE.WEB ? {ref: (el) => { tabHeaderRef.value = el; }} : {}, { id: _tabId.value, class: "at-tabs__header", style: heightStyle.value, scrollX: scrollX.value, scrollY: scrollY.value, scrollWithAnimation: true, scrollLeft: state._scrollLeft, scrollTop: state._scrollTop, scrollIntoView: state._scrollIntoView }), {default: () => tabItems}) : h(View, { id: _tabId.value, class: "at-tabs__header" }, {default: () => tabItems}), h(View, { class: "at-tabs__body", style: bodyStyle.value, onTouchstart: handleTouchStart, onTouchend: handleTouchEnd, onTouchmove: handleTouchMove }, { default: () => [ h(View, { class: "at-tabs__underline", style: underlineStyle.value }), slots.default && slots.default() ] }) ] }); }; } }); var tabs_default = AtTabs; export { tabs_default as default };