新增fixed布局

This commit is contained in:
maplemei 2021-01-19 16:28:25 +08:00
parent b47c8cfcb9
commit e928c6a038
19 changed files with 131 additions and 66 deletions

View File

@ -1,5 +1,23 @@
## 更新日志
### 1.2.2
*2021-01-19*
#### 新增
- 新增配置 `model.type: fixed`, 切换为`fixed`布局模式 [体验传送门](https://maplemei.gitee.io/xm-select/#/senior/table)
- 新增实例方法`calcPosition`, fixed布局模式下重新计算位置
#### Bug fixes
- 修改直接设置父节点无法选中的问题
- 修改非严格模式下设置父节点, 子节点受影响
- 修复渲染失败页面监听错误的问题
- 修改数据重复时分组错乱的问题
### 1.2.1
*2020-11-27*

View File

@ -96,7 +96,7 @@ const webpackConfig = {
],
devServer: {
host: '0.0.0.0',
port: 9000,
port: 9001,
publicPath: '/',
hot: true
},

4
dist/static/2.js vendored

File diff suppressed because one or more lines are too long

4
dist/static/3.js vendored

File diff suppressed because one or more lines are too long

10
dist/static/docs.js vendored

File diff suppressed because one or more lines are too long

4
dist/xm-select.js vendored

File diff suppressed because one or more lines are too long

View File

@ -38,6 +38,8 @@
this.fixedControl = bottom > document.documentElement.clientHeight &&
top + 44 <= document.documentElement.clientHeight;
this.$refs.control.style.left = this.fixedControl ? `${ left }px` : '0';
xmSelect.get().forEach(xs => xs.calcPosition());
},
removeScrollHandler() {
this.scrollParent && this.scrollParent.removeEventListener('scroll', this.scrollHandler);

View File

@ -48,7 +48,7 @@ layui.use('table', function() {
//修改一些css样式, 这里虽然能够使用, 但是还是不太友好, 努力中...
var cells = document.querySelectorAll('div[lay-id="demo"] .layui-table-cell');
for(var i = 0 ; i < cells.length ; i++ ){
cells[i].style.overflow = 'unset';
//cells[i].style.overflow = 'unset';
cells[i].style.height = 'auto';
}
//渲染多选
@ -56,6 +56,7 @@ layui.use('table', function() {
var xm = xmSelect.render({
el: '#XM-' + item.id,
autoRow: true,
model: { type: 'fixed' },
data: [
{name: '张三', value: 1},
{name: '李四', value: 2},
@ -70,6 +71,13 @@ layui.use('table', function() {
});
//表格滚动时 重新计算位置
document.querySelector('.layui-table-body').addEventListener('scroll', () => {
xmSelect.get().forEach(function(item){
item.calcPosition();
})
})
</script>
```

View File

@ -5,45 +5,21 @@
<div id="demo1" class="xm-select-demo"></div>
<script>
var demo1 = xmSelect.render({
xmSelect.render({
el: '#demo1',
autoRow: true,
model: {
label: {
type: 'search'
},
},
radio: true,
filterable: true,
tree: {
show: true,
showFolderIcon: true,
showLine: true,
indent: 20,
expandedKeys: [ -3 ],
simple: true,
clickExpand: false,
clickCheck: false,
strict: false
},
toolbar: {
show: true,
list: ['ALL', 'REVERSE', 'CLEAR']
},
filterable: true,
data(){
return [
{name: '销售员', value: -1, disabled: true, children: [
{name: '张三1', value: 1, selected: true, children: []},
{name: '李四1', value: 2, selected: true},
{name: '王五1', value: 3, disabled: true},
]},
{name: '奖品', value: -2, disabled: true, children: [
{name: '奖品3', value: -3, children: [
{name: '苹果3', value: 14, selected: true},
{name: '香蕉3', value: 15},
{name: '葡萄3', value: 16},
]},
{name: '苹果2', value: 4, selected: true, disabled: true},
{name: '香蕉2', value: 5},
{name: '葡萄2', value: 6},
]},
]
},
data: [
{name: '张三', value: 1, selected: true},
{name: '李四', value: 2},
{name: '王五', value: 3},
]
})
</script>

View File

@ -134,7 +134,7 @@ model: {
}
},
},
//展示类型, 下拉框形式: absolute, 直接显示模式: relative
//展示类型, 下拉框形式: absolute, 直接显示模式: relative, 浮动布局: fixed
type: 'absolute',
},
```
@ -258,3 +258,4 @@ xmSelect.render()后会返回一个xmSelect对象, 可以进行方法调用
| changeExpandedKeys | 树模式下更新节点展开状态, v1.2.0 新增 | (keys: true-全部展开, false-全部关闭, 数组-展开的节点值) |
| enable | 启用选项, disabled=false, v1.2.0 新增 | (array: 想要启用的选项数组) |
| disable | 禁用用选项, disabled=true, v1.2.0 新增 | (array: 想要禁用的选项数组) |
| calcPosition | fixed布局模式下重新计算位置, v1.2.2 新增 | - |

View File

@ -1,7 +1,8 @@
{
"name": "xm-select",
"version": "1.2.1",
"version": "1.2.2",
"description": "始于Layui的select多选解决方案",
"website": "https://maplemei.gitee.io/xm-select",
"main": "index.js",
"scripts": {
"dev": "cross-env NODE_ENV=dev node_modules/.bin/webpack-dev-server --config build/webpack.config.js",

View File

@ -31,11 +31,12 @@ class Framework extends Component{
show: false,
tmpColor: '',
bodyClass: '',
time: 0,
}
}
init(props, refresh){
let { data, prop, initValue, radio } = props, sels;
let { data, prop, initValue, radio, tree, cascader } = props, sels;
//如果新数据和旧数据不同 或者 强制刷新 才进行数据处理
if(refresh){
let dataObj = {};
@ -47,6 +48,9 @@ class Framework extends Component{
}), dataObj)
if(radio && sels.length > 1){
sels = sels.slice(0, 1)
if(tree.show && tree.strict || cascader.show && cascader.strict){
this.clearAndReset(data, sels, false);
}
}
this.setState({ sels, dataObj, flatData });
}
@ -139,14 +143,23 @@ class Framework extends Component{
}
clearAndReset(data, changeData, parentCK){
const { selected, children, value } = this.props.prop;
const { selected, disabled, children, value } = this.props.prop;
data.forEach(item => {
item[selected] = changeData.findIndex(c => c[value] === item[value]) != -1 || parentCK;
let child = item[children];
child && isArray(child) && this.clearAndReset(child, changeData, item[selected])
if(child && isArray(child)){
this.clearAndReset(child, changeData, item[selected])
let len = child.length;
let slen = child.filter(i => i[selected] === true || i.__node.selected === true).length;
item.__node.selected = slen === len;
item.__node.half = slen > 0 && slen < len || child.filter(i => i.__node.half === true).length > 0;
item.__node.disabled = child.filter(i => i[disabled] === true || i.__node.disabled === true).length === len;
}
})
}
load(data, dataObj, flatData, parent, level = 0, initValue){
const { prop, tree, cascader } = this.props;
const { children, optgroup, value, selected, disabled } = prop;
@ -252,7 +265,7 @@ class Framework extends Component{
//选项, 选中状态, 禁用状态, 是否强制删除:在label上点击删除
itemClick(item, itemSelected, itemDisabled, mandatoryDelete){
const { theme, prop, radio, repeat, clickClose, max, maxMethod, tree } = this.props
const { theme, prop, radio, repeat, clickClose, max, maxMethod, tree, data } = this.props
let sels = [ ...this.state.sels ]
const { value, selected, disabled, children, optgroup } = prop
@ -308,6 +321,7 @@ class Framework extends Component{
}else{
sels = [...sels, item]
}
this.clearAndReset(data, sels, itemSelected)
this.resetSelectValue(sels, [item], !itemSelected);
}
}
@ -439,6 +453,20 @@ class Framework extends Component{
}
}
calcPosition(){
if(this.state.show && this.props.model.type === 'fixed'){
let rect = this.base.getBoundingClientRect();
(Date.now() - this.state.time > 10) && this.setState({ time: Date.now() })
return {
position: 'fixed',
left: rect.x,
top: rect.y + rect.height + 4,
width: rect.width,
}
}
return {};
}
//组件将要接收新属性
componentWillReceiveProps(props){
this.init(props, props.updateData);
@ -482,6 +510,7 @@ class Framework extends Component{
//渲染组件
let Body = content ? <Custom { ...bodyProps } /> : tree.show ? <Tree { ...bodyProps } ref={ ref => this.treeRef = ref } /> : config.cascader.show ? <Cascader { ...bodyProps } /> : <General { ...bodyProps } ref={ ref => this.generalRef = ref } />;
let bodyStyle = this.calcPosition();
return (
<xm-select { ...xmSelectProps } >
@ -495,7 +524,7 @@ class Framework extends Component{
<i class={ show ? 'xm-icon xm-icon-expand' : 'xm-icon' } />
{ sels.length === 0 && <div class="xm-tips">{ config.tips }</div> }
<Label { ...labelProps } ref={ ref => this.labelRef = ref } />
<div class={ ['xm-body', bodyClass, config.model.type, show ? '':'dis', ].join(' ') } ref={ ref => this.bodyView = ref}>
<div class={ ['xm-body', bodyClass, config.model.type, show ? '':'dis', ].join(' ') } style={ bodyStyle } ref={ ref => this.bodyView = ref}>
{ Body }
</div>
{ disabled && <div class="xm-select-disabled"></div> }
@ -558,6 +587,10 @@ class Framework extends Component{
return ;
}
if(model.type === 'fixed'){
return ;
}
let rect = this.base.getBoundingClientRect();
if(direction === 'auto'){
//用于控制js获取下拉框的高度

View File

@ -104,7 +104,10 @@ class Label extends Component{
}
}else if(type == 'search'){
innerHTML = false;
let one = list[0][name];
let one = '';
if(list.length){
one = list[0][name]
}
html = (
<input class="label-search-input" type="text" placeholder={ config.searchTips } style={{ width: '100%', border: 'none' }} value={

View File

@ -286,8 +286,9 @@ class General extends Component{
//如果是分组模式, 要分页先去除分组, 然后在计算分页, 最后再加上分组
let groupInfo = {};
arr.filter(item => item[optgroup]).forEach(g => {
g[children].forEach(item => groupInfo[item[value]] = g);
arr.filter(item => item[optgroup]).forEach((g, groupIndex) => {
groupInfo[groupIndex] = g;
g[children].forEach(item => item.__group__index = groupIndex);
});
arr = arr.filter(item => !item[optgroup]);
@ -342,7 +343,8 @@ class General extends Component{
let newArr = [], group, tmpGroup = { __tmp: true };
tmpGroup[optgroup] = true;
arr.forEach(item => {
let g = groupInfo[item[value]];
let g = groupInfo[item.__group__index];
delete item.__group__index;
if(group && !g){
g = tmpGroup
}

View File

@ -264,6 +264,14 @@ class xmOptions {
return this;
}
/**
* 重新计算下拉的位置
*/
calcPosition(){
childData[this.options.el].calcPosition()
return this;
}
}
export default xmOptions;

View File

@ -160,7 +160,7 @@ export default function (lan = 'zn') {
},
},
icon: 'show',
type: 'absolute',
type: 'absolute',//可选值, relative fixed
},
//自定义选中的图标
iconfont: {

View File

@ -1,4 +1,4 @@
import { name, version } from '../package.json'
import { name, version, website } from '../package.json'
import { selector, warn } from '@/common/util'
import Select from '@/components/xm-select'
@ -9,6 +9,7 @@ export const childData = {};
export default {
name,
version,
doc: website,
render(options) {
let { el } = options;
options.dom = selector(el);
@ -23,7 +24,7 @@ export default {
let instance = new Select(options);
//已经渲染
if (instance && instance.__render_success) {
if (instance && instance.options.__render_success) {
datas[el] = instance;
}
return instance;

View File

@ -15,6 +15,16 @@ window.addEventListener('click', () => {
})
})
/**
* 监听页面滚动事件
*/
window.addEventListener('scroll', () => {
Object.keys(datas).forEach(key => {
let item = datas[key]
item && item.calcPosition && item.calcPosition()
})
})
if ((typeof exports === 'undefined' ? 'undefined' : _typeof(exports)) === 'object') {
module.exports = xmSelect;

View File

@ -109,11 +109,13 @@ xm-select{
}
.label-content{
flex-wrap: nowrap;
white-space: nowrap;
}
}
&.auto-row{
.label-content{
flex-wrap: wrap;
padding-right: 30px !important;
}
.xm-label-block > span{
white-space: unset;
@ -124,7 +126,7 @@ xm-select{
.scroll{
.label-content{
display: flex;
padding: 3px 30px 3px 10px;
padding: 3px 10px;
}
}