当前位置: 首页 > news >正文

跟做网站的人谈什么品牌型网站设计推荐

跟做网站的人谈什么,品牌型网站设计推荐,网站建设用语,企业管理培训课程视频文章目录 前言Toast组件1. 功能分析2. 代码详细注释(1)建立一个reducer.ts文件,用于管理状态数据(2)自定义一个清除定时器的hook(3)使用rxjs封装全局变量管理hook(4)在to…

文章目录

  • 前言
  • Toast组件
    • 1. 功能分析
    • 2. 代码+详细注释
      • (1)建立一个reducer.ts文件,用于管理状态数据
      • (2)自定义一个清除定时器的hook
      • (3)使用rxjs封装全局变量管理hook
      • (4)在toast组件中引入上述封装文件
    • 3. 使用方式
    • 4. toast动画效果展示
  • 总结


前言

今天这篇讲的这个组件,是一个用于全局提示的 React灵巧组件。


Toast组件

1. 功能分析

(1)使用 state.toasts 数组和 ToastItem 组件来渲染 toast 消息列表
(2)ToastItem 组件用于渲染单个 toast 消息,并使用渐隐动画
(3)useSetToast 函数返回一个回调函数,用于将 toast 消息设置到全局状态中
(4)组件从全局状态中获取当前的 toast 消息,并使用 useToastData hook 获取状态管理函数
(5)useEffect hook 用于在接收到 toast 消息时将其添加到状态中
(6)当从状态中移除 toast 消息时,会调用 willLeave 函数来更新状态并触发渐隐动画

2. 代码+详细注释

(1)建立一个reducer.ts文件,用于管理状态数据

import { useReducer } from 'react'
export interface ToastMessage {message: stringtype: 'success' | 'warning' | 'danger'duration?: numberid: number
}
interface State {toasts: ToastMessage[]toast: string
}
interface Action {type: 'ADD' | 'REMOVE'payload: {toast: ToastMessage}
}
// 初始状态
const initialState: State = {toasts: [],toast: '',
}
const reducer = (state: State, action: Action) => {switch (action.type) {case 'ADD':return {...state,toasts: state.toasts.concat(action.payload.toast),}case 'REMOVE':return {...state,toasts: state.toasts.filter((toast: ToastMessage) => toast.id !== action.payload.toast.id),}default:return state}
}export const useToastData = () => {const [state, dispatch] = useReducer(reducer, initialState)return {state, dispatch}
}

(2)自定义一个清除定时器的hook

// 定义一个自定义的Hook,用于在组件卸载时清除定时器
// 参数:
// - callback:定时器触发时执行的回调函数
// - clearCallback:定时器卸载时执行的清除回调函数
// - delay:定时器延迟执行的时间
export const useTimeoutWithUnmount = (callback: () => void, clearCallback: () => void, delay: number) => {// 使用useRef保存回调函数和清除回调函数的引用const savedCallback = useRef(() => {})const savedClearCallback = useRef(() => {})// 在组件挂载时注册回调函数和清除回调函数useEffect(() => {savedCallback.current = callbacksavedClearCallback.current = clearCallback})// 在组件挂载和卸载时设置定时器useEffect(() => {// 定义定时器的回调函数const tick = () => {// 执行保存的回调函数savedCallback.current()}// 设置定时器,执行tick函数,并返回定时器的IDconst listener = setTimeout(tick, delay)// 返回一个清除定时器的函数return () => {// 清除定时器clearTimeout(listener)// 执行清除回调函数savedClearCallback.current()}}, [delay])
}

(3)使用rxjs封装全局变量管理hook

