react 提示消息队列 (支持动态添加,删除,多实例化)
import React from 'react'
import PropTypes from 'prop-types' import AnimationOperateFeedbackInfo from '../AnimationOperateFeedbackInfo'
import OperateFeedbackInfo from '../OperateFeedbackInfo' import './index.less' const OPERATE_ARRAY_MAX_LENGTH = 5 export default function AssistantOperateFeedbackArea({
processingOperateList, failedOperateList, onClickCleanFailedOperateBtn, animationEndCallback,
}) {
const operateWrapStyle = {
width: '200px',
height: '28px',
color: '#fff',
} return (
<div className="assistant-operate-feedback-area-wrap">
{
processingOperateList.length > 0 && (
<div
className="operate-feedback-area"
style={{
// queueMaxLength + 1 省略区域高度
height: `${processingOperateList.length > OPERATE_ARRAY_MAX_LENGTH ? (OPERATE_ARRAY_MAX_LENGTH + 1) * 28 : processingOperateList.length * 28}px`,
}}
>
{
processingOperateList.slice(0, OPERATE_ARRAY_MAX_LENGTH).map((item) => {
return (
<AnimationOperateFeedbackInfo
operateId={item.operateId}
operate={item.operate}
operateType={item.state}
animationEndCallback={animationEndCallback}
style={operateWrapStyle}
key={item.operateId}
/>
)
})
}
{
processingOperateList.length > OPERATE_ARRAY_MAX_LENGTH && (
<div
style={operateWrapStyle}
className="ellipsis-operate-info"
>
... ...
</div>
)
}
</div>
)
}
{
failedOperateList.length > 0 && (
<div
className="operate-feedback-area"
style={{
// queueMaxLength + 1 省略区域高度
height: `${failedOperateList.length > OPERATE_ARRAY_MAX_LENGTH ? (OPERATE_ARRAY_MAX_LENGTH + 1) * 28 : failedOperateList.length * 28}px`,
}}
>
{
failedOperateList.slice(0, OPERATE_ARRAY_MAX_LENGTH).map((item) => {
return (
<div className="operate-feedback-info-wrap">
<OperateFeedbackInfo
operate={item.operate}
style={operateWrapStyle}
iconRotate={false}
iconPath={require('~/shared/assets/image/red-white-warn-icon-60-60.png')}
/>
</div>
)
})
}
<div
className="clean-failed-feedback-info-btn"
onClick={onClickCleanFailedOperateBtn}
tabIndex={0}
role="button"
>
清除所有异常
</div>
{
failedOperateList.length > OPERATE_ARRAY_MAX_LENGTH && (
<div
style={operateWrapStyle}
className="ellipsis-operate-info"
>
... ...
</div>
)
}
</div>
)
}
{
processingOperateList.length === 0 && failedOperateList.length === 0 && (
<div className="no-feedback-info-tip">
暂无对教师端操作
</div>
)
}
</div>
)
} AssistantOperateFeedbackArea.propTypes = {
processingOperateList: PropTypes.array,
failedOperateList: PropTypes.array,
onClickCleanFailedOperateBtn: PropTypes.func,
animationEndCallback: PropTypes.func,
} AssistantOperateFeedbackArea.defaultProps = {
processingOperateList: [],
failedOperateList: [],
animationEndCallback: () => {},
onClickCleanFailedOperateBtn: () => {},
}
import React, { useRef, useLayoutEffect } from 'react'
import PropTypes from 'prop-types'
import CX from 'classnames'
import './index.less'
export default function OperateFeedbackInfo({
operate, iconPath, style, iconRotate, resetAnimation,
}) {
const imgRef = useRef(null)
useLayoutEffect(() => {
if (resetAnimation === true) {
const imgElem = imgRef.current
imgElem.className = ''
// 触发一次重绘 同步所有旋转的icon动画
imgElem.height = imgElem.offsetHeight
imgElem.className = 'operate-icon-rotate'
}
})
return (
<div
className="operate-feedback-Info"
style={style}
>
<div className="operate-feedback-content">{operate}</div>
<div className="operate-feedback-state-icon">
<img
className={CX({
'operate-icon-rotate': iconRotate,
})}
src={iconPath}
alt=""
ref={imgRef}
/>
</div>
</div>
)
}
OperateFeedbackInfo.propTypes = {
operate: PropTypes.string.isRequired,
iconPath: PropTypes.string.isRequired,
iconRotate: PropTypes.bool,
resetAnimation: PropTypes.bool,
style: PropTypes.object,
}
OperateFeedbackInfo.defaultProps = {
style: {},
resetAnimation: false,
iconRotate: false,
}
import React from 'react'
import PropTypes from 'prop-types' import CX from 'classnames'
import OperateFeedbackInfo from '../OperateFeedbackInfo' import './index.less' export default function AnimationOperateFeedbackInfo({
operateId, operate, operateType, animationEndCallback, style,
}) {
return (
<div
className={CX({
'animation-operate-feedback-info-wrap': true,
'animation-operate-feedback-processing-state': operateType === 'processing',
'animation-operate-feedback-success-state': operateType === 'success',
})}
onAnimationEnd={() => {
if (operateType === 'success') {
animationEndCallback(operateId)
}
}}
>
<OperateFeedbackInfo
resetAnimation={operateType !== 'success'}
operate={operate}
style={style}
iconRotate={operateType !== 'success'}
iconPath={operateType === 'success' ? require('~/shared/assets/image/icon-success-green-white-100-100.png') : require('~/shared/assets/image/processing-icon.svg')}
/>
</div>
)
} AnimationOperateFeedbackInfo.propTypes = {
operateId: PropTypes.string,
operate: PropTypes.string,
operateType: PropTypes.string,
animationEndCallback: PropTypes.func,
style: PropTypes.object,
} AnimationOperateFeedbackInfo.defaultProps = {
operateId: '',
operate: '',
operateType: '',
animationEndCallback: () => {},
style: {},
}
以上是所有UI部分(包括交互):效果如下:

下面是hoc逻辑部分:
import React, { Component } from 'react'
import {
observable,
action,
} from 'mobx'
import {
observer,
} from 'mobx-react'
import uid from 'uuid'
import { AssistantOperateFeedbackArea } from '@dby-h5-clients/pc-1vn-components'
import { Rnd } from 'react-rnd'
import _ from 'lodash'
const operateListClump = observable.object({
failedOperateList: [],
processingOperateList: [],
})
class OperateState {
@action
constructor(operate = '') {
this.operateId = uid()
this.operate = operate
operateListClump.processingOperateList.push({ operate, operateId: this.operateId, state: 'processing' })
}
operateId
operate
@action
success(operate = '') {
const operateIndex = _.findIndex(operateListClump.processingOperateList, { operateId: this.operateId })
operateListClump.processingOperateList[operateIndex] = { operate: operate || this.operate, operateId: this.operateId, state: 'success' }
}
@action
failed(operate = '') {
operateListClump.failedOperateList.push({ operate: operate || this.operate, operateId: this.operateId, state: 'failed' })
_.remove(operateListClump.processingOperateList, { operateId: this.operateId })
}
}
@observer
class AssistantOperateList extends Component {
static addOperate = action((operate) => {
return new OperateState(operate)
})
@action
removeSuccessOperate = (operateId) => {
_.remove(operateListClump.processingOperateList, { operateId })
}
@action
handleCleanAllFailedFeedbackInfo = () => {
operateListClump.failedOperateList = []
}
render() {
return (
<Rnd
bounds=".main-space-wrap"
dragHandleClassName="assistant-operate-feedback-area-wrap"
lockAspectRatio={16 / 9}
enableResizing={{
top: false,
right: false,
bottom: false,
left: false,
topRight: false,
bottomRight: false,
bottomLeft: false,
topLeft: false,
}}
default={{
x: 30,
y: 30,
}}
>
<AssistantOperateFeedbackArea
failedOperateList={operateListClump.failedOperateList.toJSON()}
processingOperateList={operateListClump.processingOperateList.toJSON()}
animationEndCallback={this.removeSuccessOperate}
onClickCleanFailedOperateBtn={this.handleCleanAllFailedFeedbackInfo}
/>
</Rnd>
)
}
}
export default AssistantOperateList
使用说明:
在其它组件中导入:
import AssistantOperateList from '../AssistantOperateList'
const msg = AssistantOperateList.addOperate('协助开启答题器')
msg.success()
msg.failed()
react 提示消息队列 (支持动态添加,删除,多实例化)的更多相关文章
- easyui 扩展layout的方法,支持动态添加删除块
$.extend($.fn.layout.methods, { remove: function(jq, region){ return jq.each(function(){ var panel = ...
- Lua中如何实现类似gdb的断点调试—09支持动态添加和删除断点
前面已经支持了几种不同的方式添加断点,但是必须事先在代码中添加断点,在使用上不是那么灵活方便.本文将支持动态增删断点,只需要开一开始引入调试库即可,后续可以在调试过程中动态的添加和删除断点.事不宜迟, ...
- 编辑 Ext 表格(一)——— 动态添加删除行列
一.动态增删行 在 ext 表格中,动态添加行主要和表格绑定的 store 有关, 通过对 store 数据集进行添加或删除,就能实现表格行的动态添加删除. (1) 动态添加表格的行 gridS ...
- 用Javascript动态添加删除HTML元素实例 (转载)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- js实现网页收藏功能,动态添加删除网址
<html> <head> <title> 动态添加删除网址 </title> <meta charset="utf-8"&g ...
- jquery动态添加删除div--事件绑定,对象克隆
我想做一个可以动态添加删除div的功能.中间遇到一个问题,最后在manong123.com开发文摘 版主的热心帮助下解答了(答案在最后) 使用到的jquery方法和思想就是:事件的绑定和销毁(unbi ...
- jQuery动态添加删除CSS样式
jQuery框架提供了两个CSS样式操作方法,一个是追加样式addClass,一个是移除样式removeClass,下面通过一个小例子讲解用法. jQuery动态追加移除CSS样式 <!DOCT ...
- JS动态添加删除html
本功能要求是页面传一个List 集合给后台而且页面可以动态添加删除html代码需求如下: 下面是jsp页面代码 <%@ page language="java" pageEn ...
- C#控制IIS动态添加删除网站
我的目的是在Winform程序里面,可以直接启动一个HTTP服务端,给下游客户连接使用. 查找相关技术,有两种方法: 1.使用C#动态添加网站应用到IIS中,借用IIS的管理能力来提供HTTP接口.本 ...
随机推荐
- flask 设置访问地址 和 访问端口
app.run() 四个参数 host:主机,可设置为本地或其他IP port:端口,是run()启动服务的时候指定的运行端口, debug:调试,如果需要进入调试模式,可以将这个选项设置成True ...
- spring线程池的同步和异步(1)
spring线程池(同步.异步) 一.spring异步线程池类图 二.简单介绍 2.1. TaskExecutor---Spring异步线程池的接口类,其实质是java.util.concurrent ...
- ntpd服务
yum -y install ntp 服务器端 [root@ip-172-31-6-148~]# vim /etc/ntp.conf ...# Use public servers from thep ...
- Remix 搭建与简单使用,并支持外部访问
Remix 搭建与简单使用,并支持外部访问 转 https://blog.csdn.net/linshenyuan1213/article/details/83444911 remix是基于浏览器的在 ...
- Leetcode: Capacity To Ship Packages Within D Days
A conveyor belt has packages that must be shipped from one port to another within D days. The i-th p ...
- Ajax serialize()提交form表单不能上传file类型
前台form表单的提交方式有很多种,例如: 1. form表单submit直接提交的方法 2. Ajax提交的方法 3. jquery提交的方法 4. 原生js提交的方法 每一种方法都有它的优势和不足 ...
- 使用SoapUI发送Post请求
https://www.cnblogs.com/xiaowangzi1110/p/8544264.html 使用SoapUI发送Post请求 SoapUI作为一个开源的工具,其具备强大的功能.易用的界 ...
- 算法习题---5.9数据库(Uva1592)
一:题目 对数据库中数据进行检测,是否出现数据冗余现象.即是否某一列出现两个及以上数据重复 如上图中,第二列中第2,3行数据重复,所以我们判断为数据冗余.因为他可以分解为下面两张表 (一)样例输入 H ...
- hppts的理解
参考: https://www.ruanyifeng.com/blog/2014/02/ssl_tls.html
- 123457123456#4#----com.MC.mathGame246----前拼后广--数学Q版训练Game-mc4444
com.MC.mathGame246----前拼后广--数学Q版训练Game-mc