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
|
### 1.1.0.Beta
|
||||||
|
|
||||||
|
#### 2019-11-25
|
||||||
|
#### 新增
|
||||||
|
|
||||||
|
- 树形组件
|
||||||
|
- [新增]搜索模式
|
||||||
|
|
||||||
#### 2019-11-23
|
#### 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-family: Menlo, Monaco, Consolas, Courier, monospace;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
padding: 18px 24px;
|
padding: 18px 24px;
|
||||||
background-color: #fafafa;
|
// background-color: #fafafa;
|
||||||
border: solid 1px #eaeefb;
|
border: solid 1px #eaeefb;
|
||||||
margin-bottom: 25px;
|
margin-bottom: 25px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
-webkit-font-smoothing: auto;
|
-webkit-font-smoothing: auto;
|
||||||
|
.hljs-tag{
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-cnt {
|
.main-cnt {
|
||||||
@ -261,3 +264,7 @@ button, input, select, textarea {
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tool_bar{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
import "babel-polyfill"
|
import "babel-polyfill"
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import ElementUI from 'element-ui';
|
import ElementUI from 'element-ui';
|
||||||
import 'element-ui/lib/theme-chalk/index.css';
|
import 'element-ui/lib/theme-chalk/index.css';
|
||||||
|
|
||||||
import hljs from 'highlight.js';
|
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 VueRouter from 'vue-router';
|
||||||
import routes from './router';
|
import routes from './router';
|
||||||
import App from './App.vue';
|
import App from './App.vue';
|
||||||
|
@ -71,6 +71,7 @@ layui.slider.render({
|
|||||||
var demo1 = xmSelect.render({
|
var demo1 = xmSelect.render({
|
||||||
el: '#demo1',
|
el: '#demo1',
|
||||||
autoRow: true,
|
autoRow: true,
|
||||||
|
filterable: true,
|
||||||
tree: {
|
tree: {
|
||||||
show: true,
|
show: true,
|
||||||
showFolderIcon: true,
|
showFolderIcon: true,
|
||||||
@ -78,6 +79,7 @@ var demo1 = xmSelect.render({
|
|||||||
indent: 20,
|
indent: 20,
|
||||||
expandedKeys: [ -3 ],
|
expandedKeys: [ -3 ],
|
||||||
},
|
},
|
||||||
|
filterable: true,
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
data(){
|
data(){
|
||||||
return [
|
return [
|
||||||
|
@ -8,7 +8,9 @@
|
|||||||
var demo1 = xmSelect.render({
|
var demo1 = xmSelect.render({
|
||||||
el: '#demo1',
|
el: '#demo1',
|
||||||
autoRow: true,
|
autoRow: true,
|
||||||
|
filterable: true,
|
||||||
tree: {
|
tree: {
|
||||||
|
strict: false,
|
||||||
show: true,
|
show: true,
|
||||||
showFolderIcon: true,
|
showFolderIcon: true,
|
||||||
showLine: true,
|
showLine: true,
|
||||||
|
@ -20,7 +20,6 @@ class General extends Component{
|
|||||||
this.searchCid = 0;
|
this.searchCid = 0;
|
||||||
this.inputOver = true;
|
this.inputOver = true;
|
||||||
this.__value = '';
|
this.__value = '';
|
||||||
this.dynamicInput = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
optionClick(item, selected, disabled, e){
|
optionClick(item, selected, disabled, e){
|
||||||
|
@ -7,7 +7,12 @@ class Tree extends Component{
|
|||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
expandedKeys: [],
|
expandedKeys: [],
|
||||||
|
filterValue: '',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.searchCid = 0;
|
||||||
|
this.inputOver = true;
|
||||||
|
this.__value = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
init(props){
|
init(props){
|
||||||
@ -34,10 +39,18 @@ class Tree extends Component{
|
|||||||
|
|
||||||
optionClick(item, selected, disabled, type, e){
|
optionClick(item, selected, disabled, type, e){
|
||||||
if(type === 'line'){
|
if(type === 'line'){
|
||||||
|
//加载中的不需要进行处理
|
||||||
if(item.__node.loading === true){
|
if(item.__node.loading === true){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { tree, prop, sels } = this.props;
|
||||||
|
|
||||||
|
//不是父节点的不需要处理
|
||||||
|
if(!tree.lazy && !item[prop.optgroup]){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
let val = item[this.props.prop.value];
|
let val = item[this.props.prop.value];
|
||||||
let expandedKeys = this.state.expandedKeys;
|
let expandedKeys = this.state.expandedKeys;
|
||||||
let index = expandedKeys.findIndex(v => v === val);
|
let index = expandedKeys.findIndex(v => v === val);
|
||||||
@ -45,13 +58,12 @@ class Tree extends Component{
|
|||||||
this.setState({ expandedKeys });
|
this.setState({ expandedKeys });
|
||||||
|
|
||||||
//是否需要懒加载
|
//是否需要懒加载
|
||||||
const { tree, prop, sels } = this.props;
|
|
||||||
let child = item[prop.children];
|
let child = item[prop.children];
|
||||||
if(tree.lazy && child && child.length === 0 && item.__node.loading !== false){
|
if(tree.lazy && child && child.length === 0 && item.__node.loading !== false){
|
||||||
item.__node.loading = true;
|
item.__node.loading = true;
|
||||||
tree.load(item, (result) => {
|
tree.load(item, (result) => {
|
||||||
item.__node.loading = false;
|
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
|
item[prop.selected] = sels.findIndex(i => i[prop.value] === item[prop.value]) != -1
|
||||||
this.props.onReset(item, 'treeData');
|
this.props.onReset(item, 'treeData');
|
||||||
});
|
});
|
||||||
@ -63,9 +75,93 @@ class Tree extends Component{
|
|||||||
this.blockClick(e);
|
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){
|
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 }) {
|
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;
|
let { name, value, disabled, children } = prop;
|
||||||
|
|
||||||
const showIcon = config.model.icon != 'hidden';
|
const showIcon = config.model.icon != 'hidden';
|
||||||
@ -120,6 +216,10 @@ class Tree extends Component{
|
|||||||
}
|
}
|
||||||
|
|
||||||
const renderGroup = (item, indent) => {
|
const renderGroup = (item, indent) => {
|
||||||
|
if(item.__node.hidn){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const child = item[children];
|
const child = item[children];
|
||||||
indent = indent + tree.indent
|
indent = indent + tree.indent
|
||||||
if(child){//分组模式
|
if(child){//分组模式
|
||||||
@ -136,19 +236,45 @@ class Tree extends Component{
|
|||||||
return renderItem(item, indent, 0);
|
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){
|
if(!arr.length){
|
||||||
//查看无数据情况下是否显示分页
|
//查看无数据情况下是否显示分页
|
||||||
arr.push(<div class="xm-select-empty">{ empty }</div>)
|
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 (
|
return (
|
||||||
<div onClick={ this.blockClick } class="xm-body-tree" >
|
<div onClick={ this.blockClick } class="xm-body-tree" >
|
||||||
|
{ filterable && search }
|
||||||
<div class="scroll-body" style={ {maxHeight: config.height} }>{ arr }</div>
|
<div class="scroll-body" style={ {maxHeight: config.height} }>{ arr }</div>
|
||||||
</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;
|
export default Tree;
|
||||||
|
@ -3,7 +3,7 @@ import { datas, optionData, childData } from '@/index.js';
|
|||||||
import { selector, warn, listenerClose, isArray, deepMerge, exchangeOptionsData } from '@/common/util'
|
import { selector, warn, listenerClose, isArray, deepMerge, exchangeOptionsData } from '@/common/util'
|
||||||
import Framework from '@/components/framework'
|
import Framework from '@/components/framework'
|
||||||
import defaultOptions from '@/config/options'
|
import defaultOptions from '@/config/options'
|
||||||
|
|
||||||
class xmOptions {
|
class xmOptions {
|
||||||
|
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
@ -156,7 +156,6 @@ class xmOptions {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default xmOptions;
|
export default xmOptions;
|
||||||
|
Loading…
Reference in New Issue
Block a user