taro-ui-vue3
Version:
Taro UI Rewritten in Vue 3.0
260 lines (259 loc) • 7.54 kB
JavaScript
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
import {
h,
defineComponent,
computed,
ref,
reactive,
nextTick,
watch,
onMounted,
onBeforeMount,
mergeProps
} from "vue";
import {
delayQuerySelector,
pxTransform
} from "../utils/common";
import Taro from "@tarojs/taro";
import {ScrollView, View} from "@tarojs/components";
import AtList from "../list";
import AtListItem from "../list/item";
import AtToast from "../toast";
const AtIndexes = defineComponent({
name: "AtIndexes",
props: {
animation: Boolean,
isVibrate: {
type: Boolean,
default: true
},
isShowToast: {
type: Boolean,
default: true
},
topKey: {
type: String,
default: "Top"
},
list: {
type: Array,
default: () => []
},
onClick: Function,
onScrollIntoView: Function
},
setup(props, {attrs, slots}) {
const scrollItemHeights = ref([]);
const currentIndex = ref(0);
const timeoutTimer = ref(null);
const state = reactive({
_scrollIntoView: "",
_scrollTop: 0,
_tipText: "",
_isShowToast: false,
isWEB: Taro.getEnv() === Taro.ENV_TYPE.WEB
});
const toastStyle = computed(() => ({
minWidth: pxTransform(100)
}));
const activeIndexStyle = computed(() => (i) => {
return currentIndex.value === i ? {
color: "white",
backgroundColor: "rgba(97, 144, 232, 1)",
borderRadius: "40px"
} : {};
});
watch(() => props.list, (list, prevList) => {
if (list.length !== prevList.length) {
initData();
}
});
function handleClick(item) {
props.onClick && props.onClick(item);
}
function jumpTarget(_scrollIntoView, idx) {
currentIndex.value = idx;
updateState({
_scrollIntoView,
_scrollTop: scrollItemHeights.value[idx],
_tipText: idx === 0 ? props.topKey : props.list[idx - 1].key
});
}
function __jumpTarget(key) {
const index = props.list.findIndex((item) => item.key === key);
const targetView = `at-indexes__list-${key}`;
jumpTarget(targetView, index + 1);
}
function updateState(stateValue) {
const {_scrollIntoView, _tipText, _scrollTop} = stateValue;
state._scrollIntoView = _scrollIntoView;
state._tipText = _tipText;
state._scrollTop = _scrollTop;
state._isShowToast = props.isShowToast;
nextTick(() => {
clearTimeout(timeoutTimer.value);
timeoutTimer.value = setTimeout(() => {
state._tipText = "";
state._isShowToast = false;
}, 1e3);
});
if (props.isVibrate) {
Taro.vibrateShort();
}
}
function initData() {
return __async(this, null, function* () {
if (props.list.length > 0) {
yield _getScrollListItemHeights(props.list).then((res) => {
scrollItemHeights.value = [...res];
});
}
});
}
function _getHeight(selector, delay) {
if (!delay) {
delay = 500;
}
return new Promise((resolve) => {
delayQuerySelector(this, selector, delay).then((rect) => {
if (rect && rect[0]) {
resolve(rect[0].height);
}
});
});
}
function _getScrollListItemHeights(list) {
return new Promise((resolve) => {
if (list.length > 0) {
let rawHeights = [];
let itemHeights = [];
rawHeights.push(_getHeight(`#at-indexes__top`));
list.forEach((item) => {
rawHeights.push(_getHeight(`#at-indexes__list-${item.key}`));
});
Promise.all(rawHeights).then((res) => {
let height = 0;
itemHeights.push(height);
for (let i = 0; i < res.length; i++) {
height += res[i];
itemHeights.push(height);
}
resolve(itemHeights);
});
}
});
}
function handleScroll(e) {
if (e && e.detail) {
state._scrollIntoView = "";
for (let i = 0; i < scrollItemHeights.value.length - 1; i++) {
let h1 = Math.floor(scrollItemHeights.value[i]);
let h2 = Math.floor(scrollItemHeights.value[i + 1]);
if (e.detail.scrollTop >= h1 && e.detail.scrollTop < h2) {
currentIndex.value = i;
return;
}
}
}
}
onMounted(() => {
initData();
});
onBeforeMount(() => {
props.onScrollIntoView && props.onScrollIntoView(__jumpTarget);
});
return () => h(View, mergeProps(attrs, {
class: "at-indexes"
}), {
default: () => [
h(View, {
class: "at-indexes__menu"
}, {
default: () => [
h(View, {
class: "at-indexes__menu-item",
style: activeIndexStyle.value(0),
onTap: jumpTarget.bind(this, "at-indexes__top", 0)
}, {default: () => props.topKey}),
...props.list.map((dataList, i) => {
const {key} = dataList;
const targetView = `at-indexes__list-${key}`;
return h(View, {
key: `${key}-${i}`,
class: "at-indexes__menu-item",
style: activeIndexStyle.value(i + 1),
onTap: jumpTarget.bind(this, targetView, i + 1)
}, {default: () => key});
})
]
}),
h(ScrollView, {
class: "at-indexes__body",
scrollY: true,
enableBackToTop: true,
scrollWithAnimation: props.animation,
scrollTop: state._scrollTop,
scrollIntoView: !state.isWEB ? state._scrollIntoView : "",
onScroll: (e) => handleScroll(e)
}, {
default: () => [
h(View, {
id: "at-indexes__top",
class: "at-indexes__content"
}, {default: () => slots.default && slots.default()}),
...props.list.map((dataList) => {
return h(View, {
id: `at-indexes__list-${dataList.key}`,
class: "at-indexes__list",
key: dataList.key
}, {
default: () => [
h(View, {
class: "at-indexes__list-title"
}, {default: () => dataList.title}),
h(AtList, null, {
default: () => dataList.items && dataList.items.map((item) => h(AtListItem, {
key: item.name,
title: item.name,
onClick: handleClick.bind(this, item)
}))
})
]
});
})
]
}),
h(AtToast, {
isOpened: state._isShowToast,
text: state._tipText,
duration: 1e3,
style: toastStyle.value
})
]
});
}
});
var indexes_default = AtIndexes;
export {
indexes_default as default
};