feat: update autocomplete
parent
5e80e8019e
commit
ad6f343376
|
@ -2,6 +2,7 @@ import isPlainObject from 'lodash/isPlainObject';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { isVNode, Fragment, Comment, Text } from 'vue';
|
import { isVNode, Fragment, Comment, Text } from 'vue';
|
||||||
import { camelize, hyphenate, isOn, resolvePropValue } from './util';
|
import { camelize, hyphenate, isOn, resolvePropValue } from './util';
|
||||||
|
import isValid from './isValid';
|
||||||
// function getType(fn) {
|
// function getType(fn) {
|
||||||
// const match = fn && fn.toString().match(/^\s*function (\w+)/);
|
// const match = fn && fn.toString().match(/^\s*function (\w+)/);
|
||||||
// return match ? match[1] : '';
|
// return match ? match[1] : '';
|
||||||
|
@ -82,6 +83,8 @@ const flattenChildren = (children = [], filterEmpty = true) => {
|
||||||
} else if (!filterEmpty) {
|
} else if (!filterEmpty) {
|
||||||
res.push(child);
|
res.push(child);
|
||||||
}
|
}
|
||||||
|
} else if (isValid(child)) {
|
||||||
|
res.push(child);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return res;
|
return res;
|
||||||
|
|
|
@ -1,53 +1,59 @@
|
||||||
import PropTypes from '../_util/vue-types';
|
|
||||||
import { cloneElement } from '../_util/vnode';
|
import { cloneElement } from '../_util/vnode';
|
||||||
import { getOptionProps, getListeners } from '../_util/props-util';
|
import { flattenChildren } from '../_util/props-util';
|
||||||
function chaining(...fns) {
|
// function chaining(...fns) {
|
||||||
return function(...args) {
|
// return function(...args) {
|
||||||
// eslint-disable-line
|
// // eslint-disable-line
|
||||||
// eslint-disable-line
|
// // eslint-disable-line
|
||||||
for (let i = 0; i < fns.length; i++) {
|
// for (let i = 0; i < fns.length; i++) {
|
||||||
if (fns[i] && typeof fns[i] === 'function') {
|
// if (fns[i] && typeof fns[i] === 'function') {
|
||||||
fns[i].apply(this, args);
|
// fns[i].apply(this, args);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
}
|
// }
|
||||||
export default {
|
// export default {
|
||||||
name: 'InputElement',
|
// name: 'InputElement',
|
||||||
inheritAttrs: false,
|
// inheritAttrs: false,
|
||||||
props: {
|
// props: {
|
||||||
value: PropTypes.any,
|
// value: PropTypes.any,
|
||||||
disabled: PropTypes.bool,
|
// disabled: PropTypes.bool,
|
||||||
placeholder: PropTypes.string,
|
// placeholder: PropTypes.string,
|
||||||
},
|
// },
|
||||||
render() {
|
// render() {
|
||||||
const { $slots = {}, $attrs = {}, placeholder } = this;
|
// const { $slots = {}, $attrs = {}, placeholder } = this;
|
||||||
const listeners = getListeners(this);
|
// const listeners = getListeners(this);
|
||||||
const props = getOptionProps(this);
|
// const props = getOptionProps(this);
|
||||||
const value = props.value === undefined ? '' : props.value;
|
// const value = props.value === undefined ? '' : props.value;
|
||||||
const children = $slots.default[0];
|
// const children = getSlot(this)[0];
|
||||||
const { componentOptions = {} } = $slots.default[0];
|
// const { componentOptions = {} } = $slots.default[0];
|
||||||
const { listeners: events = {} } = componentOptions;
|
// const { listeners: events = {} } = componentOptions;
|
||||||
const newEvent = { ...events };
|
// const newEvent = { ...events };
|
||||||
|
|
||||||
for (const [eventName, event] of Object.entries(listeners)) {
|
// for (const [eventName, event] of Object.entries(listeners)) {
|
||||||
newEvent[eventName] = chaining(event, events[eventName]);
|
// newEvent[eventName] = chaining(event, events[eventName]);
|
||||||
}
|
// }
|
||||||
const attrs = { ...$attrs, value };
|
// const attrs = { ...$attrs, value };
|
||||||
// https://github.com/vueComponent/ant-design-vue/issues/1761
|
// // https://github.com/vueComponent/ant-design-vue/issues/1761
|
||||||
delete props.placeholder;
|
// delete props.placeholder;
|
||||||
if (placeholder) {
|
// if (placeholder) {
|
||||||
props.placeholder = placeholder;
|
// props.placeholder = placeholder;
|
||||||
attrs.placeholder = placeholder;
|
// attrs.placeholder = placeholder;
|
||||||
}
|
// }
|
||||||
return cloneElement(children, {
|
// return cloneElement(children, {
|
||||||
domProps: {
|
// domProps: {
|
||||||
value,
|
// value,
|
||||||
},
|
// },
|
||||||
props,
|
// props,
|
||||||
on: newEvent,
|
// on: newEvent,
|
||||||
attrs,
|
// attrs,
|
||||||
ref: 'ele',
|
// ref: 'ele',
|
||||||
});
|
// });
|
||||||
},
|
// },
|
||||||
|
// };
|
||||||
|
|
||||||
|
const InputElement = (_, { attrs, slots }) => {
|
||||||
|
const children = flattenChildren(slots.default?.())[0];
|
||||||
|
return cloneElement(children, { ...attrs });
|
||||||
};
|
};
|
||||||
|
InputElement.inheritAttrs = false;
|
||||||
|
export default InputElement;
|
||||||
|
|
|
@ -1,17 +1,11 @@
|
||||||
|
import { inject, provide } from 'vue';
|
||||||
import { Option, OptGroup } from '../vc-select';
|
import { Option, OptGroup } from '../vc-select';
|
||||||
import Select, { AbstractSelectProps, SelectValue } from '../select';
|
import Select, { AbstractSelectProps, SelectValue } from '../select';
|
||||||
import Input from '../input';
|
import Input from '../input';
|
||||||
import InputElement from './InputElement';
|
import InputElement from './InputElement';
|
||||||
import PropTypes from '../_util/vue-types';
|
import PropTypes from '../_util/vue-types';
|
||||||
import { ConfigConsumerProps } from '../config-provider';
|
import { ConfigConsumerProps } from '../config-provider';
|
||||||
import {
|
import { getComponent, getOptionProps, isValidElement, getSlot } from '../_util/props-util';
|
||||||
getComponentFromProp,
|
|
||||||
getOptionProps,
|
|
||||||
filterEmpty,
|
|
||||||
isValidElement,
|
|
||||||
getListeners,
|
|
||||||
} from '../_util/props-util';
|
|
||||||
import Base from '../base';
|
|
||||||
|
|
||||||
// const DataSourceItemObject = PropTypes.shape({
|
// const DataSourceItemObject = PropTypes.shape({
|
||||||
// value: String,
|
// value: String,
|
||||||
|
@ -26,6 +20,9 @@ import Base from '../base';
|
||||||
// onChange?: React.FormEventHandler<any>;
|
// onChange?: React.FormEventHandler<any>;
|
||||||
// value: any;
|
// value: any;
|
||||||
// }
|
// }
|
||||||
|
function isSelectOptionOrSelectOptGroup(child) {
|
||||||
|
return child && child.type && (child.type.isSelectOption || child.type.isSelectOptGroup);
|
||||||
|
}
|
||||||
|
|
||||||
const AutoCompleteProps = {
|
const AutoCompleteProps = {
|
||||||
...AbstractSelectProps(),
|
...AbstractSelectProps(),
|
||||||
|
@ -41,6 +38,7 @@ const AutoCompleteProps = {
|
||||||
|
|
||||||
const AutoComplete = {
|
const AutoComplete = {
|
||||||
name: 'AAutoComplete',
|
name: 'AAutoComplete',
|
||||||
|
inheritAttrs: false,
|
||||||
props: {
|
props: {
|
||||||
...AutoCompleteProps,
|
...AutoCompleteProps,
|
||||||
prefixCls: PropTypes.string.def('ant-select'),
|
prefixCls: PropTypes.string.def('ant-select'),
|
||||||
|
@ -55,50 +53,53 @@ const AutoComplete = {
|
||||||
},
|
},
|
||||||
Option: { ...Option, name: 'AAutoCompleteOption' },
|
Option: { ...Option, name: 'AAutoCompleteOption' },
|
||||||
OptGroup: { ...OptGroup, name: 'AAutoCompleteOptGroup' },
|
OptGroup: { ...OptGroup, name: 'AAutoCompleteOptGroup' },
|
||||||
model: {
|
// model: {
|
||||||
prop: 'value',
|
// prop: 'value',
|
||||||
event: 'change',
|
// event: 'change',
|
||||||
},
|
// },
|
||||||
inject: {
|
setup() {
|
||||||
configProvider: { default: () => ConfigConsumerProps },
|
|
||||||
},
|
|
||||||
provide() {
|
|
||||||
return {
|
return {
|
||||||
savePopupRef: this.savePopupRef,
|
configProvider: inject('configProvider', ConfigConsumerProps),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
created() {
|
||||||
|
provide('savePopupRef', this.savePopupRef);
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
savePopupRef(ref) {
|
savePopupRef(ref) {
|
||||||
this.popupRef = ref;
|
this.popupRef = ref;
|
||||||
},
|
},
|
||||||
|
saveSelect(node) {
|
||||||
|
this.select = node;
|
||||||
|
},
|
||||||
getInputElement() {
|
getInputElement() {
|
||||||
const { $slots, placeholder } = this;
|
const { placeholder } = this;
|
||||||
const children = filterEmpty($slots.default);
|
const children = getSlot(this);
|
||||||
const element = children.length ? children[0] : <Input lazy={false} />;
|
const element = children.length ? children[0] : <Input lazy={false} />;
|
||||||
return <InputElement placeholder={placeholder}>{element}</InputElement>;
|
return <InputElement placeholder={placeholder}>{element}</InputElement>;
|
||||||
},
|
},
|
||||||
|
|
||||||
focus() {
|
focus() {
|
||||||
if (this.$refs.select) {
|
if (this.select) {
|
||||||
this.$refs.select.focus();
|
this.select.focus();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
blur() {
|
blur() {
|
||||||
if (this.$refs.select) {
|
if (this.select) {
|
||||||
this.$refs.select.blur();
|
this.select.blur();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { size, prefixCls: customizePrefixCls, optionLabelProp, dataSource, $slots } = this;
|
const { size, prefixCls: customizePrefixCls, optionLabelProp, dataSource } = this;
|
||||||
|
|
||||||
const getPrefixCls = this.configProvider.getPrefixCls;
|
const getPrefixCls = this.configProvider.getPrefixCls;
|
||||||
const prefixCls = getPrefixCls('select', customizePrefixCls);
|
const prefixCls = getPrefixCls('select', customizePrefixCls);
|
||||||
|
const { class: className } = this.$attrs;
|
||||||
const cls = {
|
const cls = {
|
||||||
|
[className]: !!className,
|
||||||
[`${prefixCls}-lg`]: size === 'large',
|
[`${prefixCls}-lg`]: size === 'large',
|
||||||
[`${prefixCls}-sm`]: size === 'small',
|
[`${prefixCls}-sm`]: size === 'small',
|
||||||
[`${prefixCls}-show-search`]: true,
|
[`${prefixCls}-show-search`]: true,
|
||||||
|
@ -106,8 +107,8 @@ const AutoComplete = {
|
||||||
};
|
};
|
||||||
|
|
||||||
let options;
|
let options;
|
||||||
const childArray = filterEmpty($slots.dataSource);
|
const childArray = getSlot(this, 'dataSource');
|
||||||
if (childArray.length) {
|
if (childArray.length && isSelectOptionOrSelectOptGroup(childArray[0])) {
|
||||||
options = childArray;
|
options = childArray;
|
||||||
} else {
|
} else {
|
||||||
options = dataSource
|
options = dataSource
|
||||||
|
@ -129,28 +130,25 @@ const AutoComplete = {
|
||||||
: [];
|
: [];
|
||||||
}
|
}
|
||||||
const selectProps = {
|
const selectProps = {
|
||||||
props: {
|
...getOptionProps(this),
|
||||||
...getOptionProps(this),
|
...this.$attrs,
|
||||||
mode: Select.SECRET_COMBOBOX_MODE_DO_NOT_USE,
|
mode: Select.SECRET_COMBOBOX_MODE_DO_NOT_USE,
|
||||||
optionLabelProp,
|
optionLabelProp,
|
||||||
getInputElement: this.getInputElement,
|
getInputElement: this.getInputElement,
|
||||||
notFoundContent: getComponentFromProp(this, 'notFoundContent'),
|
notFoundContent: getComponent(this, 'notFoundContent'),
|
||||||
placeholder: '',
|
placeholder: '',
|
||||||
},
|
|
||||||
class: cls,
|
class: cls,
|
||||||
ref: 'select',
|
ref: this.saveSelect,
|
||||||
on: getListeners(this),
|
|
||||||
};
|
};
|
||||||
return <Select {...selectProps}>{options}</Select>;
|
return <Select {...selectProps}>{options}</Select>;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
AutoComplete.install = function(Vue) {
|
AutoComplete.install = function(app) {
|
||||||
Vue.use(Base);
|
app.component(AutoComplete.name, AutoComplete);
|
||||||
Vue.component(AutoComplete.name, AutoComplete);
|
app.component(AutoComplete.Option.name, AutoComplete.Option);
|
||||||
Vue.component(AutoComplete.Option.name, AutoComplete.Option);
|
app.component(AutoComplete.OptGroup.name, AutoComplete.OptGroup);
|
||||||
Vue.component(AutoComplete.OptGroup.name, AutoComplete.OptGroup);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default AutoComplete;
|
export default AutoComplete;
|
||||||
|
|
|
@ -33,7 +33,8 @@ export function getPropValue(child, prop) {
|
||||||
return getValuePropValue(child);
|
return getValuePropValue(child);
|
||||||
}
|
}
|
||||||
if (prop === 'children') {
|
if (prop === 'children') {
|
||||||
const newChild = cloneElement(getComponent(child));
|
const temp = getComponent(child);
|
||||||
|
const newChild = isVNode(temp) ? cloneElement(temp) : temp;
|
||||||
if (isVNode(newChild) && newChild.type === Text) {
|
if (isVNode(newChild) && newChild.type === Text) {
|
||||||
return newChild.children;
|
return newChild.children;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ import '@babel/polyfill';
|
||||||
import { createApp } from 'vue';
|
import { createApp } from 'vue';
|
||||||
import App from './App.vue';
|
import App from './App.vue';
|
||||||
import {
|
import {
|
||||||
|
AutoComplete,
|
||||||
Radio,
|
Radio,
|
||||||
Spin,
|
Spin,
|
||||||
Select,
|
Select,
|
||||||
|
@ -49,4 +50,5 @@ app
|
||||||
.use(Row)
|
.use(Row)
|
||||||
.use(Radio)
|
.use(Radio)
|
||||||
.use(InputNumber)
|
.use(InputNumber)
|
||||||
|
.use(AutoComplete)
|
||||||
.mount('#app');
|
.mount('#app');
|
||||||
|
|
Loading…
Reference in New Issue