基於Taro多端實踐TaroPop:自定義模態框|dialog對話框|msg消息框|Toast提示 taro自定義彈出框支持編譯到多端H5/小程式/ReactNative,還可以自定義彈窗類型/彈窗樣式、多按鈕事件/樣式、自動關閉、遮罩層、彈窗顯示位置及自定義內容模板 用法 ▍在相應頁面引入組件 i ...
基於Taro多端實踐TaroPop:自定義模態框|dialog對話框|msg消息框|Toast提示
taro自定義彈出框支持編譯到多端H5/小程式/ReactNative,還可以自定義彈窗類型/彈窗樣式、多按鈕事件/樣式、自動關閉、遮罩層、彈窗顯示位置及自定義內容模板
用法
▍在相應頁面引入組件
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> ); } }
通過ref方式調用組件內show、close方法
this.refs.taroPop.show({...options})
this.refs.taroPop.close()
▍自定義彈窗模板內容(如下圖)
只需把頁面上的模板寫成如下即可,調用方式還和上面一樣
<TaroPop ref="taroPopTpl">
...
</TaroPop>
支持多種參數配置:
/** * @ 彈窗預設配置 */ 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}] }
/** * 顯示彈窗事件 */ 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) } /** * 點擊遮罩關閉 */ shadeClick = () => { if(!this.state.shadeClose) return this.close() }
◆ msg消息框提示
this.refs.taroPop.show({ content: 'Taro自定義模態Modal彈窗', shadeClose: false, style: {backgroundColor: 'rgba(0,0,0,.7)', borderRadius: 6}, contentStyle: {color: '#fff', fontSize: 12, padding: 12}, time: 3, opacity: .2, })
◆ Toast輕提示效果(success | error | info | loading四種圖標)
let taroPop = this.refs.taroPop taroPop.show({ skin: 'toast', content: 'loading', icon: 'loading', //success | info | error | loading shade: false, time: 3 })
◆ android彈窗效果
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('您點擊了前往設置!') } } ] })
emmmm,看瞭如上展示及調用方式,是否覺得還不錯喲!哈哈哈,這可是花了無數個日夜採坑的結果。
尤其是編譯到reactNative端,各種千奇百怪的問題,有些抓狂~~
另外對於不同端的一些相容性處理,需要判斷各端環境並渲染相應模板,對於RN,則使用Modal
let taroEnv = process.env.TARO_ENV // 渲染窗體 if (taroEnv === 'rn') { return ( <Modal transparent={true} visible={isVisible} onRequestClose={this.close}> {renderTpl} </Modal> ) }else if (taroEnv === 'h5' || taroEnv === 'weapp'){ return isVisible && renderTpl }
另外在樣式處理上也需註意RN端相容性。
/** * @Title Taro自定義彈窗組件 - taroPop.js * @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 } /** * @ 顯示彈窗事件 */ 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) } /** * @ 點擊遮罩關閉 */ shadeClick = () => { if(!this.state.shadeClose) return this.close() } 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="atpop__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 } } }
好了,以上就是taro自定義彈窗組件實現方式,希望能有幫助✊✊~~