翻译|使用教程|编辑:杨鹏连|2020-10-21 09:53:59.567|阅读 824 次
概述:本教程致力于将我们的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@ke049m.cn
文章转载自: