
基于 Taro/React 多端实践:自定义 Modal 组件|Toast 加载框|dialog 对话框
之前有使用 taro 做过自定义导航栏 /tabbar,想着继续做个自定义弹窗,看了官网 taro-ui 组件里面的弹窗功能 /样式甚是不满意,如是就自己动手开发taroPop 自定义模态框组件。
支持自定义弹窗样式及类型、自定义按钮事件 /样式、自动关闭、遮罩层、自定义模板内容等功能
在页面引入 taroPop 组件
import TaroPop from '@components/taroPop' import Taro from '@tarojs/taro' import { View, Text } from '@tarojs/components' // 引入弹窗组件 import TaroPop from '@components/taroPop' export default class TaroPopDemo extends Taro.Component { ... render() { return ( <View className="taro-container"> ... {/* 弹窗模板 */} <TaroPop ref="taroPop" /> </View> ); } } 通过如下方法调用组件 show/close 方法
this.refs.taroPop.show({...options}) this.refs.taroPop.close() /** * 显示弹窗事件 */ show = (options) => { this.setState({ ...this.props, ...options, isVisible: true }) } /** * 关闭弹窗事件 */ close = () => { this.setState({...this.props}) this.timer && clearTimeout(this.timer) delete this.timer typeof this.state.end === 'function' && this.state.end.call(this) } static defaultProps = { isVisible: false, //弹窗显示 title: '', //标题 content: '', //内容 contentStyle: null, //内容样式 style: null, //自定义弹窗样式 skin: '', //弹窗风格 icon: '', //弹窗图标 xclose: false, //自定义关闭按钮 shade: true, //遮罩层 shadeClose: true, //点击遮罩关闭 opacity: '', //遮罩透明度 time: 0, //自动关闭时间 end: null, //销毁弹窗回调函数 position: '', //弹窗位置显示 btns: null, //弹窗按钮 [{...args}, {...args}] } this.refs.taroPop.show({ content: 'Taro 消息提示框( 3s 后窗口关闭)', shade: true, shadeClose: true, time: 3, anim: 'fadeIn', }) let taroPop = this.refs.taroPop taroPop.show({ skin: 'ios', title: '消息提示', content: 'ios 弹窗效果 (弹窗内容,用于告知当前状态、提示信息和解决方法,描述文字 /文案尽量控制在三行内)', shadeClose: false, btns: [ { text: '取消', style: {color: '#6190e8'}, onClick() { taroPop.close() } }, { text: '不再提醒', style: {color: '#6190e8'}, onClick() { console.log('您点击了前往设置!') } } ] }) let taroPop = this.refs.taroPop taroPop.show({ skin: 'android', title: '邮件提醒', content: '系统检测到你未开启新邮件提醒功能,为了保证新邮件能及时收到提醒,请前往系统 [设置] - [应用] 中开启', shadeClose: false, btns: [ { text: '取消', onClick() { taroPop.close() } }, { text: '前往设置', style: {color: '#4eca33'}, onClick() { console.log('您点击了前往设置!') } } ] }) 还有更多效果,用法就不一一介绍了
/** * @Title Taro 自定义弹窗组件 - taroPop.jsx * @Time andy by 2019-11-28 * @About Q:282310962 wx:xy190310 */ import Taro from '@tarojs/taro' import { View, Text, Image } from '@tarojs/components' import { Modal, ActivityIndicator, TouchableHighlight } from 'react-native' import classNames from 'classnames' import './index.scss' export default class TaroPop extends Taro.Component { /** * @ 弹窗默认配置 */ static defaultProps = { isVisible: false, //弹窗显示 title: '', //标题 content: '', //内容 contentStyle: null, //内容样式 style: null, //自定义弹窗样式 skin: '', //弹窗风格 icon: '', //弹窗图标 xclose: false, //自定义关闭按钮 shade: true, //遮罩层 shadeClose: true, //点击遮罩关闭 opacity: '', //遮罩透明度 time: 0, //自动关闭时间 end: null, //销毁弹窗回调函数 anim: 'scaleIn', //弹窗动画 position: '', //弹窗位置显示 btns: null, //弹窗按钮 [{...args}, {...args}] } constructor(props) { super(props) this.state = { ...this.props, } this.timer = null } ... render() { let { isVisible, title, content, contentStyle, style, skin, icon, xclose, shade, shadeClose, opacity, time, end, anim, position, btns } = this.state let toastIcon = { loading: require('./skin/loading.png'), success: require('./skin/success.png'), error: require('./skin/error.png'), info: require('./skin/info.png'), } let taroEnv = process.env.TARO_ENV ... // 渲染 H5、RN 模板 const renderTpl = ( <View className="taroPop"> {/* 遮罩 */} {shade ? <View className="atpop__ui_mask" style={{opacity: opacity == '' ? .6 : opacity}} OnClick={this.shadeClick} /> : null} {/* 窗体 */} <View className="atpop__ui_main"> <View className={classNames('atpop__ui_child', skin && 'atpop__' + skin, position && 'atpop__ui_child-' + position)} style={style}> {/* 标题 */} {title ? <Text className={classNames('atpop__ui_tit', skin && 'atpop__ui_tit-' + skin)}>{title}</Text> : null} {/* 内容 */} {content ? <View className="atpo__ui_cnt"> {/* toast 内容 */} {icon && skin === 'toast' ? <View className="atpop__ui_toast"> {icon === 'loading' && taroEnv === 'rn' ? <ActivityIndicator color="rgba(255,255,255,.5)" size={24} /> : <Image className={classNames('atpop__ui_toast-img', icon=='loading' && 'atpop__ui_toast-img-loading')} src={toastIcon[icon]} mode="aspectFit" /> } </View> : null } {/* 文本内容 */} <Text className={classNames('atpop__ui_cntxt', skin && 'atpop__ui_cntxt-' + skin)} style={contentStyle}>{content}</Text> </View> : this.props.children } {/* 按钮 */} {btns ? <View className={classNames('atpop__ui_btns', skin && 'atpop__ui_btns-' + skin)}> {btns.map((item, i) => { return taroEnv === 'rn' ? <TouchableHighlight className={classNames('atpop__ui_btn', skin && 'atpop__ui_btn-' + skin)} activeOpacity={1} underlayColor='rgba(200,200,200,.3)' key={i} OnPress={item.onClick}> <Text className={classNames('atpop__ui_btntxt', skin && 'atpop__ui_btntxt-' + skin)} style={item.style}>{item.text}</Text> </TouchableHighlight> : <View className={classNames('atpop__ui_btn', skin && 'atpop__ui_btn-' + skin)} key={i} OnClick={item.onClick}> <Text className={classNames('atpop__ui_btntxt', skin && 'atpop__ui_btntxt-' + skin)} style={item.style}>{item.text}</Text> </View> })} </View> : null } </View> {/* xclose */} {xclose ? <View className="atpop__ui_xclose" OnClick={this.close}><Image className="atpop__ui_xclose-img" src={require('./skin/error.png')} mode="aspectFit" /></View> : null} </View> </View> ) // 渲染窗体 if (taroEnv === 'rn') { return ( <Modal transparent={true} visible={isVisible} OnRequestClose={this.close}> {renderTpl} </Modal> ) }else if (taroEnv === 'h5' || taroEnv === 'weapp'){ return isVisible && renderTpl } } } okay,今天的分享就到这里,希望能有些帮助,后面会继续分享一些实例~~
1 lblblong 2019 年 12 月 3 日 import './index.scss' 大佬,样式文件没有分享出来 |
2 xiaoyan2017 OP [taro+react 多端开发实践|仿微信聊天 App 实例|taro 聊天室|朋友圈]( https://blog.csdn.net/yanxinyun1990/article/details/103553872) |