v1.1.0
This commit is contained in:
parent
57a0ab9f15
commit
3fcd41969c
32
CHANGELOG.md
32
CHANGELOG.md
@ -1,7 +1,39 @@
|
||||
## 更新日志
|
||||
|
||||
### 1.1.0
|
||||
|
||||
*2019-11-25*
|
||||
|
||||
- 经过了将近一周的测试, 树形结构也趋向于完善阶段, 当然现有的功能并不能满足所有的需求, xm-select将会继续前行
|
||||
|
||||
#### 新增
|
||||
|
||||
- 树形组件
|
||||
- 懒加载
|
||||
- 严格/非严格父子结构
|
||||
- 搜索模式
|
||||
- 新增参数`layVerify`和`layVerType`, 用于表单验证
|
||||
- `el`配置可以指定dom对象
|
||||
- 解决`on`监听时无法使用`setValue`, 增加return处理
|
||||
- 新增远程分页配置`pageRemote`
|
||||
- label也可以自定义渲染
|
||||
- label新增title提示
|
||||
|
||||
#### 调整
|
||||
|
||||
- 移除分组中的optgroup模式
|
||||
- 调整代码文件夹结构
|
||||
- 调整preact版本
|
||||
|
||||
|
||||
### 1.1.0.Beta
|
||||
|
||||
#### 2019-11-25
|
||||
#### 新增
|
||||
|
||||
- 树形组件
|
||||
- [新增]搜索模式
|
||||
|
||||
#### 2019-11-23
|
||||
#### 新增
|
||||
|
||||
|
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
4
dist/static/docs.js
vendored
4
dist/static/docs.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
@ -68,11 +68,14 @@ button, input, select, textarea {
|
||||
font-family: Menlo, Monaco, Consolas, Courier, monospace;
|
||||
font-size: 12px;
|
||||
padding: 18px 24px;
|
||||
background-color: #fafafa;
|
||||
// background-color: #fafafa;
|
||||
border: solid 1px #eaeefb;
|
||||
margin-bottom: 25px;
|
||||
border-radius: 4px;
|
||||
-webkit-font-smoothing: auto;
|
||||
.hljs-tag{
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.main-cnt {
|
||||
@ -261,3 +264,7 @@ button, input, select, textarea {
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.tool_bar{
|
||||
display: none;
|
||||
}
|
||||
|
@ -2,8 +2,11 @@ import "babel-polyfill"
|
||||
import Vue from 'vue';
|
||||
import ElementUI from 'element-ui';
|
||||
import 'element-ui/lib/theme-chalk/index.css';
|
||||
|
||||
import hljs from 'highlight.js';
|
||||
import 'highlight.js/styles/color-brewer.css'
|
||||
// import 'highlight.js/styles/color-brewer.css'
|
||||
import 'highlight.js/styles/monokai-sublime.css'
|
||||
|
||||
import VueRouter from 'vue-router';
|
||||
import routes from './router';
|
||||
import App from './App.vue';
|
||||
|
@ -71,6 +71,7 @@ layui.slider.render({
|
||||
var demo1 = xmSelect.render({
|
||||
el: '#demo1',
|
||||
autoRow: true,
|
||||
filterable: true,
|
||||
tree: {
|
||||
show: true,
|
||||
showFolderIcon: true,
|
||||
@ -78,6 +79,7 @@ var demo1 = xmSelect.render({
|
||||
indent: 20,
|
||||
expandedKeys: [ -3 ],
|
||||
},
|
||||
filterable: true,
|
||||
height: 'auto',
|
||||
data(){
|
||||
return [
|
||||
|
@ -8,7 +8,9 @@
|
||||
var demo1 = xmSelect.render({
|
||||
el: '#demo1',
|
||||
autoRow: true,
|
||||
filterable: true,
|
||||
tree: {
|
||||
strict: false,
|
||||
show: true,
|
||||
showFolderIcon: true,
|
||||
showLine: true,
|
||||
|
@ -20,7 +20,6 @@ class General extends Component{
|
||||
this.searchCid = 0;
|
||||
this.inputOver = true;
|
||||
this.__value = '';
|
||||
this.dynamicInput = false;
|
||||
}
|
||||
|
||||
optionClick(item, selected, disabled, e){
|
||||
|
@ -7,7 +7,12 @@ class Tree extends Component{
|
||||
|
||||
this.state = {
|
||||
expandedKeys: [],
|
||||
filterValue: '',
|
||||
}
|
||||
|
||||
this.searchCid = 0;
|
||||
this.inputOver = true;
|
||||
this.__value = '';
|
||||
}
|
||||
|
||||
init(props){
|
||||
@ -34,10 +39,18 @@ class Tree extends Component{
|
||||
|
||||
optionClick(item, selected, disabled, type, e){
|
||||
if(type === 'line'){
|
||||
//加载中的不需要进行处理
|
||||
if(item.__node.loading === true){
|
||||
return;
|
||||
}
|
||||
|
||||
const { tree, prop, sels } = this.props;
|
||||
|
||||
//不是父节点的不需要处理
|
||||
if(!tree.lazy && !item[prop.optgroup]){
|
||||
return
|
||||
}
|
||||
|
||||
let val = item[this.props.prop.value];
|
||||
let expandedKeys = this.state.expandedKeys;
|
||||
let index = expandedKeys.findIndex(v => v === val);
|
||||
@ -45,13 +58,12 @@ class Tree extends Component{
|
||||
this.setState({ expandedKeys });
|
||||
|
||||
//是否需要懒加载
|
||||
const { tree, prop, sels } = this.props;
|
||||
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] = result;
|
||||
item[prop.children] = this.handlerData(result, prop.children);
|
||||
item[prop.selected] = sels.findIndex(i => i[prop.value] === item[prop.value]) != -1
|
||||
this.props.onReset(item, 'treeData');
|
||||
});
|
||||
@ -63,9 +75,93 @@ class Tree extends Component{
|
||||
this.blockClick(e);
|
||||
}
|
||||
|
||||
handlerData(data, children){
|
||||
return data.map(item => {
|
||||
item.__node = {};
|
||||
if(item[children]){
|
||||
item[children] = this.handlerData(item[children], children);
|
||||
}
|
||||
return item;
|
||||
})
|
||||
}
|
||||
|
||||
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 })
|
||||
}, 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);
|
||||
}
|
||||
}
|
||||
|
||||
filterData(data, val){
|
||||
const { prop, filterMethod, tree } = this.props;
|
||||
const { children, optgroup, name, value } = prop;
|
||||
data.forEach((item, index) => {
|
||||
if(item[optgroup]){
|
||||
let child = this.filterData(item[children], val);
|
||||
item.__node.hidn = val ? child.filter(c => !c.__node.hidn).length === 0 : false;
|
||||
if(!item.__node.hidn){
|
||||
let keys = this.state.expandedKeys;
|
||||
if(val && keys.findIndex(key => key === item[value]) === -1){
|
||||
keys.push(item[value]);
|
||||
this.setState({ expandedKeys: keys })
|
||||
}
|
||||
return
|
||||
}
|
||||
if(tree.strict){
|
||||
return
|
||||
}
|
||||
}
|
||||
item.__node.hidn = val ? !filterMethod(val, item, index, prop) : false;
|
||||
});
|
||||
return data;
|
||||
}
|
||||
|
||||
//组件将要接收新属性
|
||||
componentWillReceiveProps(props){
|
||||
// this.init(props);
|
||||
if(this.props.show != props.show){
|
||||
if(!props.show){
|
||||
//清空输入框的值
|
||||
this.setState({ filterValue: '' });
|
||||
this.__value = '';
|
||||
this.searchInputRef && (this.searchInputRef.value = '');
|
||||
}else{
|
||||
//聚焦输入框
|
||||
setTimeout(() => this.focus(), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//组件将要被挂载
|
||||
@ -74,7 +170,7 @@ class Tree extends Component{
|
||||
}
|
||||
|
||||
render(config, { expandedKeys }) {
|
||||
let { prop, empty, sels, theme, radio, template, data, tree } = config;
|
||||
let { prop, empty, sels, theme, radio, template, data, tree, filterable, searchTips } = config;
|
||||
let { name, value, disabled, children } = prop;
|
||||
|
||||
const showIcon = config.model.icon != 'hidden';
|
||||
@ -120,6 +216,10 @@ class Tree extends Component{
|
||||
}
|
||||
|
||||
const renderGroup = (item, indent) => {
|
||||
if(item.__node.hidn){
|
||||
return;
|
||||
}
|
||||
|
||||
const child = item[children];
|
||||
indent = indent + tree.indent
|
||||
if(child){//分组模式
|
||||
@ -136,19 +236,45 @@ class Tree extends Component{
|
||||
return renderItem(item, indent, 0);
|
||||
}
|
||||
|
||||
let arr = data.map(item => renderGroup(item, 10 - tree.indent));
|
||||
//这里处理过滤数据
|
||||
if(filterable){
|
||||
this.filterData(data, this.state.filterValue);
|
||||
}
|
||||
|
||||
let arr = data.map(item => renderGroup(item, 10 - tree.indent)).filter(a => a);
|
||||
|
||||
if(!arr.length){
|
||||
//查看无数据情况下是否显示分页
|
||||
arr.push(<div class="xm-select-empty">{ empty }</div>)
|
||||
}
|
||||
|
||||
const search = (
|
||||
<div class='xm-search'>
|
||||
<i class="xm-iconfont xm-icon-sousuo"></i>
|
||||
<input class="xm-input xm-search-input" placeholder={ searchTips } />
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div onClick={ this.blockClick } class="xm-body-tree" >
|
||||
{ filterable && search }
|
||||
<div class="scroll-body" style={ {maxHeight: config.height} }>{ arr }</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
//组件完成挂载
|
||||
componentDidMount(){
|
||||
let input = this.base.querySelector('.xm-search-input');
|
||||
if(input){
|
||||
input.addEventListener('compositionstart', this.handleComposition.bind(this));
|
||||
input.addEventListener('compositionupdate', this.handleComposition.bind(this));
|
||||
input.addEventListener('compositionend', this.handleComposition.bind(this));
|
||||
input.addEventListener('input', this.searchInput.bind(this));
|
||||
this.searchInputRef = input;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default Tree;
|
||||
|
@ -156,7 +156,6 @@ class xmOptions {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
export default xmOptions;
|
||||
|
Loading…
Reference in New Issue
Block a user