修复tree模式的节点显示异常
This commit is contained in:
parent
1175612369
commit
ca9453469e
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,4 +1,5 @@
|
|||||||
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
node_modules/*
|
node_modules/*
|
||||||
yarn.lock
|
yarn.lock
|
||||||
|
*.zip
|
15
CHANGELOG.md
15
CHANGELOG.md
@ -1,5 +1,20 @@
|
|||||||
## 更新日志
|
## 更新日志
|
||||||
|
|
||||||
|
### 1.2.1
|
||||||
|
|
||||||
|
*2020-11-27*
|
||||||
|
|
||||||
|
#### 新增
|
||||||
|
|
||||||
|
- 新增配置`enableKeyboard`, 用于控制是否使用键盘操作, 用于取消因为键盘事件带来的性能影响
|
||||||
|
- tree模式新增配置`clickExpand`, 是否点击节点即展开节点
|
||||||
|
- tree模式新增配置`clickCheck`, 是否点击节点即选中节点
|
||||||
|
|
||||||
|
#### Bug fixes
|
||||||
|
|
||||||
|
- [紧急修复]tree模式下节点超过2层, 父节点半选状态异常
|
||||||
|
|
||||||
|
|
||||||
### 1.2.0
|
### 1.2.0
|
||||||
|
|
||||||
*2020-11-26*
|
*2020-11-26*
|
||||||
|
2
dist/static/2.js
vendored
2
dist/static/2.js
vendored
File diff suppressed because one or more lines are too long
2
dist/static/3.js
vendored
2
dist/static/3.js
vendored
File diff suppressed because one or more lines are too long
2
dist/xm-select.js
vendored
2
dist/xm-select.js
vendored
File diff suppressed because one or more lines are too long
@ -20,6 +20,10 @@ tree: {
|
|||||||
strict: true,
|
strict: true,
|
||||||
//是否开启极简模式
|
//是否开启极简模式
|
||||||
simple: false,
|
simple: false,
|
||||||
|
//点击节点是否展开
|
||||||
|
clickExpand: true,
|
||||||
|
//点击节点是否选中
|
||||||
|
clickCheck: true,
|
||||||
},
|
},
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -42,6 +46,11 @@ tree: {
|
|||||||
<input type="checkbox" name="all" lay-filter="all" lay-skin="primary" title="展开所有节点">
|
<input type="checkbox" name="all" lay-filter="all" lay-skin="primary" title="展开所有节点">
|
||||||
<input type="checkbox" name="close" lay-filter="close" lay-skin="primary" title="闭合所有节点">
|
<input type="checkbox" name="close" lay-filter="close" lay-skin="primary" title="闭合所有节点">
|
||||||
<input type="checkbox" name="key3" lay-filter="key3" lay-skin="primary" title="展开指定节点">
|
<input type="checkbox" name="key3" lay-filter="key3" lay-skin="primary" title="展开指定节点">
|
||||||
|
|
||||||
|
<br/><br/>
|
||||||
|
<input type="checkbox" name="clickExpand" lay-filter="clickExpand" lay-skin="primary" title="clickExpand" checked>
|
||||||
|
<input type="checkbox" name="clickCheck" lay-filter="clickCheck" lay-skin="primary" title="clickExpand" checked>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="margin-top: 20px">间距</div>
|
<div style="margin-top: 20px">间距</div>
|
||||||
@ -110,6 +119,22 @@ layui.form.on('checkbox(key3)', function(data){
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
layui.form.on('checkbox(clickExpand)', function(data){
|
||||||
|
demo1.update({
|
||||||
|
tree: {
|
||||||
|
clickExpand: data.elem.checked
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
layui.form.on('checkbox(clickCheck)', function(data){
|
||||||
|
demo1.update({
|
||||||
|
tree: {
|
||||||
|
clickCheck: data.elem.checked
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
layui.slider.render({
|
layui.slider.render({
|
||||||
elem: '#slideTest1',
|
elem: '#slideTest1',
|
||||||
min: 10,
|
min: 10,
|
||||||
|
@ -16,6 +16,8 @@ var demo1 = xmSelect.render({
|
|||||||
indent: 20,
|
indent: 20,
|
||||||
expandedKeys: [ -3 ],
|
expandedKeys: [ -3 ],
|
||||||
simple: true,
|
simple: true,
|
||||||
|
clickExpand: false,
|
||||||
|
clickCheck: false,
|
||||||
},
|
},
|
||||||
toolbar: {
|
toolbar: {
|
||||||
show: true,
|
show: true,
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
| layReqText | 表单验证, 同layui的lay-reqText | string | - | '' |
|
| layReqText | 表单验证, 同layui的lay-reqText | string | - | '' |
|
||||||
| toolbar | 工具条, 具体看下表 | object | - | - |
|
| toolbar | 工具条, 具体看下表 | object | - | - |
|
||||||
| showCount | 展示在下拉框中的最多选项数量 | int | - | 0 |
|
| showCount | 展示在下拉框中的最多选项数量 | int | - | 0 |
|
||||||
|
| enableKeyboard | 是否启用键盘操作选项 | boolean | true / false | true |
|
||||||
| autoRow | 是否开启自动换行(选项过多时) | boolean | true / false | false |
|
| autoRow | 是否开启自动换行(选项过多时) | boolean | true / false | false |
|
||||||
| size | 尺寸 | string | large / medium / small / mini | medium |
|
| size | 尺寸 | string | large / medium / small / mini | medium |
|
||||||
| disabled | 是否禁用多选 | boolean | true / false | false |
|
| disabled | 是否禁用多选 | boolean | true / false | false |
|
||||||
@ -189,6 +190,8 @@ list: [ "ALL", "CLEAR",
|
|||||||
| strict | 是否遵循严格父子结构 | boolean | true / false | true |
|
| strict | 是否遵循严格父子结构 | boolean | true / false | true |
|
||||||
| simple | 是否开启极简模式 | boolean | true / false | false |
|
| simple | 是否开启极简模式 | boolean | true / false | false |
|
||||||
| nodeType | 标注节点类型的key | string | leaf: 叶子节点, parent: 父节点, half: 半选节点 | __node_type |
|
| nodeType | 标注节点类型的key | string | leaf: 叶子节点, parent: 父节点, half: 半选节点 | __node_type |
|
||||||
|
| clickExpand | 点击节点是否展开, false时点击三角箭头进行展开操作| boolean | true / false | true |
|
||||||
|
| clickCheck | 点击节点是否选中, false时点击复选框进行选中操作 | boolean | true / false | true |
|
||||||
|
|
||||||
|
|
||||||
### cascader
|
### cascader
|
||||||
|
@ -193,7 +193,7 @@ class Framework extends Component{
|
|||||||
let child = parent[children];
|
let child = parent[children];
|
||||||
child.filter(item => !(item[disabled] || item.__node.disabled)).forEach(item => {
|
child.filter(item => !(item[disabled] || item.__node.disabled)).forEach(item => {
|
||||||
if(item[optgroup]){
|
if(item[optgroup]){
|
||||||
this.treeHandler(sels, item, change, type);
|
this.treeHandler(sels, item, change, type, changeStatus);
|
||||||
}else{
|
}else{
|
||||||
let index = sels.findIndex(sel => sel[value] == item[value])
|
let index = sels.findIndex(sel => sel[value] == item[value])
|
||||||
if(type === 'del'){
|
if(type === 'del'){
|
||||||
@ -255,9 +255,11 @@ class Framework extends Component{
|
|||||||
}else{
|
}else{
|
||||||
handlerType = 'add';
|
handlerType = 'add';
|
||||||
}
|
}
|
||||||
|
|
||||||
if(handlerType != 'half'){
|
if(handlerType != 'half'){
|
||||||
this.treeHandler(sels, item, change, handlerType);
|
this.treeHandler(sels, item, change, handlerType);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.checkMax(change, change)){
|
if(this.checkMax(change, change)){
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
@ -117,6 +117,8 @@ class Label extends Component{
|
|||||||
this.props.onReset(e, 'labelSearch')
|
this.props.onReset(e, 'labelSearch')
|
||||||
}} compositionend={ e => {
|
}} compositionend={ e => {
|
||||||
this.props.onReset(e, 'labelSearch')
|
this.props.onReset(e, 'labelSearch')
|
||||||
|
}} onClick={ e => {
|
||||||
|
e.stopPropagation();
|
||||||
}}></input>
|
}}></input>
|
||||||
)
|
)
|
||||||
}else{
|
}else{
|
||||||
|
@ -164,46 +164,48 @@ class General extends Component{
|
|||||||
this.pageNextClick();
|
this.pageNextClick();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const { value, optgroup, disabled } = this.props.prop;
|
if(this.props.enableKeyboard){
|
||||||
let data = this.tempData.filter(item => !item[optgroup] && !item[disabled]);
|
const { value, optgroup, disabled } = this.props.prop;
|
||||||
let len = data.length - 1;
|
let data = this.tempData.filter(item => !item[optgroup] && !item[disabled]);
|
||||||
if(len === -1){
|
let len = data.length - 1;
|
||||||
return ;
|
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 })
|
let index = data.findIndex(item => item[value] === this.state.val);
|
||||||
//键盘选中时滚动到可视范围内
|
//Up 键
|
||||||
let opt = this.base.querySelector(`.xm-option[value="${ val }"]`);
|
if(keyCode === 38){
|
||||||
opt && opt.scrollIntoView(false)
|
if(index <= 0){
|
||||||
}else
|
index = len
|
||||||
//Down 键
|
}else if(index > 0){
|
||||||
if(keyCode === 40){
|
index -= 1;
|
||||||
if(index === -1 || index === len){
|
}
|
||||||
index = 0
|
let val = data[index][value];
|
||||||
}else if(index < len){
|
this.setState({ val })
|
||||||
index += 1;
|
//键盘选中时滚动到可视范围内
|
||||||
}
|
let opt = this.base.querySelector(`.xm-option[value="${ val }"]`);
|
||||||
let val = data[index][value];
|
opt && opt.scrollIntoView(false)
|
||||||
this.setState({ val })
|
}else
|
||||||
//键盘选中时滚动到可视范围内
|
//Down 键
|
||||||
let opt = this.base.querySelector(`.xm-option[value="${ val }"]`);
|
if(keyCode === 40){
|
||||||
opt && opt.scrollIntoView(false)
|
if(index === -1 || index === len){
|
||||||
}else
|
index = 0
|
||||||
//Enter 键
|
}else if(index < len){
|
||||||
if(keyCode === 13){
|
index += 1;
|
||||||
if(this.state.val != emptyVal){
|
}
|
||||||
let option = data[index];
|
let val = data[index][value];
|
||||||
this.optionClick(option, this.props.sels.findIndex(item => item[value] === this.state.val) != -1, option[disabled], e)
|
this.setState({ val })
|
||||||
|
//键盘选中时滚动到可视范围内
|
||||||
|
let opt = this.base.querySelector(`.xm-option[value="${ val }"]`);
|
||||||
|
opt && opt.scrollIntoView(false)
|
||||||
|
}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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,7 +239,7 @@ class General extends Component{
|
|||||||
}
|
}
|
||||||
|
|
||||||
render(config) {
|
render(config) {
|
||||||
let { data, flatData, prop, template, theme, radio, sels, empty, filterable, filterMethod, remoteSearch, remoteMethod, delay, searchTips, create, pageRemote, max } = config
|
let { data, flatData, prop, template, theme, radio, sels, empty, filterable, filterMethod, remoteSearch, remoteMethod, delay, searchTips, create, pageRemote, max, enableKeyboard } = config
|
||||||
|
|
||||||
const { name, value, disabled, children, optgroup } = prop;
|
const { name, value, disabled, children, optgroup } = prop;
|
||||||
|
|
||||||
@ -451,7 +453,7 @@ class General extends Component{
|
|||||||
const itemStyle = {}
|
const itemStyle = {}
|
||||||
|
|
||||||
//处理键盘的选择背景色
|
//处理键盘的选择背景色
|
||||||
if(item[value] === this.state.val){
|
if(enableKeyboard && item[value] === this.state.val){
|
||||||
itemStyle.backgroundColor = theme.hover
|
itemStyle.backgroundColor = theme.hover
|
||||||
}
|
}
|
||||||
//不显示图标时候的背景色处理
|
//不显示图标时候的背景色处理
|
||||||
@ -473,7 +475,19 @@ class General extends Component{
|
|||||||
const hoverChange = e => {
|
const hoverChange = e => {
|
||||||
if(e.type === 'mouseenter'){
|
if(e.type === 'mouseenter'){
|
||||||
if(!item[disabled]){
|
if(!item[disabled]){
|
||||||
this.setState({ val: item[value] })
|
if(enableKeyboard){
|
||||||
|
this.setState({ val: item[value] })
|
||||||
|
}else{
|
||||||
|
e.target.style.backgroundColor = theme.hover;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else if(e.type === 'mouseleave'){
|
||||||
|
if(!item[disabled]){
|
||||||
|
if(enableKeyboard){
|
||||||
|
|
||||||
|
}else{
|
||||||
|
e.target.style.backgroundColor = '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,31 +58,43 @@ class Tree extends Component{
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { tree, prop, sels } = this.props;
|
const { tree, prop, sels } = this.props;
|
||||||
|
const { clickExpand, clickCheck } = tree;
|
||||||
|
|
||||||
|
//检测点击的是不是三角箭头
|
||||||
|
let isExpand = e.target && isFunction(e.target.getAttribute) && e.target.getAttribute('type') === 'expand'
|
||||||
|
//如果点击即展开
|
||||||
|
if(clickExpand || isExpand){
|
||||||
|
//不是父节点的不需要处理
|
||||||
|
if(!tree.lazy && !item[prop.optgroup]){
|
||||||
|
this.props.ck(item, selected, disabled);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
//不是父节点的不需要处理
|
let val = item[this.props.prop.value];
|
||||||
if(!tree.lazy && !item[prop.optgroup]){
|
let expandedKeys = this.state.expandedKeys;
|
||||||
this.props.ck(item, selected, disabled);
|
let index = expandedKeys.findIndex(v => v === val);
|
||||||
return
|
index === -1 ? expandedKeys.push(val) : expandedKeys.splice(index, 1);
|
||||||
|
this.setState({ expandedKeys });
|
||||||
|
|
||||||
|
//是否需要懒加载
|
||||||
|
let child = item[prop.children];
|
||||||
|
if(tree.lazy && child && child.length === 0 && item.__node.loading !== false){
|
||||||
|
item.__node.loading = true;
|
||||||
|
tree.load(item, (result) => {
|
||||||
|
item.__node.loading = false;
|
||||||
|
item[prop.children] = this.handlerData(result, prop.children);
|
||||||
|
item[prop.selected] = sels.findIndex(i => i[prop.value] === item[prop.value]) != -1
|
||||||
|
this.props.onReset(sels, 'treeData');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if(clickCheck){
|
||||||
|
type = 'checkbox'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let val = item[this.props.prop.value];
|
if(type === 'checkbox'){
|
||||||
let expandedKeys = this.state.expandedKeys;
|
|
||||||
let index = expandedKeys.findIndex(v => v === val);
|
|
||||||
index === -1 ? expandedKeys.push(val) : expandedKeys.splice(index, 1);
|
|
||||||
this.setState({ expandedKeys });
|
|
||||||
|
|
||||||
//是否需要懒加载
|
|
||||||
let child = item[prop.children];
|
|
||||||
if(tree.lazy && child && child.length === 0 && item.__node.loading !== false){
|
|
||||||
item.__node.loading = true;
|
|
||||||
tree.load(item, (result) => {
|
|
||||||
item.__node.loading = false;
|
|
||||||
item[prop.children] = this.handlerData(result, prop.children);
|
|
||||||
item[prop.selected] = sels.findIndex(i => i[prop.value] === item[prop.value]) != -1
|
|
||||||
this.props.onReset(sels, 'treeData');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}else if(type === 'checkbox'){
|
|
||||||
this.props.ck(item, selected, disabled);
|
this.props.ck(item, selected, disabled);
|
||||||
}
|
}
|
||||||
//阻止父组件上的事件冒泡
|
//阻止父组件上的事件冒泡
|
||||||
@ -218,7 +230,7 @@ class Tree extends Component{
|
|||||||
}
|
}
|
||||||
|
|
||||||
render(config, { expandedKeys }) {
|
render(config, { expandedKeys }) {
|
||||||
let { prop, empty, sels, theme, radio, template, data, tree, filterable, remoteSearch, searchTips, iconfont } = config;
|
let { prop, empty, sels, theme, radio, template, data, tree, filterable, remoteSearch, searchTips, iconfont, enableKeyboard } = config;
|
||||||
let { name, value, disabled, children, optgroup } = prop;
|
let { name, value, disabled, children, optgroup } = prop;
|
||||||
|
|
||||||
let showIcon = config.model.icon != 'hidden';
|
let showIcon = config.model.icon != 'hidden';
|
||||||
@ -246,7 +258,7 @@ class Tree extends Component{
|
|||||||
const itemStyle = { paddingLeft: indent + 'px' }
|
const itemStyle = { paddingLeft: indent + 'px' }
|
||||||
|
|
||||||
//处理键盘的选择背景色
|
//处理键盘的选择背景色
|
||||||
if(item[value] === this.state.val){
|
if(enableKeyboard && item[value] === this.state.val){
|
||||||
itemStyle.backgroundColor = theme.hover
|
itemStyle.backgroundColor = theme.hover
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,7 +291,7 @@ class Tree extends Component{
|
|||||||
|
|
||||||
const iconArray = [];
|
const iconArray = [];
|
||||||
if(tree.showFolderIcon){
|
if(tree.showFolderIcon){
|
||||||
iconArray.push(<i class={ treeIconClass }></i>);
|
iconArray.push(<i class={ treeIconClass } type="expand"></i>);
|
||||||
if(tree.showLine){
|
if(tree.showLine){
|
||||||
if(expand){
|
if(expand){
|
||||||
iconArray.push(<i class='left-line' style={ {left: indent - tree.indent + 3 + 'px'} }></i>)
|
iconArray.push(<i class='left-line' style={ {left: indent - tree.indent + 3 + 'px'} }></i>)
|
||||||
@ -293,7 +305,19 @@ class Tree extends Component{
|
|||||||
const hoverChange = e => {
|
const hoverChange = e => {
|
||||||
if(e.type === 'mouseenter'){
|
if(e.type === 'mouseenter'){
|
||||||
if(!item[disabled]){
|
if(!item[disabled]){
|
||||||
this.setState({ val: item[value] })
|
if(enableKeyboard){
|
||||||
|
this.setState({ val: item[value] })
|
||||||
|
}else{
|
||||||
|
e.target.style.backgroundColor = theme.hover;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else if(e.type === 'mouseleave'){
|
||||||
|
if(!item[disabled]){
|
||||||
|
if(enableKeyboard){
|
||||||
|
|
||||||
|
}else{
|
||||||
|
e.target.style.backgroundColor = '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -349,7 +373,6 @@ class Tree extends Component{
|
|||||||
|
|
||||||
//工具条操作
|
//工具条操作
|
||||||
function flat(list, array){
|
function flat(list, array){
|
||||||
//array.forEach(item => item[optgroup] ? (!tree.strict && list.push(item), flat(list, item[children])) : list.push(item))
|
|
||||||
array.forEach(item => {
|
array.forEach(item => {
|
||||||
if(item[optgroup]){
|
if(item[optgroup]){
|
||||||
//非严格模式, 如果隐藏父节点, 证明不可选
|
//非严格模式, 如果隐藏父节点, 证明不可选
|
||||||
|
@ -78,7 +78,9 @@ export default function (lan = 'zn') {
|
|||||||
max: 0,
|
max: 0,
|
||||||
maxMethod: function(sels, item){},
|
maxMethod: function(sels, item){},
|
||||||
//选项显示数量
|
//选项显示数量
|
||||||
showCount: 0,
|
showCount: 0,
|
||||||
|
//是否开启键盘操作
|
||||||
|
enableKeyboard: true,
|
||||||
//工具条
|
//工具条
|
||||||
toolbar: {
|
toolbar: {
|
||||||
show: false,
|
show: false,
|
||||||
@ -106,7 +108,11 @@ export default function (lan = 'zn') {
|
|||||||
//是否开启极简模式
|
//是否开启极简模式
|
||||||
simple: false,
|
simple: false,
|
||||||
//标注节点类型的key
|
//标注节点类型的key
|
||||||
nodeType: '__node_type',
|
nodeType: '__node_type',
|
||||||
|
//点击节点是否展开
|
||||||
|
clickExpand: true,
|
||||||
|
//点击节点是否选中
|
||||||
|
clickCheck: true,
|
||||||
},
|
},
|
||||||
//级联结构
|
//级联结构
|
||||||
cascader: {
|
cascader: {
|
||||||
|
Loading…
Reference in New Issue
Block a user