прелюдия
- Справочник по стилю API Ant DesignГлобальная подсказка сообщения
текст
анализ спроса
- Тосты не нужно отображать вместе со страницей, они вызываются всякий раз, когда это необходимо.
- Toast — это легкий компонент подсказок, его подсказка не прерывает операции пользователя и автоматически закрывается после определенного периода подсказки.
- Toast должен предоставлять несколько разных типов сообщений для разных сценариев использования.
- Методы всплывающих сообщений должны быть достаточно краткими, чтобы избежать ненужной избыточности кода.
окончательный эффект:
пример вызова
Toast.info('普通提示')
Toast.success('成功提示', 3000)
Toast.warning('警告提示', 1000)
Toast.error('错误提示', 2000, () => {
Toast.info('哈哈')
})
const hideLoading = Toast.loading('加载中...', 0, () => {
Toast.success('加载完成')
})
setTimeout(hideLoading, 2000)
Реализация компонента
Компоненты тоста можно разделить на три части, а именно:
- note.js: уведомление. Компонент без сохранения состояния отвечает только за отрисовку компонента, соответствующего информации подсказки в соответствии с параметрами, переданными родительским компонентом, то есть окном подсказки, которое в конечном итоге видит пользователь.
- уведомление.js: Уведомление. Контейнер компонента «Уведомление» используется для сохранения компонента «Уведомление», существующего на странице, и предоставляет методы добавления и удаления компонента «Уведомление».
- toast.js: управляет окончательным открытым интерфейсом и вызывает метод add компонента Notification в соответствии с информацией, переданной внешним миром, чтобы добавить на страницу информационный компонент подсказки.
Структура каталогов проекта выглядит следующим образом:
├── toast
│ ├── icons.js
│ ├── index.js
│ ├── notice.js
│ ├── notification.js
│ ├── toast.css
│ ├── toast.js
Для простоты понимания реализация начинается с внешней части тоста.
toast.js
Поскольку на странице нет элемента, связанного с компонентом Toast, чтобы вставить информацию подсказки, то есть компонент «Уведомление», на страницу необходимо сначала вставить компонент «Уведомление-контейнер» компонента «Уведомление» на страницу. Определите здесь функцию createNotification для отображения компонента Notification на странице и сохраните функции addNotice и destroy.
function createNotification() {
const div = document.createElement('div')
document.body.appendChild(div)
const notification = ReactDOM.render(<Notification />, div)
return {
addNotice(notice) {
return notification.addNotice(notice)
},
destroy() {
ReactDOM.unmountComponentAtNode(div)
document.body.removeChild(div)
}
}
}
Затем определите глобальную переменную уведомления для хранения объекта, возвращаемого createNotification. И определите внешние функции, которые передают параметры компоненту уведомлений при вызове этих функций. Поскольку на странице должен существовать только один компонент уведомления, вам нужно только судить о том, существует ли текущий объект уведомления каждый раз, когда вызывается функция, и нет необходимости создавать его повторно.
let notification
const notice = (type, content, duration = 2000, onClose) => {
if (!notification) notification = createNotification()
return notification.addNotice({ type, content, duration, onClose })
}
export default {
info(content, duration, onClose) {
return notice('info', content, duration, onClose)
},
success(content, duration, onClose) {
return notice('success', content, duration, onClose)
},
warning(content, duration, onClose) {
return notice('warning', content, duration, onClose)
},
error(content, duration, onClose) {
return notice('error', content, duration, onClose)
},
loading(content, duration = 0, onClose) {
return notice('loading', content, duration, onClose)
}
}
notification.js
Итак, внешняя работа завершена, и теперь необходимо завершить внутреннюю реализацию компонента Notification. Во-первых, в атрибуте состояния компонента Notification есть атрибут notes, который используется для сохранения информации о Notification, существующей на текущей странице. А компонент Notification имеет два метода, addNotice и removeNotice, которые используются для добавления и удаления информации извещения (далее сокращенно извещение) в извещения.
При добавлении уведомления необходимо использовать метод getNoticeKey, чтобы добавить к уведомлению уникальное значение ключа, а затем добавить его к уведомлениям. И согласно длительности, предоставленной параметром, установить таймер на автоматическое закрытие по истечении времени.Здесь оговорено, что если значение длительности меньше или равно 0, то сообщение будет не закрываться автоматически, а всегда будет отображаться. Последний метод возвращает вызывающему методу метод, удаляющий собственное уведомление, чтобы он мог немедленно отклонить уведомление по мере необходимости.
При вызове метода removeNotice уведомления будут проходиться в соответствии со значением переданного ключа, и если результат будет найден, сработает его callback-функция и она будет удалена из уведомлений.
Наконец, он проходит через массив Notices и передает свойство Notice компоненту Notice для завершения рендеринга, где rendered-guout используется для реализации входящей анимации компонента.
(Примечание. Что касается проблемы с отображением, когда на странице одновременно отображается несколько подсказок, схема, принятая в этой статье, напрямую заменяет предыдущую подсказку последней подсказкой, поэтому уведомление добавляется в код и напрямую записывается как уведомления[ 0] = уведомление вместо уведомлений .push(уведомление), если вы хотите получить эффект сосуществования нескольких подсказок на странице, вы можете изменить его самостоятельно.)
class Notification extends Component {
constructor() {
super()
this.transitionTime = 300
this.state = { notices: [] }
this.removeNotice = this.removeNotice.bind(this)
}
getNoticeKey() {
const { notices } = this.state
return `notice-${new Date().getTime()}-${notices.length}`
}
addNotice(notice) {
const { notices } = this.state
notice.key = this.getNoticeKey()
if (notices.every(item => item.key !== notice.key)) {
notices[0] = notice
this.setState({ notices })
if (notice.duration > 0) {
setTimeout(() => {
this.removeNotice(notice.key)
}, notice.duration)
}
}
return () => { this.removeNotice(notice.key) }
}
removeNotice(key) {
this.setState(previousState => ({
notices: previousState.notices.filter((notice) => {
if (notice.key === key) {
if (notice.onClose) notice.onClose()
return false
}
return true
})
}))
}
render() {
const { notices } = this.state
return (
<TransitionGroup className="toast-notification">
{
notices.map(notice => (
<CSSTransition
key={notice.key}
classNames="toast-notice-wrapper notice"
timeout={this.transitionTime}
>
<Notice {...notice} />
</CSSTransition>
))
}
</TransitionGroup>
)
}
}
notice.js
Последний оставшийся компонент уведомления очень прост, вам нужно только вывести окончательный контент в соответствии с информацией, переданной компонентом уведомления. Вы можете играть со своим собственным стилем дизайна.
class Notice extends Component {
render() {
const icons = {
info: 'icon-info-circle-fill',
success: 'icon-check-circle-fill',
warning: 'icon-warning-circle-fill',
error: 'icon-close-circle-fill',
loading: 'icon-loading'
}
const { type, content } = this.props
return (
<div className={`toast-notice ${type}`}>
<svg className="icon" aria-hidden="true">
<use xlinkHref={`#${icons[type]}`} />
</svg>
<span>{content}</span>
</div>
)
}
}
Обновлено 18 августа 2005 г.
- Настройте схему отображения нескольких подсказок на странице: разрешите одновременное существование нескольких подсказок на странице;
- Исправлена проблема, из-за которой метод удаления подсказки, возвращаемый при добавлении подсказки, на самом деле не вступал в силу;
- Оптимизируйте стили компонентов и эффекты перехода.
Примечание. Основные изменения касаются методов addNotice и removeNotice в файле уведомления.js. Код в исходном тексте не был изменен, пожалуйста, обратитесь к измененному коду.Исходный код проекта.