Taro自定義Modal對話框組件|taro仿微信、android彈窗

来源:https://www.cnblogs.com/xiaoyan2017/archive/2019/12/02/11969729.html
-Advertisement-
Play Games

基於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自定義彈窗組件實現方式,希望能有幫助✊✊~~

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 原始數據類型: number, string, boolean, undefined, null, object 基本類型(簡單類型), 即值類型: number, string, boolean 複雜類型(引用類型): object 空類型:undefined, null 存儲空間 值類型的值在哪 ...
  • 1. 對象: 有屬性和方法,特指的某個事物 對象: 一組無序屬性的集合的鍵值對,屬性的值可以是任意的類型 2.JSON格式的數據:一般都是成對的,是鍵值對, json也是一個對象, 數據都是成對的, 一般json格式的數據無論是鍵還是值都是用雙引號括起來的 var json = { "name": ...
  • 在使用jquery-validate.js插件時可以做一些初始化配置在初始化jquery-validate.js對象的時候,將外部的一些配置和該插件內部的一些預設配置合併在一起,如果有相同的配置,前者覆蓋後者(預設)的配置 // Constructor for validator $.validat ...
  • JS是一門什麼樣的語言? 是一門解釋性的語言 是一門腳本語言 是一門弱類型語言,聲明變數都用var 是一門基於對象的語言 是一門動態類型的語言: 1. 代碼(變數)只有執行到這個位置的時候,才知道這個變數中到底存儲的是什麼,如果是對象,就有對象的屬性和方法,如果是變數就是變數的作用 2. 對象沒有什 ...
  • 1. 簡書類 實現效果 html代碼 <div class="container"> <form action="" class="parent"> <input type="text" class="search" placeholder="搜索"> <input type="button" na ...
  • javascript 報錯 string.split is not a function ...
  • 自定義html元素滑鼠右鍵菜單 實現思路 在觸發contextmenu事件時,取消預設行為(也就是阻止瀏覽器顯示自帶的菜單),獲取右鍵事件對象,來確定滑鼠的點擊位置,作為顯示菜單的left和top值 編碼實現 <!DOCTYPE html> <html> <head> <meta charset=" ...
  • 功能:在文本框中輸入待辦事項按下回車後,事項會出現在未完成列表中;點擊未完成事項前邊的覆選框後,該事項會出現在已完成列表中,反之亦然;點擊刪除按鈕會刪除該事項。待辦事項的數據是保存到本地存儲的(localStorage),就算關閉頁面再打開,數據還是存在的(前提是要用相同瀏覽器)。 ToDoList ...
一周排行
    -Advertisement-
    Play Games
  • 概述:在C#中,++i和i++都是自增運算符,其中++i先增加值再返回,而i++先返回值再增加。應用場景根據需求選擇,首碼適合先增後用,尾碼適合先用後增。詳細示例提供清晰的代碼演示這兩者的操作時機和實際應用。 在C#中,++i 和 i++ 都是自增運算符,但它們在操作上有細微的差異,主要體現在操作的 ...
  • 上次發佈了:Taurus.MVC 性能壓力測試(ap 壓測 和 linux 下wrk 壓測):.NET Core 版本,今天計劃準備壓測一下 .NET 版本,來測試並記錄一下 Taurus.MVC 框架在 .NET 版本的性能,以便後續持續優化改進。 為了方便對比,本文章的電腦環境和測試思路,儘量和... ...
  • .NET WebAPI作為一種構建RESTful服務的強大工具,為開發者提供了便捷的方式來定義、處理HTTP請求並返迴響應。在設計API介面時,正確地接收和解析客戶端發送的數據至關重要。.NET WebAPI提供了一系列特性,如[FromRoute]、[FromQuery]和[FromBody],用 ...
  • 原因:我之所以想做這個項目,是因為在之前查找關於C#/WPF相關資料時,我發現講解圖像濾鏡的資源非常稀缺。此外,我註意到許多現有的開源庫主要基於CPU進行圖像渲染。這種方式在處理大量圖像時,會導致CPU的渲染負擔過重。因此,我將在下文中介紹如何通過GPU渲染來有效實現圖像的各種濾鏡效果。 生成的效果 ...
  • 引言 上一章我們介紹了在xUnit單元測試中用xUnit.DependencyInject來使用依賴註入,上一章我們的Sample.Repository倉儲層有一個批量註入的介面沒有做單元測試,今天用這個示例來演示一下如何用Bogus創建模擬數據 ,和 EFCore 的種子數據生成 Bogus 的優 ...
  • 一、前言 在自己的項目中,涉及到實時心率曲線的繪製,項目上的曲線繪製,一般很難找到能直接用的第三方庫,而且有些還是定製化的功能,所以還是自己繪製比較方便。很多人一聽到自己畫就害怕,感覺很難,今天就分享一個完整的實時心率數據繪製心率曲線圖的例子;之前的博客也分享給DrawingVisual繪製曲線的方 ...
  • 如果你在自定義的 Main 方法中直接使用 App 類並啟動應用程式,但發現 App.xaml 中定義的資源沒有被正確載入,那麼問題可能在於如何正確配置 App.xaml 與你的 App 類的交互。 確保 App.xaml 文件中的 x:Class 屬性正確指向你的 App 類。這樣,當你創建 Ap ...
  • 一:背景 1. 講故事 上個月有個朋友在微信上找到我,說他們的軟體在客戶那邊隔幾天就要崩潰一次,一直都沒有找到原因,讓我幫忙看下怎麼回事,確實工控類的軟體環境複雜難搞,朋友手上有一個崩潰的dump,剛好丟給我來分析一下。 二:WinDbg分析 1. 程式為什麼會崩潰 windbg 有一個厲害之處在於 ...
  • 前言 .NET生態中有許多依賴註入容器。在大多數情況下,微軟提供的內置容器在易用性和性能方面都非常優秀。外加ASP.NET Core預設使用內置容器,使用很方便。 但是筆者在使用中一直有一個頭疼的問題:服務工廠無法提供請求的服務類型相關的信息。這在一般情況下並沒有影響,但是內置容器支持註冊開放泛型服 ...
  • 一、前言 在項目開發過程中,DataGrid是經常使用到的一個數據展示控制項,而通常表格的最後一列是作為操作列存在,比如會有編輯、刪除等功能按鈕。但WPF的原始DataGrid中,預設只支持固定左側列,這跟大家習慣性操作列放最後不符,今天就來介紹一種簡單的方式實現固定右側列。(這裡的實現方式參考的大佬 ...