1. [新增]物理分页配置 2. [新增]自定义搜索模式(远程搜索) 3. [新增]下拉选高度配置 4. [修改]调整布局为flex布局 5. [修改]展开下拉选时, 自动聚焦搜索框
156 lines
4.2 KiB
JavaScript
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; |