init
This commit is contained in:
114
src/components/element/framework.js
Normal file
114
src/components/element/framework.js
Normal file
@@ -0,0 +1,114 @@
|
||||
import { h, Component, render } from '@/components/preact'
|
||||
|
||||
//渲染类
|
||||
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);
|
||||
}
|
||||
|
||||
reset(){
|
||||
let selected = this.props.prop.selected;
|
||||
this.value(this.props.initValue ? this.props.initValue : this.props.data.filter(item => item[selected]), false);
|
||||
}
|
||||
|
||||
value(sels, show){
|
||||
let data = this.props.data;
|
||||
let value = this.props.prop.value;
|
||||
this.setState({
|
||||
sels: sels.map(sel => typeof sel === 'object' ? sel[value] : sel).map(val => data.find(item => item[value] == val)).filter(a => a),
|
||||
//下拉框是否展开
|
||||
show
|
||||
})
|
||||
}
|
||||
|
||||
onClick(e){
|
||||
let show = !this.state.show;
|
||||
|
||||
if(show){
|
||||
if(this.props.show && this.props.show() == false){
|
||||
return;
|
||||
}
|
||||
//事件互斥原则, 打开一个多选, 关闭其他所有多选
|
||||
this.props.onClose(this.props.el);
|
||||
}else{
|
||||
if(this.props.hidn && this.props.hidn() == false){
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({ show })
|
||||
//阻止其他绑定事件的冒泡
|
||||
e && e.stopPropagation();
|
||||
}
|
||||
|
||||
componentWillReceiveProps(props){
|
||||
|
||||
}
|
||||
|
||||
render({ tips, theme, data, prop, template, model, empty }, { sels, show }) {
|
||||
const borderStyle = { borderColor: theme.color };
|
||||
//最外层边框的属性
|
||||
const xmSelectProps = {
|
||||
style: show ? borderStyle : '',
|
||||
onClick: this.onClick.bind(this)
|
||||
}
|
||||
//右边下拉箭头的变化class
|
||||
const iconClass = show ? 'xm-icon xm-icon-expand' : 'xm-icon';
|
||||
//提示信息的属性
|
||||
const tipsProps = {
|
||||
tips,
|
||||
//没有已选择数据, 则显示提示
|
||||
show: !sels.length
|
||||
}
|
||||
//普通多选数据
|
||||
const valueProp = prop.value;
|
||||
|
||||
const ck = (item, selected, disabled) => {
|
||||
//如果是禁用状态, 不能进行操作
|
||||
if(disabled) return;
|
||||
|
||||
//如果现在是选中状态
|
||||
if(selected){
|
||||
let index = sels.findIndex(sel => sel[valueProp] == item[valueProp])
|
||||
if(index != -1){
|
||||
sels.splice(index, 1);
|
||||
this.setState(sels);
|
||||
}
|
||||
}else{
|
||||
this.setState({
|
||||
sels: [...sels, item]
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
const labelProps = { data, prop, model, theme, sels, ck, title: sels.map(sel => sel[prop.name]).join(',') }
|
||||
const bodyProps = { data, prop, template, theme, sels, ck, empty }
|
||||
//控制下拉框的显示于隐藏
|
||||
const bodyClass = show ? 'xm-body' : 'xm-body dis';
|
||||
|
||||
return (
|
||||
<xm-select { ...xmSelectProps }>
|
||||
<i class={ iconClass } />
|
||||
<Tips { ...tipsProps } />
|
||||
<Label { ...labelProps } />
|
||||
<div class={ bodyClass }>
|
||||
<General { ...bodyProps } />
|
||||
</div>
|
||||
</xm-select>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Framework;
|
||||
0
src/components/element/header.js
Normal file
0
src/components/element/header.js
Normal file
76
src/components/element/label.js
Normal file
76
src/components/element/label.js
Normal file
@@ -0,0 +1,76 @@
|
||||
import { h, Component, render } from '@/components/preact'
|
||||
|
||||
/**
|
||||
* 标签的渲染
|
||||
*/
|
||||
class Label extends Component{
|
||||
|
||||
constructor(options){
|
||||
super(options);
|
||||
}
|
||||
|
||||
iconClick(item, selected, disabled, e){
|
||||
this.props.ck(item, selected, disabled);
|
||||
//阻止父组件上的事件冒泡
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
render({ data, prop, theme, model, sels }) {
|
||||
//获取变换属性
|
||||
const { name, disabled } = prop;
|
||||
|
||||
//获取配置项
|
||||
const label = model.label;
|
||||
const type = label.type;
|
||||
const conf = label[type];
|
||||
|
||||
//渲染结果
|
||||
let html = '';
|
||||
|
||||
if(type === 'text'){
|
||||
html = sels.map(sel => `${conf.left}${sel[name]}${conf.right}`).join(conf.separator)
|
||||
}else if(type === 'block'){
|
||||
//已选择的数据
|
||||
let arr = [...sels];
|
||||
|
||||
const style = { backgroundColor: theme.color }
|
||||
//显示的个数
|
||||
const count = conf.showCount <= 0 ? arr.length : conf.showCount;
|
||||
|
||||
html = arr.splice(0, count).map(sel => {
|
||||
const styleProps = { width: conf.showIcon ? 'calc(100% - 20px)' : '100%', }
|
||||
const className = ['xm-label-block', sel[disabled] ? 'disabled':''].join(' ');
|
||||
return (
|
||||
<div class={className} style={ style }>
|
||||
<span style={ styleProps }>{ sel[name] }</span>
|
||||
{ conf.showIcon && <i class="xm-iconfont icon-close" onClick={ this.iconClick.bind(this, sel, true, sel[disabled]) }></i> }
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
||||
//剩余没显示的数据
|
||||
if(arr.length){
|
||||
html.push(
|
||||
<div class="xm-label-block" style={ style }>
|
||||
+ { arr.length }
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}else{
|
||||
if(sels.length && conf && conf.template){
|
||||
html = conf.template(data, sels);
|
||||
}else{
|
||||
html = sels.map(sel => sel[name]).join(',')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<div class="xm-label">
|
||||
{ html }
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Label;
|
||||
51
src/components/element/model/general.js
Normal file
51
src/components/element/model/general.js
Normal file
@@ -0,0 +1,51 @@
|
||||
import { h, Component, render } from '@/components/preact'
|
||||
|
||||
/**
|
||||
* 普通的多选渲染
|
||||
*/
|
||||
class General extends Component{
|
||||
|
||||
constructor(options){
|
||||
super(options);
|
||||
}
|
||||
|
||||
optionClick(item, selected, disabled, e){
|
||||
this.props.ck(item, selected, disabled);
|
||||
//阻止父组件上的事件冒泡
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
render({ data, prop, template, theme, sels, empty }) {
|
||||
|
||||
const { name, value, disabled } = prop;
|
||||
|
||||
const arr = data.map(item => {
|
||||
|
||||
const selected = !!sels.find(sel => sel[value] == item[value])
|
||||
const iconStyle = { color: selected ? theme.color : '' }
|
||||
// const className = 'xm-option' + (item.disabled ? ' disabled' : '');
|
||||
const className = ['xm-option', (item[disabled] ? ' disabled' : ''), (selected ? ' selected' : '')].join(' ');
|
||||
|
||||
return (
|
||||
<div class={className} value={ item[value] } onClick={ this.optionClick.bind(this, item, selected, item[disabled]) }>
|
||||
<div class="xm-option-icon" style={ { borderColor: theme.color, } }>
|
||||
<i class="xm-iconfont icon-duox" style={ iconStyle }></i>
|
||||
</div>
|
||||
<div class='xm-option-content' dangerouslySetInnerHTML={{ __html: template(item, sels, item[name], item[value]) }}></div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
||||
if(!data.length){
|
||||
arr.push(
|
||||
<div class="xm-select-empty">{ empty }</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div> { arr } </div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default General;
|
||||
20
src/components/element/tips.js
Normal file
20
src/components/element/tips.js
Normal file
@@ -0,0 +1,20 @@
|
||||
import { h, Component, render } from '@/components/preact'
|
||||
|
||||
/**
|
||||
* 默认提示
|
||||
*/
|
||||
class Tips extends Component{
|
||||
|
||||
constructor(options){
|
||||
super(options);
|
||||
}
|
||||
|
||||
render({ tips, show }) {
|
||||
const tipsClass = show ? 'xm-tips' : 'xm-tips dis';
|
||||
return (
|
||||
<div class={ tipsClass }>{ tips }</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Tips;
|
||||
Reference in New Issue
Block a user