翻译|使用教程|编辑:杨鹏连|2020-10-21 09:53:59.567|阅读 717 次
概述:本教程致力于将我们的Web应用程序组件与不同的客户端框架进行集成,将DHTMLX Scheduler与流行的基于React JS组件的库一起使用的新分步指南。
# 慧都年终大促·界面/图表报表/文档/IDE等千款热门软控件火热促销中 >>
dhtmlxScheduler是一个类似于Google日历的JavaScript日程安排控件,日历事件通过Ajax动态加载,支持通过拖放功能调整事件日期和时间。事件可以按天,周,月三个种视图显示。
本文介绍了dhtmlxScheduler v5.3各小版本更新内容集合,请查看文章内容了解详细信息。
我们继续进行一系列教程,致力于将我们的Web应用程序组件与不同的客户端框架进行集成。查阅我们有关将DHTMLX Scheduler与流行的基于React JS组件的库一起使用的新分步指南。
在这里,您将学习如何:
如何开始
我们的第一步是初始化应用程序结构。为此,我们将使用创建React应用程序工具。您可以在本文中找到有关它的其他信息。
要创建一个应用程序,请运行以下命令:
npx create-react-app scheduler-react然后,我们进入app文件夹并使用以下命令运行该应用程序:
cd scheduler-react yarn start (if you use yarn) npm start (if you use npm)现在我们的应用程序应该从http:// localhost:3000 /开始
yarn add dhtmlx-scheduler (for yarn)
or
npm install dhtmlx-scheduler (for npm)
然后,创建src / components / Scheduler文件夹。在这里,我们将为DHTMLX Scheduler添加一个React Component包装器。
创建Scheduler.js文件并打开它:
{{ src/components/Scheduler/Scheduler.js }}
import React, { Component } from 'react';
import 'dhtmlx-scheduler';
import 'dhtmlx-scheduler/codebase/dhtmlxscheduler_material.css';
const scheduler = window.scheduler;
export default class Scheduler extends Component {
componentDidMount() {
scheduler.skin = 'material';
scheduler.config.header = [
'day',
'week',
'month',
'date',
'prev',
'today',
'next'
];
const { events } = this.props;
scheduler.init(this.schedulerContainer, new Date(2020, 5, 10));
scheduler.clearAll();
scheduler.parse(events);
}
render() {
return (
<div
ref={ (input) => { this.schedulerContainer = input } }
style={ { width: '100%', height: '100%' } }
></div>
);
}
}
现在创建Scheduler.css文件并为scheduler-container添加样式:
{{ src/components/Scheduler/Scheduler.css }}
.scheduler-container {
height: 100vh;
width: 100vw;
}
最后,创建具有以下内容的index.js文件:
{{ src/components/Scheduler/index.js }}
import Scheduler from './Scheduler';
import './Scheduler.css';
export default Scheduler;
由于DHTMLX Scheduler是位于ReactJS世界之外的常规JS库,因此我们创建了包装器组件。装入组件后,我们将初始化DHTMLX Scheduler并将其附加到DOM。我们还可以使用通过props传递的数据来填充它。
请注意,由于DHTMLX Scheduler的免费版本没有析构函数,因此我们没有定义componentWillUnmount。这也意味着,如果我们在某个时候从React中删除了一个组件,则DHTMLX Scheduler的实例将保留在内存中,并在下次再次安装该组件时再次使用。
现在,将Scheduler添加到我们的App组件中。请注意,我们对此示例使用硬编码数据:
{{ src/App.js }} import React, { Component } from 'react'; import Scheduler from './components/Scheduler'; import './App.css'; const data = [ { start_date:'2020-06-10 6:00', end_date:'2020-06-10 8:00', text:'Event 1', id: 1 }, { start_date:'2020-06-13 10:00', end_date:'2020-06-13 18:00', text:'Event 2', id: 2 } ]; class App extends Component { render() { return ( <div> <div className='scheduler-container'> <Scheduler events={data}/> </div> </div> ); } } export default App;如果我们现在运行该应用程序,我们应该在页面上看到一个带有初始事件的简单事件日历:
yarn start or npm start
配置React Scheduler组件
让我们在React js事件日历中添加一些自定义功能。假设我们需要添加一个带有复选框的工具栏,该复选框将负责在小时刻度上切换时间格式。
我们可以使用hour_date配置和hour_scale模板更改时间格式。之后,我们需要使用渲染器以新格式重新绘制视图。让我们尝试在React中实现它。首先,让我们转到Scheduler组件,并为视图配置实现几个预设。
打开Scheduler.js,向其添加以下代码:
{{ src/components/Scheduler/Scheduler.js }} componentDidMount() { scheduler.skin = 'material'; scheduler.config.header = [ 'day', 'week', 'month', 'date', 'prev', 'today', 'next' ]; scheduler.config.hour_date = '%g:%i %A'; scheduler.xy.scale_width = 70; const { events } = this.props; scheduler.init(this.schedulerContainer, new Date(2020, 5, 10)); scheduler.clearAll(); scheduler.parse(events); } shouldComponentUpdate(nextProps) { return this.props.timeFormatState !== nextProps.timeFormatState; } componentDidUpdate() { scheduler.render(); } setTimeFormat(state) { scheduler.config.hour_date = state ? '%H:%i' : '%g:%i %A'; scheduler.templates.hour_scale = scheduler.date.date_to_str(scheduler.config.hour_date); }在这里,我们添加了componentDidUpdate处理程序(将在更新时重新绘制视图)和shouldComponentUpdate处理程序,在其中将确定是否需要更新视图。
{{ src/components/Scheduler/Scheduler.js }} render() { const { timeFormatState } = this.props; this.setTimeFormat(timeFormatState); return ( <div ref={ (input) => { this.schedulerContainer = input } } style={ { width: '100%', height: '100%' } } ></div> ); }现在,调度程序将以24小时格式显示时间。当hour_date属性和hour_scale模板更改时,我们需要调用视图的更新。
让我们添加用于更改时间格式的UI。我们将使用一个简单的工具栏和切换器。
创建工具栏组件:
{{ src/components/Toolbar/index.js }} import Toolbar from './Toolbar'; import './Toolbar.css'; export default Toolbar;
{{ src/components/Toolbar/Toolbar.js }} import React, { Component } from 'react'; export default class Toolbar extends Component { handleTimeFormatStateChange = (e) => { if (this.props.onTimeFormatStateChange) { this.props.onTimeFormatStateChange(e.target.checked) } } render() { return ( <div className='time-format-section'> <label className='time-format-chkbx'> Time format: <input type='checkbox' checked={ this.props.timeFormatState } onChange={ this.handleTimeFormatStateChange } /> <div className='chkbx-text'></div> </label> </div> ); } }
{{ src/components/Toolbar/Toolbar.css }} .tool-bar { background: #ededed; height: 40px; line-height: 14px; padding: 5px 10px; text-align: center; padding-left: 60px; } .time-format-chkbx { display: inline-flex; padding-top: 10px; font-family: Roboto,Arial; user-select: none; font-weight: 500; font-size: 20px; color: rgba(0,0,0,.75); } .time-format-chkbx input { position: absolute; z-index: -1; opacity: 0; margin: 10px 0 0 20px; } .chkbx-text { position: relative; cursor: pointer; user-select: none; font-weight: 800; font-size: 20px; line-height: 30px; font-family: Roboto,Arial; margin-left: 10px; } .chkbx-text:before { content: '12h'; text-align: right; padding: 0 10px; position: absolute; top: -8px; left: 0; width: 60px; height: 30px; border-radius: 15px; background: #CDD1DA; box-shadow: inset 0 2px 3px rgba(0,0,0,.2); transition: .2s; } .chkbx-text:after { content: ''; position: absolute; top: -6px; left: 2px; width: 25px; height: 25px; border-radius: 15px; background: #FFF; box-shadow: 0 2px 5px rgba(0,0,0,.3); transition: .2s; } .time-format-chkbx input:checked + .chkbx-text:before { content: '24h'; color: white; text-align: left; background: #0288d1; } .time-format-chkbx input:checked + .chkbx-text:after { left: 53px; } .time-format-chkbx input:focus + .chkbx-text:before { box-shadow: inset 0 2px 3px rgba(0,0,0,.2), 0 0 0 3px rgba(2,136,209,.7); }并更新调度程序容器的高度:
{{ src/components/Scheduler/Scheduler.css }} .scheduler-container { height: calc(100vh - 50px); width: 100vw; }在这里,我们添加了用于更改时间格式的复选框,并为父组件提供了onTimeFormatStateChange处理程序。现在,您需要将工具栏添加到App组件中:
{{ src/App.js }} import Toolbar from './components/Toolbar';以及用于更改事件的处理程序:
{{ src/App.js }} state = { currentTimeFormatState: true }; handleTimeFormatStateChange = (state) => { this.setState({ currentTimeFormatState: state }); }JSX:
{{ src/App.js }} render() { const { currentTimeFormatState } = this.state; return ( <div> <div className="tool-bar"> <Toolbar timeFormatState={currentTimeFormatState} onTimeFormatStateChange={this.handleTimeFormatStateChange} /> </div> <div className='scheduler-container'> <Scheduler events={data} timeFormatState={currentTimeFormatState} /> </div> </div> ); }因此,每次用户更改时间格式时,我们就有机会将更新后的状态传递给我们的React Scheduler:
现在,我们将展示如何捕获日历视图更改,然后将其传递到应用程序中的某处。
我们将使用dhtmlxScheduler事件捕获Scheduler的更改。
让我们看看如何在实践中做到这一点。打开src / components / Scheduler / Scheduler.js并添加以下方法:
{{ src/components/Scheduler/Scheduler.js }} initSchedulerEvents() { if (scheduler._$initialized) { return; } const onDataUpdated = this.props.onDataUpdated; scheduler.attachEvent('onEventAdded', (id, ev) => { if (onDataUpdated) { onDataUpdated('create', ev, id); } }); scheduler.attachEvent('onEventChanged', (id, ev) => { if (onDataUpdated) { onDataUpdated('update', ev, id); } }); scheduler.attachEvent('onEventDeleted', (id, ev) => { if (onDataUpdated) { onDataUpdated('delete', ev, id); } }); scheduler._$initialized = true; } componentDidMount() { scheduler.skin = 'material'; scheduler.config.header = [ 'day', 'week', 'month', 'date', 'prev', 'today', 'next' ]; scheduler.config.hour_date = '%g:%i %A'; scheduler.xy.scale_width = 70; this.initSchedulerEvents(); const { events } = this.props; scheduler.init(this.schedulerContainer, new Date(2020, 5, 10)); scheduler.clearAll(); scheduler.parse(events); }我们使用调度程序的全局实例,并且由于可以多次挂载它,因此需要确保仅添加一次事件侦听器。
为此,我们使用一个自定义的“ scheduler ._ $ initialized”标志。首次初始化调度程序时,未定义此标志,因此我们添加了事件侦听器并将此标志设置为`true`。这样,我们确保不再将事件侦听器附加到同一Scheduler实例。
这样,我们就可以捕获在Scheduler中所做的所有更改并将其发送到父组件。
我们需要捕获事件,为事件创建消息,并将这些消息置于本地状态。为此,请更新App组件:
{{ src/App.js }} state = { currentTimeFormatState: true, messages: [] }; addMessage(message) { const maxLogLength = 5; const newMessage = { message }; const messages = [ newMessage, ...this.state.messages ]; if (messages.length > maxLogLength) { messages.length = maxLogLength; } this.setState({ messages }); } logDataUpdate = (action, ev, id) => { const text = ev && ev.text ? ` (${ev.text})` : ''; const message = `event ${action}: ${id} ${text}`; this.addMessage(message); }之后,创建一个组件,将在页面上显示以下消息:
{{ src/components/MessageArea/MessageArea.js }} import React, { Component } from 'react'; export default class MessageArea extends Component { render() { const messages = this.props.messages.map(({ message }) => { return <li key={ Math.random() }>{message}</li> }); return ( <div className="message-area"> <h3>Messages:</h3> <ul> { messages } </ul> </div> ); } } MessageArea.defaultProps = { messages: [] };
{{ src/components/MessageArea/index.js }} import MessageArea from './MessageArea'; import './MessageArea.css'; export default MessageArea;添加样式:
{{ src/components/MessageArea/MessageArea.css }} .message-area { background: #ebebeb; height: 200px; overflow: auto; padding: 10px; box-sizing:border-box; } .message-area ul{ margin: 0; padding: 0; list-style: none; } .message-area li:before { content: "\003e"; padding-right: 10px; }并更新调度程序容器的高度:
{{ src/components/Scheduler/Scheduler.css }} .scheduler-container { height: calc(100vh - 50px - 200px); width: 100vw; }最后,将此组件连接到App:
{{ src/App.js }} import MessageArea from './components/MessageArea';JSX:
render() { const { currentTimeFormatState, messages } = this.state; return ( <div> <div className="tool-bar"> <Toolbar timeFormatState={currentTimeFormatState} onTimeFormatStateChange={this.handleTimeFormatStateChange} /> </div> <div className='scheduler-container'> <Scheduler events={data} timeFormatState={currentTimeFormatState} onDataUpdated={this.logDataUpdate} /> </div> <MessageArea messages={messages} /> </div> ); }因此,现在每次用户更改日历事件时,处理程序都会调用App组件并更新MessageArea,后者在页面上打印有关用户操作的信息。
如果运行该应用程序,我们将看到以下结果:
我们希望我们的教程对您的项目有用。如果您遇到任何困难,请随时在下面的评论中向我们发送您的问题。
本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@pclwef.cn
文章转载自: