maplemei 45cbfe8f1d v1.0.1
1. [新增]物理分页配置
2. [新增]自定义搜索模式(远程搜索)
3. [新增]下拉选高度配置
4. [修改]调整布局为flex布局
5. [修改]展开下拉选时, 自动聚焦搜索框
2019-09-22 14:15:46 +08:00

156 lines
4.2 KiB
JavaScript

import { h, Component, render } from '@/components/preact'
import { checkUserAgent } from '@/components/common/util'
//渲染类
import Tips from './tips';
import Label from './label';
import General from './model/general';
/**
* 框架渲染类, 渲染基础的外边框 + 属性变化监听
*/
class Framework extends Component{
constructor(options){
super(options);
//初始化多选数据
this.reset();
//回传子组件
this.props.onRef(this);
this.bodyView = null;
}
reset(){
let selected = this.props.prop.selected;
this.value(this.props.initValue ? this.props.initValue : this.props.data.filter(item => item[selected]), false);
this.resetDate(this.props.data);
}
resetDate(data = []){
this.setState({ data });
}
value(sels, show){
let data = this.props.data;
let value = this.props.prop.value;
let direction = this.props.direction;
this.setState({
sels: sels.map(sel => typeof sel === 'object' ? sel[value] : sel).map(val => data.find(item => item[value] == val)).filter(a => a),
//下拉框是否展开
show,
//下拉方向
direction,
directionVal: '',
})
}
onReset(data){
this.resetDate(data);
}
onClick(e){
let show = !this.state.show;
if(show){
if(this.props.show && this.props.show() == false){
return;
}
//事件互斥原则, 打开一个多选, 关闭其他所有多选
this.props.onClose(this.props.el);
let direction = this.state.direction;
if(direction === 'auto'){
//确定下拉框是朝上还是朝下
let bodyHeight = document.documentElement.clientHeight;
let rect = this.base.getBoundingClientRect();
let diff = bodyHeight - rect.y - rect.height - 20;
direction = diff > 300 ? 'down' : 'up';
}
this.setState({ directionVal: direction })
}else{
if(this.props.hidn && this.props.hidn() == false){
return;
}
//如果产生滚动条, 关闭下拉后回到顶部
this.bodyView.scroll(0, 0);
}
this.setState({ show });
//阻止其他绑定事件的冒泡
e && e.stopPropagation();
}
componentWillReceiveProps(props){
this.resetDate(props.data);
}
render(config, { sels, show }) {
const { tips, theme, prop, style, radio, repeat, clickClose, on } = config;
const borderStyle = { borderColor: theme.color };
//最外层边框的属性
const xmSelectProps = {
style: {
...style,
...(show ? borderStyle : {})
},
onClick: this.onClick.bind(this),
ua: checkUserAgent(),
}
//右边下拉箭头的变化class
const iconClass = show ? 'xm-icon xm-icon-expand' : 'xm-icon';
//提示信息的属性
const tipsProps = {
tips,
//没有已选择数据, 则显示提示
show: !sels.length
}
//普通多选数据
const valueProp = prop.value;
//选项, 选中状态, 禁用状态, 是否强制删除:在label上点击删除
const ck = (item, selected, disabled, mandatoryDelete) => {
//如果是禁用状态, 不能进行操作
if(disabled) return;
//如果现在是选中状态
if(selected && (!repeat || mandatoryDelete)){
let index = sels.findIndex(sel => sel[valueProp] == item[valueProp])
if(index != -1){
sels.splice(index, 1);
this.setState(sels);
}
}else{
//如果是单选模式
if(radio){
this.setState({ sels: [item] });
}else{
this.setState({ sels: [...sels, item] });
}
}
on && on({ arr: sels, item, selected: !selected });
//检查是否为选择即关闭状态, 强制删除情况下不做处理
clickClose && !mandatoryDelete && this.onClick();
};
const labelProps = { ...config, data: this.state.data, sels, ck, title: sels.map(sel => sel[prop.name]).join(',') }
const bodyProps = { ...config, data: this.state.data, sels, ck, show, onReset: this.onReset.bind(this) }
//控制下拉框的显示于隐藏
const bodyClass = ['xm-body', this.state.directionVal, show ? '' : 'dis'].join(' ');
return (
<xm-select { ...xmSelectProps } >
<i class={ iconClass } />
<Tips { ...tipsProps } />
<Label { ...labelProps } />
<div class={ bodyClass } ref={ ref => this.bodyView = ref}>
<General { ...bodyProps } />
</div>
</xm-select>
);
}
}
export default Framework;