zoukankan      html  css  js  c++  java
  • Taro自定义Modal对话框组件|taro仿微信、android弹窗

    基于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自定义弹窗组件实现方式,希望能有帮助✊✊~~

  • 相关阅读:
    [题解] [NOIP2008] 双栈排序——关系的冲突至图论解法
    [搬运] [贪心]NOIP2011 观光公交
    [总结] 最短路径数问题
    [持续更新]一些zyys的题的集合
    [教程]Ubuntu下完整配置自动壁纸切换
    在NOILINUX下的简易VIM配置
    [模板]ST表浅析
    21、Android--RecyclerView
    20、Android--GridView
    19、Android--ListView
  • 原文地址:https://www.cnblogs.com/xiaoyan2017/p/11969729.html
Copyright © 2011-2022 走看看