新增fixed布局
This commit is contained in:
parent
b47c8cfcb9
commit
e928c6a038
18
CHANGELOG.md
18
CHANGELOG.md
@ -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
|
### 1.2.1
|
||||||
|
|
||||||
*2020-11-27*
|
*2020-11-27*
|
||||||
|
@ -96,7 +96,7 @@ const webpackConfig = {
|
|||||||
],
|
],
|
||||||
devServer: {
|
devServer: {
|
||||||
host: '0.0.0.0',
|
host: '0.0.0.0',
|
||||||
port: 9000,
|
port: 9001,
|
||||||
publicPath: '/',
|
publicPath: '/',
|
||||||
hot: true
|
hot: true
|
||||||
},
|
},
|
||||||
|
4
dist/static/2.js
vendored
4
dist/static/2.js
vendored
File diff suppressed because one or more lines are too long
4
dist/static/3.js
vendored
4
dist/static/3.js
vendored
File diff suppressed because one or more lines are too long
10
dist/static/docs.js
vendored
10
dist/static/docs.js
vendored
File diff suppressed because one or more lines are too long
4
dist/xm-select.js
vendored
4
dist/xm-select.js
vendored
File diff suppressed because one or more lines are too long
@ -38,6 +38,8 @@
|
|||||||
this.fixedControl = bottom > document.documentElement.clientHeight &&
|
this.fixedControl = bottom > document.documentElement.clientHeight &&
|
||||||
top + 44 <= document.documentElement.clientHeight;
|
top + 44 <= document.documentElement.clientHeight;
|
||||||
this.$refs.control.style.left = this.fixedControl ? `${ left }px` : '0';
|
this.$refs.control.style.left = this.fixedControl ? `${ left }px` : '0';
|
||||||
|
|
||||||
|
xmSelect.get().forEach(xs => xs.calcPosition());
|
||||||
},
|
},
|
||||||
removeScrollHandler() {
|
removeScrollHandler() {
|
||||||
this.scrollParent && this.scrollParent.removeEventListener('scroll', this.scrollHandler);
|
this.scrollParent && this.scrollParent.removeEventListener('scroll', this.scrollHandler);
|
||||||
|
@ -48,7 +48,7 @@ layui.use('table', function() {
|
|||||||
//修改一些css样式, 这里虽然能够使用, 但是还是不太友好, 努力中...
|
//修改一些css样式, 这里虽然能够使用, 但是还是不太友好, 努力中...
|
||||||
var cells = document.querySelectorAll('div[lay-id="demo"] .layui-table-cell');
|
var cells = document.querySelectorAll('div[lay-id="demo"] .layui-table-cell');
|
||||||
for(var i = 0 ; i < cells.length ; i++ ){
|
for(var i = 0 ; i < cells.length ; i++ ){
|
||||||
cells[i].style.overflow = 'unset';
|
//cells[i].style.overflow = 'unset';
|
||||||
cells[i].style.height = 'auto';
|
cells[i].style.height = 'auto';
|
||||||
}
|
}
|
||||||
//渲染多选
|
//渲染多选
|
||||||
@ -56,6 +56,7 @@ layui.use('table', function() {
|
|||||||
var xm = xmSelect.render({
|
var xm = xmSelect.render({
|
||||||
el: '#XM-' + item.id,
|
el: '#XM-' + item.id,
|
||||||
autoRow: true,
|
autoRow: true,
|
||||||
|
model: { type: 'fixed' },
|
||||||
data: [
|
data: [
|
||||||
{name: '张三', value: 1},
|
{name: '张三', value: 1},
|
||||||
{name: '李四', value: 2},
|
{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>
|
</script>
|
||||||
```
|
```
|
||||||
|
@ -5,45 +5,21 @@
|
|||||||
<div id="demo1" class="xm-select-demo"></div>
|
<div id="demo1" class="xm-select-demo"></div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
var demo1 = xmSelect.render({
|
xmSelect.render({
|
||||||
el: '#demo1',
|
el: '#demo1',
|
||||||
autoRow: true,
|
model: {
|
||||||
filterable: true,
|
label: {
|
||||||
tree: {
|
type: 'search'
|
||||||
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']
|
|
||||||
},
|
},
|
||||||
|
radio: true,
|
||||||
filterable: true,
|
filterable: true,
|
||||||
data(){
|
data: [
|
||||||
return [
|
{name: '张三', value: 1, selected: true},
|
||||||
{name: '销售员', value: -1, disabled: true, children: [
|
{name: '李四', value: 2},
|
||||||
{name: '张三1', value: 1, selected: true, children: []},
|
{name: '王五', value: 3},
|
||||||
{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},
|
|
||||||
]},
|
|
||||||
]
|
]
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -134,7 +134,7 @@ model: {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
//展示类型, 下拉框形式: absolute, 直接显示模式: relative
|
//展示类型, 下拉框形式: absolute, 直接显示模式: relative, 浮动布局: fixed
|
||||||
type: 'absolute',
|
type: 'absolute',
|
||||||
},
|
},
|
||||||
```
|
```
|
||||||
@ -258,3 +258,4 @@ xmSelect.render()后会返回一个xmSelect对象, 可以进行方法调用
|
|||||||
| changeExpandedKeys | 树模式下更新节点展开状态, v1.2.0 新增 | (keys: true-全部展开, false-全部关闭, 数组-展开的节点值) |
|
| changeExpandedKeys | 树模式下更新节点展开状态, v1.2.0 新增 | (keys: true-全部展开, false-全部关闭, 数组-展开的节点值) |
|
||||||
| enable | 启用选项, disabled=false, v1.2.0 新增 | (array: 想要启用的选项数组) |
|
| enable | 启用选项, disabled=false, v1.2.0 新增 | (array: 想要启用的选项数组) |
|
||||||
| disable | 禁用用选项, disabled=true, v1.2.0 新增 | (array: 想要禁用的选项数组) |
|
| disable | 禁用用选项, disabled=true, v1.2.0 新增 | (array: 想要禁用的选项数组) |
|
||||||
|
| calcPosition | fixed布局模式下重新计算位置, v1.2.2 新增 | - |
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
{
|
{
|
||||||
"name": "xm-select",
|
"name": "xm-select",
|
||||||
"version": "1.2.1",
|
"version": "1.2.2",
|
||||||
"description": "始于Layui的select多选解决方案",
|
"description": "始于Layui的select多选解决方案",
|
||||||
|
"website": "https://maplemei.gitee.io/xm-select",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "cross-env NODE_ENV=dev node_modules/.bin/webpack-dev-server --config build/webpack.config.js",
|
"dev": "cross-env NODE_ENV=dev node_modules/.bin/webpack-dev-server --config build/webpack.config.js",
|
||||||
|
@ -31,11 +31,12 @@ class Framework extends Component{
|
|||||||
show: false,
|
show: false,
|
||||||
tmpColor: '',
|
tmpColor: '',
|
||||||
bodyClass: '',
|
bodyClass: '',
|
||||||
|
time: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init(props, refresh){
|
init(props, refresh){
|
||||||
let { data, prop, initValue, radio } = props, sels;
|
let { data, prop, initValue, radio, tree, cascader } = props, sels;
|
||||||
//如果新数据和旧数据不同 或者 强制刷新 才进行数据处理
|
//如果新数据和旧数据不同 或者 强制刷新 才进行数据处理
|
||||||
if(refresh){
|
if(refresh){
|
||||||
let dataObj = {};
|
let dataObj = {};
|
||||||
@ -47,6 +48,9 @@ class Framework extends Component{
|
|||||||
}), dataObj)
|
}), dataObj)
|
||||||
if(radio && sels.length > 1){
|
if(radio && sels.length > 1){
|
||||||
sels = sels.slice(0, 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 });
|
this.setState({ sels, dataObj, flatData });
|
||||||
}
|
}
|
||||||
@ -139,14 +143,23 @@ class Framework extends Component{
|
|||||||
}
|
}
|
||||||
|
|
||||||
clearAndReset(data, changeData, parentCK){
|
clearAndReset(data, changeData, parentCK){
|
||||||
const { selected, children, value } = this.props.prop;
|
const { selected, disabled, children, value } = this.props.prop;
|
||||||
data.forEach(item => {
|
data.forEach(item => {
|
||||||
item[selected] = changeData.findIndex(c => c[value] === item[value]) != -1 || parentCK;
|
item[selected] = changeData.findIndex(c => c[value] === item[value]) != -1 || parentCK;
|
||||||
let child = item[children];
|
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){
|
load(data, dataObj, flatData, parent, level = 0, initValue){
|
||||||
const { prop, tree, cascader } = this.props;
|
const { prop, tree, cascader } = this.props;
|
||||||
const { children, optgroup, value, selected, disabled } = prop;
|
const { children, optgroup, value, selected, disabled } = prop;
|
||||||
@ -252,7 +265,7 @@ class Framework extends Component{
|
|||||||
//选项, 选中状态, 禁用状态, 是否强制删除:在label上点击删除
|
//选项, 选中状态, 禁用状态, 是否强制删除:在label上点击删除
|
||||||
itemClick(item, itemSelected, itemDisabled, mandatoryDelete){
|
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 ]
|
let sels = [ ...this.state.sels ]
|
||||||
const { value, selected, disabled, children, optgroup } = prop
|
const { value, selected, disabled, children, optgroup } = prop
|
||||||
|
|
||||||
@ -308,6 +321,7 @@ class Framework extends Component{
|
|||||||
}else{
|
}else{
|
||||||
sels = [...sels, item]
|
sels = [...sels, item]
|
||||||
}
|
}
|
||||||
|
this.clearAndReset(data, sels, itemSelected)
|
||||||
this.resetSelectValue(sels, [item], !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){
|
componentWillReceiveProps(props){
|
||||||
this.init(props, props.updateData);
|
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 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 (
|
return (
|
||||||
<xm-select { ...xmSelectProps } >
|
<xm-select { ...xmSelectProps } >
|
||||||
@ -495,7 +524,7 @@ class Framework extends Component{
|
|||||||
<i class={ show ? 'xm-icon xm-icon-expand' : 'xm-icon' } />
|
<i class={ show ? 'xm-icon xm-icon-expand' : 'xm-icon' } />
|
||||||
{ sels.length === 0 && <div class="xm-tips">{ config.tips }</div> }
|
{ sels.length === 0 && <div class="xm-tips">{ config.tips }</div> }
|
||||||
<Label { ...labelProps } ref={ ref => this.labelRef = ref } />
|
<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 }
|
{ Body }
|
||||||
</div>
|
</div>
|
||||||
{ disabled && <div class="xm-select-disabled"></div> }
|
{ disabled && <div class="xm-select-disabled"></div> }
|
||||||
@ -558,6 +587,10 @@ class Framework extends Component{
|
|||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(model.type === 'fixed'){
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
let rect = this.base.getBoundingClientRect();
|
let rect = this.base.getBoundingClientRect();
|
||||||
if(direction === 'auto'){
|
if(direction === 'auto'){
|
||||||
//用于控制js获取下拉框的高度
|
//用于控制js获取下拉框的高度
|
||||||
|
@ -104,7 +104,10 @@ class Label extends Component{
|
|||||||
}
|
}
|
||||||
}else if(type == 'search'){
|
}else if(type == 'search'){
|
||||||
innerHTML = false;
|
innerHTML = false;
|
||||||
let one = list[0][name];
|
let one = '';
|
||||||
|
if(list.length){
|
||||||
|
one = list[0][name]
|
||||||
|
}
|
||||||
|
|
||||||
html = (
|
html = (
|
||||||
<input class="label-search-input" type="text" placeholder={ config.searchTips } style={{ width: '100%', border: 'none' }} value={
|
<input class="label-search-input" type="text" placeholder={ config.searchTips } style={{ width: '100%', border: 'none' }} value={
|
||||||
|
@ -286,8 +286,9 @@ class General extends Component{
|
|||||||
|
|
||||||
//如果是分组模式, 要分页先去除分组, 然后在计算分页, 最后再加上分组
|
//如果是分组模式, 要分页先去除分组, 然后在计算分页, 最后再加上分组
|
||||||
let groupInfo = {};
|
let groupInfo = {};
|
||||||
arr.filter(item => item[optgroup]).forEach(g => {
|
arr.filter(item => item[optgroup]).forEach((g, groupIndex) => {
|
||||||
g[children].forEach(item => groupInfo[item[value]] = g);
|
groupInfo[groupIndex] = g;
|
||||||
|
g[children].forEach(item => item.__group__index = groupIndex);
|
||||||
});
|
});
|
||||||
arr = arr.filter(item => !item[optgroup]);
|
arr = arr.filter(item => !item[optgroup]);
|
||||||
|
|
||||||
@ -342,7 +343,8 @@ class General extends Component{
|
|||||||
let newArr = [], group, tmpGroup = { __tmp: true };
|
let newArr = [], group, tmpGroup = { __tmp: true };
|
||||||
tmpGroup[optgroup] = true;
|
tmpGroup[optgroup] = true;
|
||||||
arr.forEach(item => {
|
arr.forEach(item => {
|
||||||
let g = groupInfo[item[value]];
|
let g = groupInfo[item.__group__index];
|
||||||
|
delete item.__group__index;
|
||||||
if(group && !g){
|
if(group && !g){
|
||||||
g = tmpGroup
|
g = tmpGroup
|
||||||
}
|
}
|
||||||
|
@ -264,6 +264,14 @@ class xmOptions {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重新计算下拉的位置
|
||||||
|
*/
|
||||||
|
calcPosition(){
|
||||||
|
childData[this.options.el].calcPosition()
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default xmOptions;
|
export default xmOptions;
|
||||||
|
@ -160,7 +160,7 @@ export default function (lan = 'zn') {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
icon: 'show',
|
icon: 'show',
|
||||||
type: 'absolute',
|
type: 'absolute',//可选值, relative, fixed
|
||||||
},
|
},
|
||||||
//自定义选中的图标
|
//自定义选中的图标
|
||||||
iconfont: {
|
iconfont: {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { name, version } from '../package.json'
|
import { name, version, website } from '../package.json'
|
||||||
import { selector, warn } from '@/common/util'
|
import { selector, warn } from '@/common/util'
|
||||||
import Select from '@/components/xm-select'
|
import Select from '@/components/xm-select'
|
||||||
|
|
||||||
@ -9,6 +9,7 @@ export const childData = {};
|
|||||||
export default {
|
export default {
|
||||||
name,
|
name,
|
||||||
version,
|
version,
|
||||||
|
doc: website,
|
||||||
render(options) {
|
render(options) {
|
||||||
let { el } = options;
|
let { el } = options;
|
||||||
options.dom = selector(el);
|
options.dom = selector(el);
|
||||||
@ -23,7 +24,7 @@ export default {
|
|||||||
|
|
||||||
let instance = new Select(options);
|
let instance = new Select(options);
|
||||||
//已经渲染
|
//已经渲染
|
||||||
if (instance && instance.__render_success) {
|
if (instance && instance.options.__render_success) {
|
||||||
datas[el] = instance;
|
datas[el] = instance;
|
||||||
}
|
}
|
||||||
return instance;
|
return instance;
|
||||||
|
10
src/main.js
10
src/main.js
@ -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') {
|
if ((typeof exports === 'undefined' ? 'undefined' : _typeof(exports)) === 'object') {
|
||||||
module.exports = xmSelect;
|
module.exports = xmSelect;
|
||||||
|
@ -109,11 +109,13 @@ xm-select{
|
|||||||
}
|
}
|
||||||
.label-content{
|
.label-content{
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&.auto-row{
|
&.auto-row{
|
||||||
.label-content{
|
.label-content{
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
padding-right: 30px !important;
|
||||||
}
|
}
|
||||||
.xm-label-block > span{
|
.xm-label-block > span{
|
||||||
white-space: unset;
|
white-space: unset;
|
||||||
@ -124,7 +126,7 @@ xm-select{
|
|||||||
.scroll{
|
.scroll{
|
||||||
.label-content{
|
.label-content{
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 3px 30px 3px 10px;
|
padding: 3px 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user