React实现PWA安装弹出模态框:按设备展示及仅首次加载触发问题
实现方案
1. 仅首次加载弹出弹窗的逻辑
用浏览器本地存储localStorage记录弹窗是否已经展示过,逻辑如下:
- 页面初始化时读取
localStorage中的a2hs_has_shown标记 - 标记不存在则打开弹窗,弹窗关闭时将标记写入
localStorage,后续访问就不会再弹出
2. 不同设备展示对应引导内容
将父组件的设备识别状态传递给弹窗组件,弹窗内部根据设备类型渲染对应的引导图和文案。
修改后的完整代码
const MasterIndexPage = () => { const classes = useStyles() const [isAndroid, setIsAndroid] = useState(false) const [isApple, setIsApple] = useState(false) const [isWindows, setIsWindows] = useState(false) useEffect(() => { const ua = navigator.userAgent if (ua.match(/Android/i)) { setIsAndroid(true) } else if (ua.match(/iPhone|iPod|iPad/i)) { setIsApple(true) } else { setIsWindows(true) } }, []) return ( <section> {/* 所有需要展示弹窗的设备都传入设备类型参数 */} {(isApple || isWindows || isAndroid) && <A2HSPrompt deviceType={isApple ? 'ios' : isWindows ? 'desktop' : 'android'} />} </section> ) } const A2HSPrompt = ({ deviceType }) => { const classes = useStyles() const [open, setOpen] = useState(false) useEffect(() => { // 读取本地存储标记,判断是否已经弹过弹窗 const hasShown = localStorage.getItem('a2hs_has_shown') if (!hasShown) { setOpen(true) } }, []) const handleClose = () => { setOpen(false) // 关闭时写入标记,后续不再弹出 localStorage.setItem('a2hs_has_shown', 'true') } return ( <div> <Modal aria-labelledby="transition-modal-title" aria-describedby="transition-modal-description" className={classes.modal} open={open} onClose={handleClose} closeAfterTransition BackdropComponent={Backdrop} BackdropProps={{ timeout: 500, }} > <div id="popup"> <h4 className="h4_addtohome"> Add Our App?<span className="popup-close-icon" onClick={handleClose}>×</span> </h4> <p className="p__addtohome"> Tap below to add an icon to your home screen for quick access! </p> {/* 根据设备类型渲染对应引导图 */} {deviceType === 'desktop' && <img src="https://i.sstatic.net/UEkeg.png" alt="桌面端弹窗展示" />} {deviceType === 'ios' && <img src="https://i.sstatic.net/6kcgG.png" alt="IOS端弹窗展示" />} {/* 安卓设备可以自行补充对应的引导图 */} </div> </Modal> </div> ) }
补充说明
- 如果需要定期重新弹出弹窗,可以在存储标记时加上时间戳,每次初始化时判断距离上次弹出的时间是否超过阈值,超过则重新展示
- 原代码里的关闭图标没有绑定点击事件,上面的代码已经补充了绑定逻辑,保证用户可以正常关闭弹窗
内容的提问来源于stack exchange,提问作者Pinky Promise
相关产品推荐
相关产品推荐

