import { h, Component, render } from 'preact' import { isFunction, isArray, safety, deepMerge, mergeArr, IEVersion } from '@/common/util' const emptyVal = {}; /** * 普通的多选渲染 */ class General extends Component{ constructor(options){ super(options); this.setState({ filterValue: '', remote: true, loading: false, pageIndex: 1, totalSize: 0, val: emptyVal, }); this.searchCid = 0; this.inputOver = true; this.__value = ''; this.tempData = []; this.size = 0; } optionClick(item, selected, disabled, e){ this.props.ck(item, selected, disabled); this.focus(); //阻止父组件上的事件冒泡 this.blockClick(e); } groupClick(item, e){ const { click, children, disabled } = this.props.prop; let m = item[click], arr = item[children].filter(opt => !opt[disabled]); if(m === 'SELECT'){ this.props.onReset(arr, 'append'); }else if(m === 'CLEAR'){ this.props.onReset(arr, 'delete'); }else if(m === 'AUTO'){ this.props.onReset(arr, 'auto'); }else if(isFunction(m)){ m(item); } this.focus(); //阻止父组件上的事件冒泡 this.blockClick(e); } blockClick(e){ e.stopPropagation(); } pagePrevClick(size = this.size){ let index = this.state.pageIndex; if(index <= 1){ return ; } this.changePageIndex(index - 1); this.props.pageRemote && this.postData(index - 1, true); } pageNextClick(size = this.size){ let index = this.state.pageIndex; if(index >= size){ return ; } this.changePageIndex(index + 1); this.props.pageRemote && this.postData(index + 1, true); } changePageIndex(index){ this.setState({ pageIndex: index }) } searchInput(e){ let v = e.target.value; if(v === this.__value){ return ; } clearTimeout(this.searchCid); if(this.inputOver){ //保证输入框内的值是实时的 this.__value = v; //让搜索变成异步的 this.searchCid = setTimeout(() => { this.callback = true; this.setState({ filterValue: this.__value, remote: true, pageIndex: 1 }) }, this.props.delay); } } focus(){ this.searchInputRef && this.searchInputRef.focus(); } blur(){ this.searchInputRef && this.searchInputRef.blur(); } handleComposition(e){ let type = e.type; if(type === 'compositionstart'){ this.inputOver = false; clearTimeout(this.searchCid); }else if(type === 'compositionend'){ this.inputOver = true; this.searchInput(e); } } postData(pageIndex = this.state.pageIndex, mandatory = false){ if(this.state.remote || mandatory){ this.callback = false; this.setState({ loading: true, remote: false }); //让输入框失去焦点 this.blur(); this.props.remoteMethod(this.state.filterValue, (result, totalSize = 1) => { //这里同步修改为异步 setTimeout(() => { //回调后可以重新聚焦 this.focus(); this.callback = true; this.setState({ loading: false, totalSize }); this.props.onReset(result, 'data'); }, 10); }, this.props.show, pageIndex); } } //键盘事件 keydown(type, e){ let keyCode = e.keyCode; if(type === 'div'){ //Esc, Tab if(keyCode === 27 || keyCode === 9){ this.props.onReset(false, 'close'); }else //Left if(keyCode === 37){ this.pagePrevClick(); }else //Right 键 if(keyCode === 39){ this.pageNextClick(); } } const { value, optgroup, disabled } = this.props.prop; let data = this.tempData.filter(item => !item[optgroup] && !item[disabled]); let len = data.length - 1; if(len === -1){ return ; } let index = data.findIndex(item => item[value] === this.state.val); //Up 键 if(keyCode === 38){ if(index <= 0){ index = len }else if(index > 0){ index -= 1; } let val = data[index][value]; this.setState({ val }) }else //Down 键 if(keyCode === 40){ if(index === -1 || index === len){ index = 0 }else if(index < len){ index += 1; } let val = data[index][value]; this.setState({ val }) }else //Enter 键 if(keyCode === 13){ if(this.state.val != emptyVal){ let option = data[index]; this.optionClick(option, this.props.sels.findIndex(item => item[value] === this.state.val) != -1, option[disabled], e) } } } //组件将要接收新属性 componentWillReceiveProps(props){ if(this.props.show != props.show){ if(!props.show){ //清空输入框的值 this.setState({ filterValue: '', val: emptyVal }); this.__value = ''; this.searchInputRef && (this.searchInputRef.value = ''); }else{ //聚焦输入框 setTimeout(() => { if(props.filterable){ this.focus() }else{ this.base.focus() } }, 0); } } } render(config) { let { data, flatData, prop, template, theme, radio, sels, empty, filterable, filterMethod, remoteSearch, remoteMethod, delay, searchTips, create, pageRemote, max } = config const { name, value, disabled, children, optgroup } = prop; let arr = deepMerge([], flatData), creator; //远程分页 或者 远程搜索 if(pageRemote || filterable && remoteSearch){ this.postData(); } //本地搜索 if(filterable && !remoteSearch){ const filterData = (item, index) => { const isGroup = item[optgroup]; if(isGroup){ delete item.__del; return true; } return filterMethod(this.state.filterValue, item, index, prop); } arr = arr.filter(filterData); for(let i = 0; i < arr.length - 1; i++){ let a = arr[i]; let b = arr[i + 1]; if(a[optgroup] && b[optgroup]){ arr[i].__del = true; } } if(arr.length && arr[arr.length - 1][optgroup]){ arr[arr.length - 1].__del = true; } arr = arr.filter(item => !item.__del); //创建条目 creator = this.state.filterValue && isFunction(create); } const search = (