diff --git a/src/Message.tsx b/src/Message.tsx index 25f7226..8d984df 100644 --- a/src/Message.tsx +++ b/src/Message.tsx @@ -1,63 +1,65 @@ -import React, { useRef, useState, useEffect } from 'react' -import Taro from '@tarojs/taro' -import classNames from 'classnames' -import { View } from '@tarojs/components' +import React, { useRef, useState, useEffect } from 'react'; +import Taro from '@tarojs/taro'; +import classNames from 'classnames'; +import { View } from '@tarojs/components'; -import '../style/Message.scss' +import '../style/Message.scss'; export interface MessageProps { - className?: string - style?: React.CSSProperties + className?: string; + style?: React.CSSProperties; } // 绑定函数 -Taro.atMessage = Taro.eventCenter.trigger.bind(Taro.eventCenter, 'atMessage') - -export const Message: React.FC = props => { - const { className, style } = props - - const timerRef = useRef() - const [{ isOpened, type, message }, setState] = useState({ - isOpened: false, - message: '', - type: 'info', - duration: 3000, - }) - - const atMessageHandler = (options = {} as Taro.AtMessageOptions) => { - clearTimeout(timerRef.current) - - const { message, type, duration = 3000 } = options - setState(prev => ({ ...prev, isOpened: true, message, type, duration })) - - timerRef.current = setTimeout(() => setState(prev => ({ ...prev, isOpened: false })), duration) - } - - useEffect(() => { - Taro.eventCenter.on('atMessage', atMessageHandler) - - return () => Taro.eventCenter.off('atMessage', atMessageHandler) - }, []) - - // TODO taro 3.0.0-beta.3 不允许子包中出现 @tarojs/runtime, link 后 runtime 中提供的 hooks 全部失效. - // useDidShow(() => { - // Taro.eventCenter.on('atMessage', atMessageHandler) - // }) - // useDidHide(() => { - // Taro.eventCenter.off('atMessage', atMessageHandler) - // }) - - return ( - - {message} - - ) -} +Taro.atMessage = Taro.eventCenter.trigger.bind(Taro.eventCenter, 'atMessage'); + +export const Message: React.FC = (props) => { + const { className, style } = props; + + const timerRef = useRef(); + const [{ isOpened, type, message }, setState] = useState({ + isOpened: false, + message: '', + type: 'info', + duration: 3000, + }); + + const atMessageHandler = (options = {} as Taro.AtMessageOptions) => { + clearTimeout(timerRef.current); + + const { message, type, duration = 3000 } = options; + setState((prev) => ({ ...prev, isOpened: true, message, type, duration })); + + timerRef.current = setTimeout(() => setState((prev) => ({ ...prev, isOpened: false })), duration); + }; + + useEffect(() => { + Taro.eventCenter.on('atMessage', atMessageHandler); + + return () => { + Taro.eventCenter.off('atMessage', atMessageHandler); + }; + }, []); + + // TODO taro 3.0.0-beta.3 不允许子包中出现 @tarojs/runtime, link 后 runtime 中提供的 hooks 全部失效. + // useDidShow(() => { + // Taro.eventCenter.on('atMessage', atMessageHandler) + // }) + // useDidHide(() => { + // Taro.eventCenter.off('atMessage', atMessageHandler) + // }) + + return ( + + {message} + + ); +}; diff --git a/src/Modal.tsx b/src/Modal.tsx index 4dff1d0..0c288d0 100644 --- a/src/Modal.tsx +++ b/src/Modal.tsx @@ -1,90 +1,90 @@ -import React, { useCallback } from 'react' -import classNames from 'classnames' -import { View, ScrollView, Button } from '@tarojs/components' -import { AtModalProps } from 'taro-ui/types/modal' +import React, { useCallback } from 'react'; +import classNames from 'classnames'; +import { View, ScrollView, Button } from '@tarojs/components'; +import { AtModalProps } from 'taro-ui/types/modal'; -import '../style/Modal.scss' +import '../style/Modal.scss'; export interface ModalProps extends Omit { - style?: React.CSSProperties - title?: React.ReactNode - content?: React.ReactNode + style?: React.CSSProperties; + title?: React.ReactNode; + content?: React.ReactNode; } -export const Modal: React.FC = props => { - const { - className, - style = {}, - children, - isOpened, - title, - content, - cancelText, - confirmText, - closeOnClickOverlay = true, - } = props +export const Modal: React.FC = (props) => { + const { + className, + style = {}, + children, + isOpened, + title, + content, + cancelText, + confirmText, + closeOnClickOverlay = true, + } = props; - const onClose = useCallback( - e => { - props.onClose?.(e) - }, - [props.onClose] - ) + const onClose = useCallback( + (e) => { + props.onClose?.(e); + }, + [props.onClose] + ); - const onCancel = useCallback( - e => { - props.onCancel?.(e) - onClose(e) - }, - [props.onCancel, onClose] - ) + const onCancel = useCallback( + (e) => { + props.onCancel?.(e); + onClose(e); + }, + [props.onCancel, onClose] + ); - const onConfirm = useCallback( - e => { - props.onConfirm?.(e) - }, - [props.onConfirm] - ) + const onConfirm = useCallback( + (e) => { + props.onConfirm?.(e); + }, + [props.onConfirm] + ); - const onClickOverlay = useCallback( - e => { - if (closeOnClickOverlay) { - onClose(e) - } - }, - [closeOnClickOverlay, onClose] - ) + const onClickOverlay = useCallback( + (e) => { + if (closeOnClickOverlay) { + onClose(e); + } + }, + [closeOnClickOverlay, onClose] + ); - const rootClass = classNames('at-modal', { 'at-modal--active': isOpened }, className) - - if (title || content) { - return ( - - - - {title && {title}} - {content && ( - - {content} - - )} - {(cancelText || confirmText) && ( - - - {cancelText && } - {confirmText && } - - - )} - - - ) - } + const rootClass = classNames('at-modal', { 'at-modal--active': isOpened }, className); + if (title || content) { return ( - e.stopPropagation()}> - - {children} + + + + {title && {title}} + {content && ( + + {content} + + )} + {(cancelText || confirmText) && ( + + + {cancelText && } + {confirmText && } + + + )} - ) -} + + ); + } + + return ( + e.stopPropagation()}> + + {children} + + ); +}; diff --git a/src/utils.ts b/src/utils.ts index a193279..3cf46c0 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,254 +1,255 @@ -import Taro from '@tarojs/taro' -import { SelectorQuery } from '@tarojs/taro/types/index' +import Taro from '@tarojs/taro'; +import { SelectorQuery } from '@tarojs/taro/types/index'; -const ENV = Taro.getEnv() +const ENV = Taro.getEnv(); -function delay(delayTime = 25): Promise { - return new Promise((resolve) => { - setTimeout(() => { - resolve() - }, delayTime) - }) +function delay(delayTime = 25) { + return new Promise((resolve) => { + setTimeout(() => { + resolve(); + }, delayTime); + }); } export function delayQuerySelector(selectorStr: string, delayTime = 500): Promise { - return new Promise((resolve) => { - const selector: SelectorQuery = Taro.createSelectorQuery() - delay(delayTime).then(() => { - selector - .select(selectorStr) - .boundingClientRect() - .exec((res: any[]) => { - resolve(res) - }) - }) - }) + return new Promise((resolve) => { + const selector: SelectorQuery = Taro.createSelectorQuery(); + delay(delayTime).then(() => { + selector + .select(selectorStr) + .boundingClientRect() + .exec((res: any[]) => { + resolve(res); + }); + }); + }); } function delayGetScrollOffset({ delayTime = 500 }): Promise { - return new Promise((resolve) => { - delay(delayTime).then(() => { - Taro.createSelectorQuery() - .selectViewport() - .scrollOffset() - .exec((res: any[]) => { - resolve(res) - }) - }) - }) + return new Promise((resolve) => { + delay(delayTime).then(() => { + Taro.createSelectorQuery() + .selectViewport() + .scrollOffset() + .exec((res: any[]) => { + resolve(res); + }); + }); + }); } function delayGetClientRect({ selectorStr, delayTime = 500 }): Promise { - const selector: SelectorQuery = Taro.createSelectorQuery() - - return new Promise((resolve) => { - delay(delayTime).then(() => { - selector - .select(selectorStr) - .boundingClientRect() - .exec((res: any[]) => { - resolve(res) - }) - }) - }) + const selector: SelectorQuery = Taro.createSelectorQuery(); + + return new Promise((resolve) => { + delay(delayTime).then(() => { + selector + .select(selectorStr) + .boundingClientRect() + .exec((res: any[]) => { + resolve(res); + }); + }); + }); } export function uuid(len = 8, radix = 16): string { - const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('') - const value: string[] = [] - let i = 0 - radix = radix || chars.length - - if (len) { - // Compact form - for (i = 0; i < len; i++) value[i] = chars[0 | (Math.random() * radix)] - } else { - // rfc4122, version 4 form - let r - - // rfc4122 requires these characters - /* eslint-disable-next-line */ - value[8] = value[13] = value[18] = value[23] = '-' - value[14] = '4' - - // Fill in random data. At i==19 set the high bits of clock sequence as - // per rfc4122, sec. 4.1.5 - for (i = 0; i < 36; i++) { - if (!value[i]) { - r = 0 | (Math.random() * 16) - value[i] = chars[i === 19 ? (r & 0x3) | 0x8 : r] - } - } + const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split(''); + const value: string[] = []; + let i = 0; + radix = radix || chars.length; + + if (len) { + // Compact form + for (i = 0; i < len; i++) value[i] = chars[0 | (Math.random() * radix)]; + } else { + // rfc4122, version 4 form + let r; + + // rfc4122 requires these characters + /* eslint-disable-next-line */ + value[8] = value[13] = value[18] = value[23] = '-'; + value[14] = '4'; + + // Fill in random data. At i==19 set the high bits of clock sequence as + // per rfc4122, sec. 4.1.5 + for (i = 0; i < 36; i++) { + if (!value[i]) { + r = 0 | (Math.random() * 16); + value[i] = chars[i === 19 ? (r & 0x3) | 0x8 : r]; + } } + } - return value.join('') + return value.join(''); } interface EventDetail { - pageX: number - pageY: number - clientX: number - clientY: number - offsetX: number - offsetY: number - x: number - y: number + pageX: number; + pageY: number; + clientX: number; + clientY: number; + offsetX: number; + offsetY: number; + x: number; + y: number; } function getEventDetail(event: any): EventDetail { - let detail: EventDetail - switch (ENV) { - case Taro.ENV_TYPE.WEB: - detail = { - pageX: event.pageX, - pageY: event.pageY, - clientX: event.clientX, - clientY: event.clientY, - offsetX: event.offsetX, - offsetY: event.offsetY, - x: event.x, - y: event.y, - } - break - - case Taro.ENV_TYPE.WEAPP: - detail = { - pageX: event.touches[0].pageX, - pageY: event.touches[0].pageY, - clientX: event.touches[0].clientX, - clientY: event.touches[0].clientY, - offsetX: event.target.offsetLeft, - offsetY: event.target.offsetTop, - x: event.target.x, - y: event.target.y, - } - break - - case Taro.ENV_TYPE.ALIPAY: - detail = { - pageX: event.target.pageX, - pageY: event.target.pageY, - clientX: event.target.clientX, - clientY: event.target.clientY, - offsetX: event.target.offsetLeft, - offsetY: event.target.offsetTop, - x: event.target.x, - y: event.target.y, - } - break - - case Taro.ENV_TYPE.SWAN: - detail = { - pageX: event.changedTouches[0].pageX, - pageY: event.changedTouches[0].pageY, - clientX: event.target.clientX, - clientY: event.target.clientY, - offsetX: event.target.offsetLeft, - offsetY: event.target.offsetTop, - x: event.detail.x, - y: event.detail.y, - } - break - - default: - detail = { - pageX: 0, - pageY: 0, - clientX: 0, - clientY: 0, - offsetX: 0, - offsetY: 0, - x: 0, - y: 0, - } - console.warn('getEventDetail暂未支持该环境') - break - } - return detail + let detail: EventDetail; + switch (ENV) { + case Taro.ENV_TYPE.WEB: + detail = { + pageX: event.pageX, + pageY: event.pageY, + clientX: event.clientX, + clientY: event.clientY, + offsetX: event.offsetX, + offsetY: event.offsetY, + x: event.x, + y: event.y, + }; + break; + + case Taro.ENV_TYPE.WEAPP: + detail = { + pageX: event.touches[0].pageX, + pageY: event.touches[0].pageY, + clientX: event.touches[0].clientX, + clientY: event.touches[0].clientY, + offsetX: event.target.offsetLeft, + offsetY: event.target.offsetTop, + x: event.target.x, + y: event.target.y, + }; + break; + + case Taro.ENV_TYPE.ALIPAY: + detail = { + pageX: event.target.pageX, + pageY: event.target.pageY, + clientX: event.target.clientX, + clientY: event.target.clientY, + offsetX: event.target.offsetLeft, + offsetY: event.target.offsetTop, + x: event.target.x, + y: event.target.y, + }; + break; + + case Taro.ENV_TYPE.SWAN: + detail = { + pageX: event.changedTouches[0].pageX, + pageY: event.changedTouches[0].pageY, + clientX: event.target.clientX, + clientY: event.target.clientY, + offsetX: event.target.offsetLeft, + offsetY: event.target.offsetTop, + x: event.detail.x, + y: event.detail.y, + }; + break; + + default: + detail = { + pageX: 0, + pageY: 0, + clientX: 0, + clientY: 0, + offsetX: 0, + offsetY: 0, + x: 0, + y: 0, + }; + console.warn('getEventDetail暂未支持该环境'); + break; + } + return detail; } export function setEventDetail(e: E, detail: any) { - if (process.env.TARO_ENV === 'h5') { - return Object.create(e as any, { detail: { value: detail } }) - } else { - e['detail'] = detail - return e - } + if (process.env.TARO_ENV === 'h5') { + return Object.create(e as any, { detail: { value: detail } }); + } else { + e['detail'] = detail; + return e; + } } function initTestEnv(): void { - if (process.env.NODE_ENV === 'test') { - Taro.initPxTransform({ - designWidth: 750, - deviceRatio: { - '640': 2.34 / 2, - '750': 1, - '828': 1.81 / 2, - }, - }) - } + if (process.env.NODE_ENV === 'test') { + Taro.initPxTransform({ + designWidth: 750, + deviceRatio: { + '640': 2.34 / 2, + '750': 1, + '828': 1.81 / 2, + }, + }); + } } function isTest(): boolean { - return process.env.NODE_ENV === 'test' + return process.env.NODE_ENV === 'test'; } -let scrollTop = 0 +let scrollTop = 0; function handleTouchScroll(flag: any): void { - if (ENV !== Taro.ENV_TYPE.WEB) { - return - } - if (flag) { - scrollTop = document.documentElement.scrollTop - - // 使body脱离文档流 - document.body.classList.add('at-frozen') - - // 把脱离文档流的body拉上去!否则页面会回到顶部! - document.body.style.top = `${-scrollTop}px` - } else { - document.body.style.top = '' - document.body.classList.remove('at-frozen') - - document.documentElement.scrollTop = scrollTop - } + if (ENV !== Taro.ENV_TYPE.WEB) { + return; + } + if (flag) { + scrollTop = document.documentElement.scrollTop; + + // 使body脱离文档流 + document.body.classList.add('at-frozen'); + + // 把脱离文档流的body拉上去!否则页面会回到顶部! + document.body.style.top = `${-scrollTop}px`; + } else { + document.body.style.top = ''; + document.body.classList.remove('at-frozen'); + + document.documentElement.scrollTop = scrollTop; + } } function pxTransform(size: number): string { - if (!size) return '' - const designWidth = 750 - const deviceRatio = { - 640: 2.34 / 2, - 750: 1, - 828: 1.81 / 2, - } - return `${size / deviceRatio[designWidth]}rpx` + if (!size) return ''; + const designWidth = 750; + const deviceRatio = { + 640: 2.34 / 2, + 750: 1, + 828: 1.81 / 2, + }; + return `${size / deviceRatio[designWidth]}rpx`; } function objectToString(style: object | string): string { - if (style && typeof style === 'object') { - let styleStr = '' - Object.keys(style).forEach((key) => { - const lowerCaseKey = key.replace(/([A-Z])/g, '-$1').toLowerCase() - styleStr += `${lowerCaseKey}:${style[key]};` - }) - return styleStr - } else if (style && typeof style === 'string') { - return style - } - return '' + if (style && typeof style === 'object') { + let styleStr = ''; + Object.keys(style).forEach((key) => { + const lowerCaseKey = key.replace(/([A-Z])/g, '-$1').toLowerCase(); + styleStr += `${lowerCaseKey}:${style[key]};`; + }); + return styleStr; + } else if (style && typeof style === 'string') { + return style; + } + return ''; } /** * 合并 style - * @param {Object|String} style1 - * @param {Object|String} style2 + * + * @param {Object | String} style1 + * @param {Object | String} style2 * @returns {String} */ function mergeStyle(style1: object | string, style2: object | string): object | string { - if (style1 && typeof style1 === 'object' && style2 && typeof style2 === 'object') { - return Object.assign({}, style1, style2) - } - return objectToString(style1) + objectToString(style2) + if (style1 && typeof style1 === 'object' && style2 && typeof style2 === 'object') { + return Object.assign({}, style1, style2); + } + return objectToString(style1) + objectToString(style2); }