今天介紹一個比較好用的react日期控件rc-calendar(貌似是某寶製作的react日期控件)
rc-calendar的github網址:https://github.com/react-component/calendar
rc-calendar的部分功能如下圖所示:
那麼,就讓我們一步步實現上圖中日期控件以及相關功能
第一步:安裝rc-calendar
在package.json中加入如下依賴,然後執行npm install
第二步:在頁面中加入rc-calendar依賴
1.創建文件calendar.jsx
2.加入rc-calendar組件依賴
var React=require('react');
var Link= require('react-router').Link;
var IndexLink=require('react-router').IndexLink;
var Calendar =require('rc-calendar');
var TimePickerPanel=require('rc-time-picker/lib/Panel');
var DatePicker=require('rc-calendar/lib/Picker');
var zhCN=require('rc-calendar/lib/locale/zh_CN');
import moment from 'moment';
require('moment/locale/zh-cn');
3.加入rc-calendar樣式依賴,也可以單獨把rc-calendar中的index.css提取出來,加在index.html中,方便調試 。
//require('rc-calendar/assets/index.css');
第三步:進行編碼
var React=require('react');
var PropTypes=require('react').PropTypes;
import Tree, { TreeNode } from 'rc-tree';
//require('rc-tree/assets/index.css');
import cssAnimation from 'css-animation';
var Link= require('react-router').Link;
var IndexLink=require('react-router').IndexLink;
const STYLE = `
.collapse {
overflow: hidden;
display: block;
}
.collapse-active {
transition: height 0.3s ease-out;
}
`;
function animate(node, show, done) {
let height = node.offsetHeight;
return cssAnimation(node, 'collapse', {
start() {
if (!show) {
node.style.height = `${node.offsetHeight}px`;
} else {
height = node.offsetHeight;
node.style.height = 0;
}
},
active() {
node.style.height = `${show ? height : 0}px`;
},
end() {
node.style.height = '';
done();
}
});
}
//動態樹動態創建節點方法
function createDynamicNode(treeData,eventKey){
treeData.forEach(function(item){
if(item.child!=null){
createDynamicNode(item.child,eventKey);
}else{
if(eventKey==item.key){
item.child=[
{title: '子節點1', key: '0-0-1-0',level:2},
{title: '子節點2', key: '0-0-1-1',level:2}
]
}
}
});
}
var myTree = React.createClass({
//設置默認數據類型
propTypes: {
keys: PropTypes.array
},
//設置默認屬性值
getDefaultProps() {
return {
keys: ['0-0']
};
},
getInitialState() {
const keys = this.props.keys;
return {
//defaultExpandedKeys: keys, //默認展開 keys節點
//defaultSelectedKeys: keys, //默認選中(高亮) keys節點
//defaultCheckedKeys: keys, //默認Checked keys節點
defaultExpandedKeys: [],
defaultSelectedKeys: [],
defaultCheckedKeys: [],
expandedKeys: [],
selectedKeys: [],
checkedKeys: [],
switchIt: true,
treeData:[
{title: 'dynamic 1', key: '0-0-0' ,level:1},
{title: 'dynamic 2', key: '0-0-1' ,level:1}
],
treeData2:[
{title: 'edit', key: '0-0-0' ,level:1,child:[
{title: '子節點1', key: '0-0-0-0',level:2,child:[
{title: '子子節點1', key: '0-0-0-0-1',level:3},
]},
{title: '子節點2', key: '0-0-0-1',level:2},
]},
{title: '父節點', key: '0-0-1',level:1,child:[
{title: '子節點1', key: '0-0-1-0',level:2},
{title: '子節點2', key: '0-0-1-1',level:2}
]}
]
};
},
onExpand(expandedKeys) {
console.log('onExpand', expandedKeys, arguments);
this.setState({expandedKeys:expandedKeys});
},
onSelect(selectedKeys, info) {
console.log('selected', selectedKeys, info);
this.setState({selectedKeys:selectedKeys});
this.selKey = info.node.props.eventKey;
},
onCheck(checkedKeys, info) {
this.setState({checkedKeys:checkedKeys});
console.log('onCheck', checkedKeys, info);
},
onEdit() { //用setTimeout異步阻塞線程,使onSelect先運行,得到當前選中的節點
setTimeout(() => {
console.log('current key: ', this.selKey);
alert(this.selKey);
}, 0);
},
onDel(e) {
if (!window.confirm('sure to delete?')) {
}else{
setTimeout(() => {
console.log('delete key: ', this.selKey);
}, 0);
}
e.stopPropagation();
},
onLoadData(treeNode) {
return new Promise((resolve) => {
if(treeNode.props.children!=null&&treeNode.props.children.length>0){
resolve();
}else{
setTimeout(() => {
let treeData=this.state.treeData;
//動態加載樹節點
createDynamicNode(treeData,treeNode.props.eventKey);
this.setState({ treeData });
resolve();
},500);
}
});
},
render() {
//先查出根節點
function findRoot(treeData) {
var nodeStr=treeData.map(function(node){
return (
<TreeNode title={node.title} key={node.key}>{findChild(node)}</TreeNode>
);
});
return nodeStr;
}
//循環遞歸展開樹
function findChild(node){
if(node!=null){
if(node.child!=null){
var str=node.child.map(function(n){
return(
<TreeNode title={n.title} key={n.key}>{findChild(n)}</TreeNode>
);
})
return str;
}
}
}
var dynamicNodeList=(
<TreeNode title="根節點" key="0-0">
{findRoot(this.state.treeData)}
</TreeNode>
);
var treeNodeList=(
<TreeNode title="根節點" key="0-0">
{findRoot(this.state.treeData2)}
</TreeNode>
);
const animation = {
enter(node, done) {
return animate(node, true, done);
},
leave(node, done) {
return animate(node, false, done);
},
appear(node, done) {
return animate(node, true, done);
}
};
const customLabel = (
<span className="cus-label">
<span>operations </span>
</span>
);
//defaultExpandAll 默認全部展開
//showline 顯示樹中的虛線
//checkable 提供複選框功能
//onExpand 樹展開後的回調 onSelect 樹選中後的回調 onCheck 樹選擇的回調
//onLoadData 動態加載樹
//openAnimation 展開節點時動畫函數
return (<div style={{ margin: '0 20px' }}>
<div>
選中的節點key值:{this.state.selectedKeys}<br/>
展開的節點key值:{this.state.expandedKeys}<br/>
check的節點key值:{this.state.checkedKeys}<br/>
</div>
<h2>基礎樹</h2>
<style dangerouslySetInnerHTML={{ __html: STYLE }}/>
<Tree
className="myCls" showLine checkable
defaultExpandedKeys={this.state.defaultExpandedKeys}
onExpand={this.onExpand}
defaultSelectedKeys={this.state.defaultSelectedKeys}
defaultCheckedKeys={this.state.defaultCheckedKeys}
onSelect={this.onSelect} onCheck={this.onCheck}
openAnimation={animation}
>
<TreeNode title="parent 1" key="0-0">
<TreeNode title={customLabel} key="0-0-0">
<TreeNode title="leaf" key="0-0-0-0" />
<TreeNode title="leaf" key="0-0-0-1" />
</TreeNode>
<TreeNode title="parent 1-1" key="0-0-1">
<TreeNode title="parent 1-1-0" key="0-0-1-0" />
<TreeNode title="parent 1-1-1" key="0-0-1-1" />
</TreeNode>
</TreeNode>
</Tree>
<h2>基礎樹2</h2>
<Tree
className="myCls" showLine checkable defaultExpandAll
defaultExpandedKeys={this.state.defaultExpandedKeys}
onExpand={this.onExpand}
defaultSelectedKeys={this.state.defaultSelectedKeys}
defaultCheckedKeys={this.state.defaultCheckedKeys}
onSelect={this.onSelect} onCheck={this.onCheck}
>
{treeNodeList}
</Tree>
<h2>動態樹</h2>
<Tree
className="myCls" showLine checkable
defaultExpandedKeys={this.state.defaultExpandedKeys}
onExpand={this.onExpand}
defaultSelectedKeys={this.state.defaultSelectedKeys}
defaultCheckedKeys={this.state.defaultCheckedKeys}
onSelect={this.onSelect} onCheck={this.onCheck}
loadData={this.onLoadData}
>
{dynamicNodeList}
</Tree>
</div>);
}
});
exports.Tree=myTree;