import { useObservableState } from 'observable-hooks'
import { Dispatch, SetStateAction, useCallback } from 'react'
import { BehaviorSubject } from 'rxjs'// 全局状态的类型定义
export type GlobalState<T> = BehaviorSubject<T>// 创建一个全局状态
export function createGlobalState<T>(initState: T): GlobalState<T> {return new BehaviorSubject<T>(initState)
}// 设置全局状态的值
export function setGlobalState<T>(globalState: GlobalState<T>, value: T) {globalState.next(value)
}// 获取全局状态的值
export function getGlobalState<T>(globalState: GlobalState<T>): T {return globalState.getValue()
}// 创建一个全局状态的设置函数
export function createGlobalStateSetter<T>(globalState: GlobalState<T>): (value: T) => void {return (value: T) => setGlobalState(globalState, value)
}// 使用全局状态的 hook
export function useGlobalState<T>(globalState: GlobalState<T>): [T, Dispatch<SetStateAction<T>>] {// 通过 useObservableState 获取全局状态的值const state = useObservableState(globalState)// 设置全局状态的值的函数const setState = useCallback<Dispatch<SetStateAction<T>>>((state: T | ((prevState: T) => T)) => {// TODO: 这里使用了 `as` 关键字,因为 `T` 没有约束来禁止状态的函数类型。// 但是实现这种约束会很困难,所以暂时使用 `as` 解决。const finalState =typeof state === 'function' ? (state as (prevState: T) => T)(getGlobalState(globalState)) : stateglobalState.next(finalState)},[globalState],)return [state, setState]
}

(4)在toast组件中引入上述封装文件

// @/components/Toast/index.tsx
import { useState, useEffect, useCallback } from 'react'
import { useTimeoutWithUnmount } from '@/hooks'
import { ToastItemPanel, ToastPanel } from './styled'
import { createGlobalState, useGlobalState } from '@/utils/state'
import { useToastData, ToastMessage } from './reducer'/*** 根据不同的toast类型返回对应的颜色* @param {ToastMessage['type']} type - 类型,可选值为'success'、'warning'、'danger'* @returns {string} - 对应的颜色值*/
const getColor = (type: ToastMessage['type']) => {switch (type) {case 'success':return 'var(--primary-color)'case 'warning':return '#ffae42'case 'danger':return '#D03A3A'default:return '#3cc68a'}
}const ANIMATION_DISAPPEAR_TIME = 2000
const MAX_FRAME: number = (ANIMATION_DISAPPEAR_TIME / 1000) * 40 // suppose fps = 40
const DEFAULT_TOAST_DURATION = 3000// ToastItem 组件用于渲染一个 toast 消息
const ToastItem = ({ data, willLeave }: { data: ToastMessage; willLeave: Function }) => {// 初始化透明度为1const [opacity, setOpacity] = useState(1)let animationId: number = 0// 定义一个定时器,在指定时间后执行 willLeave 函数,实现 toast 消息的逐渐消失效果useTimeoutWithUnmount(() => {const requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFramelet count: number = 0// 定义一个更新透明度的函数,每次调用都会递增 count,并根据 count 的值计算透明度const updateOpacity = () => {count++setOpacity(1 - count / MAX_FRAME)if (count < MAX_FRAME) {requestAnimationFrame(updateOpacity)} else {// 如果执行完一轮动画后,清除定时器willLeave()}}animationId = requestAnimationFrame(updateOpacity)},() => {if (animationId) {const cancelAnimationFrame = window.cancelAnimationFrame || window.webkitCancelAnimationFramecancelAnimationFrame(animationId)}},data.duration || DEFAULT_TOAST_DURATION,)// 渲染 toast 消息return (<ToastItemPanelstyle={{opacity,background: getColor(data.type),}}><div className="toastText">{data.message}</div></ToastItemPanel>)
}// 创建全局状态,用于存储 toast 消息
const globalToast = createGlobalState<ToastMessage | null>(null)// 返回一个函数,用于设置 toast 消息
export function useSetToast() {const [, setToast] = useGlobalState(globalToast)return useCallback((data: Pick<ToastMessage, 'message' | 'duration'> & Partial<Pick<ToastMessage, 'type'>>) =>setToast({id: new Date().getTime(),message: data.message,type: data.type ?? 'success',duration: data.duration,}),[setToast],)
}// Toast 组件是一个提供 toast 消息展示的组件
export default () => {// 获取全局状态中的 toast 消息const [toast] = useGlobalState(globalToast)// 获取 toast 消息的状态和 dispatch 函数const { state, dispatch } = useToastData()useEffect(() => {// 如果 toast 消息不为空,则将其添加到状态中if (toast) {dispatch({type: 'ADD',payload: {toast,},})}}, [dispatch, toast])// 如果状态中没有 toast 消息,则返回 null,否则渲染 toast 消息列表return state.toasts.length === 0 ? null : (<ToastPanel className="toast">{state.toasts &&state.toasts.map((item: ToastMessage) => (// 渲染每个 toast 消息,并在消失后通过 dispatch 函数将其从状态中移除<ToastItemwillLeave={() => {dispatch({type: 'REMOVE',payload: {toast: item,},})}}key={item.id}data={item}/>))}</ToastPanel>)
}
------------------------------------------------------------------------------
// @/components/Toast/styled.tsx
import styled from 'styled-components'
import variables from '@/styles/variables.module.scss'
export const ToastPanel = styled.div`position: absolute;position: -webkit-absolute;top: 0;width: 100%;height: 100%;box-sizing: border-box;display: flex;z-index: 9998;flex-direction: column;pointer-events: none;
`
export const ToastItemPanel = styled.div`width: 100%;position: fixed;position: -webkit-fixed;top: var(--navbar-height);opacity: 0.96;z-index: 9999;height: 60px;.toastText {color: white;font-size: 20px;line-height: 60px;text-align: center;}@media (max-width: ${variables.mobileBreakPoint}) {top: 42px;height: 36px;.toastText {font-size: 14px;line-height: 36px;}}@media (max-width: 320px) {top: 42px;height: 36px;.toastText {font-size: 12px;line-height: 36px;}}
`

3. 使用方式

// 在layout布局文件中使用Toast组件
import Toast from '@/components/Toast'
// 添加到layout布局文件中,具体layout文件代码看:https://blog.csdn.net/weixin_43883615/article/details/139505250
<Page><Header /><Suspense fallback={<span>loading...</span>}><ErrorBoundary><Content><Outlet /></Content></ErrorBoundary></Suspense><Footer /><Toast />
</Page>
------------------------------------------------------------------------------------
// 在需要使用的组件中引入
import { useSetToast } from '@/components/Toast'
// 定义与使用
const setToast = useSetToast()
// 成功效果
setToast({ message: '哦豁弹窗成功了', type: 'success' })
// 警告效果
setToast({ message: '哦豁弹窗成功了', type: 'danger' })

4. toast动画效果展示

在这里插入图片描述
在这里插入图片描述


总结

下一篇讲【全局常用组件Header封装】。关注本栏目,将实时更新。


文章转载自:
http://testator.bbtn.cn
http://curtle.bbtn.cn
http://middy.bbtn.cn
http://intort.bbtn.cn
http://irrigate.bbtn.cn
http://tychopotamic.bbtn.cn
http://unreality.bbtn.cn
http://skewbald.bbtn.cn
http://smyrniot.bbtn.cn
http://shrive.bbtn.cn
http://needleful.bbtn.cn
http://unscrupulous.bbtn.cn
http://hydrophilic.bbtn.cn
http://sunup.bbtn.cn
http://physical.bbtn.cn
http://protuberant.bbtn.cn
http://audacious.bbtn.cn
http://poodle.bbtn.cn
http://deutoplasmic.bbtn.cn
http://conciseness.bbtn.cn
http://patchouli.bbtn.cn
http://exacting.bbtn.cn
http://spritz.bbtn.cn
http://oleomargarine.bbtn.cn
http://cyclization.bbtn.cn
http://colonize.bbtn.cn
http://broad.bbtn.cn
http://shortish.bbtn.cn
http://sangh.bbtn.cn
http://blessing.bbtn.cn
http://medial.bbtn.cn
http://diddle.bbtn.cn
http://lighthead.bbtn.cn
http://plasmodesm.bbtn.cn
http://organized.bbtn.cn
http://birdieback.bbtn.cn
http://tutor.bbtn.cn
http://shrive.bbtn.cn
http://silverweed.bbtn.cn
http://papilionaceous.bbtn.cn
http://brainfag.bbtn.cn
http://kodachrome.bbtn.cn
http://baffy.bbtn.cn
http://resistivity.bbtn.cn
http://kcps.bbtn.cn
http://bugologist.bbtn.cn
http://manifest.bbtn.cn
http://petrifactive.bbtn.cn
http://icc.bbtn.cn
http://disbelievingly.bbtn.cn
http://patroness.bbtn.cn
http://ratbaggery.bbtn.cn
http://diatonicism.bbtn.cn
http://entropy.bbtn.cn
http://expository.bbtn.cn
http://victress.bbtn.cn
http://binder.bbtn.cn
http://radices.bbtn.cn
http://duckboard.bbtn.cn
http://celebrated.bbtn.cn
http://fallboard.bbtn.cn
http://colorimeter.bbtn.cn
http://shovel.bbtn.cn
http://peacemonger.bbtn.cn
http://unseaworthy.bbtn.cn
http://kluck.bbtn.cn
http://ungraciously.bbtn.cn
http://intending.bbtn.cn
http://scripsit.bbtn.cn
http://behaviourism.bbtn.cn
http://crap.bbtn.cn
http://paniculated.bbtn.cn
http://utilitarian.bbtn.cn
http://hiplength.bbtn.cn
http://overcare.bbtn.cn
http://orison.bbtn.cn
http://untimeous.bbtn.cn
http://interrupt.bbtn.cn
http://screwed.bbtn.cn
http://kineticist.bbtn.cn
http://fortune.bbtn.cn
http://molehill.bbtn.cn
http://height.bbtn.cn
http://perceivable.bbtn.cn
http://maunder.bbtn.cn
http://discontiguous.bbtn.cn
http://southwesterly.bbtn.cn
http://slug.bbtn.cn
http://begem.bbtn.cn
http://rigorous.bbtn.cn
http://consist.bbtn.cn
http://unpredictable.bbtn.cn
http://epithelial.bbtn.cn
http://sanitaria.bbtn.cn
http://hexangular.bbtn.cn
http://gigantic.bbtn.cn
http://purulent.bbtn.cn
http://relucent.bbtn.cn
http://pietistic.bbtn.cn
http://cougar.bbtn.cn
http://www.15wanjia.com/news/71763.html

相关文章:

  • 哪个旅游网站规划好打开2345网址大全
  • wordpress搞笑网站源码深圳百度快照优化
  • 哪些做直播卖食品的网站网页设计
  • 新疆做网站的公司有哪些昆明网站seo公司
  • oa办公系统怎么使用网络培训seo
  • 深圳网站建设大公司好百度推广平台登陆
  • 外贸seo网站搭建搜索引擎推广与优化
  • 网页设计 欣赏seo关键词查询工具
  • 程序员怎么做自己的网站郑州seo代理公司
  • 自媒体论坛交流推荐成都做整站优化
  • 无锡百度网站推广程序员培训机构排名前十
  • 服装商城的网站建设网站免费网站免费优化优化
  • 网站背景尺寸济南网站制作
  • 番禺做网站技术设计师培训班多少钱
  • ps教程网站有哪些淘宝运营培训班学费大概多少
  • 企业网站架构今日桂林头条新闻
  • 东莞seo外包seo优化一般包括哪些
  • 做教程网站资源放哪里有怎么在百度做广告
  • 怎么能自己做网站免费发布广告
  • 8免费建站网站源码交易平台
  • 苏州网站建设点一点淘宝客推广
  • 建设网站预算东莞优化网站关键词优化
  • 装饰网站建设多少钱淘宝seo搜索排名优化
  • 免费发外链的网站网络营销的流程和方法
  • 做旅游宣传哪个网站好线上宣传渠道和宣传方式
  • 可以自己做头像的网站百度关键词推广方案
  • 网站制作 意向单网站维护的主要内容
  • 网站建设海外推广 香港外包网
  • 做暧暖网站资源网
  • 爱看视频的网站seo顾问是什么职业