feat: update upload (#2494)

* feat: update upload

* chore: cache babel

* chore: make run dev faster
pull/2498/head
Amour1688 2020-06-25 21:23:39 +08:00 committed by GitHub
parent 23358dba44
commit a325bf2319
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 88 additions and 184 deletions

View File

@ -1,10 +1,9 @@
import classNames from 'classnames'; import classNames from 'classnames';
import uniqBy from 'lodash/uniqBy'; import uniqBy from 'lodash/uniqBy';
import findIndex from 'lodash/findIndex'; import findIndex from 'lodash/findIndex';
import pick from 'lodash/pick';
import VcUpload from '../vc-upload'; import VcUpload from '../vc-upload';
import BaseMixin from '../_util/BaseMixin'; import BaseMixin from '../_util/BaseMixin';
import { getOptionProps, initDefaultProps, hasProp, getListeners } from '../_util/props-util'; import { getOptionProps, initDefaultProps, hasProp, getSlot } from '../_util/props-util';
import LocaleReceiver from '../locale-provider/LocaleReceiver'; import LocaleReceiver from '../locale-provider/LocaleReceiver';
import defaultLocale from '../locale-provider/default'; import defaultLocale from '../locale-provider/default';
import { ConfigConsumerProps } from '../config-provider'; import { ConfigConsumerProps } from '../config-provider';
@ -12,6 +11,7 @@ import Dragger from './Dragger';
import UploadList from './UploadList'; import UploadList from './UploadList';
import { UploadProps } from './interface'; import { UploadProps } from './interface';
import { T, fileToObject, genPercentAdd, getFileItem, removeFileItem } from './utils'; import { T, fileToObject, genPercentAdd, getFileItem, removeFileItem } from './utils';
import { inject } from 'vue';
export { UploadProps }; export { UploadProps };
@ -32,8 +32,10 @@ export default {
disabled: false, disabled: false,
supportServerRender: true, supportServerRender: true,
}), }),
inject: { setup() {
configProvider: { default: () => ConfigConsumerProps }, return {
configProvider: inject('configProvider', ConfigConsumerProps),
};
}, },
// recentUploadStatus: boolean | PromiseLike<any>; // recentUploadStatus: boolean | PromiseLike<any>;
data() { data() {
@ -217,20 +219,18 @@ export default {
} = getOptionProps(this); } = getOptionProps(this);
const { showRemoveIcon, showPreviewIcon, showDownloadIcon } = showUploadList; const { showRemoveIcon, showPreviewIcon, showDownloadIcon } = showUploadList;
const { sFileList: fileList } = this.$data; const { sFileList: fileList } = this.$data;
const { onDownload, onPreview } = this.$attrs;
const uploadListProps = { const uploadListProps = {
props: { listType,
listType, items: fileList,
items: fileList, previewFile,
previewFile, showRemoveIcon: !disabled && showRemoveIcon,
showRemoveIcon: !disabled && showRemoveIcon, showPreviewIcon,
showPreviewIcon, showDownloadIcon,
showDownloadIcon, locale: { ...locale, ...propLocale },
locale: { ...locale, ...propLocale }, onRemove: this.handleManualRemove,
}, onDownload,
on: { onPreview,
remove: this.handleManualRemove,
...pick(getListeners(this), ['download', 'preview']), // uploadlist
},
}; };
return <UploadList {...uploadListProps} />; return <UploadList {...uploadListProps} />;
}, },
@ -248,31 +248,27 @@ export default {
const prefixCls = getPrefixCls('upload', customizePrefixCls); const prefixCls = getPrefixCls('upload', customizePrefixCls);
const vcUploadProps = { const vcUploadProps = {
props: { ...this.$props,
...this.$props, prefixCls,
prefixCls, beforeUpload: this.reBeforeUpload,
beforeUpload: this.reBeforeUpload, onStart: this.onStart,
}, onError: this.onError,
on: { onProgress: this.onProgress,
start: this.onStart, onSuccess: this.onSuccess,
error: this.onError, onReject: this.onReject,
progress: this.onProgress,
success: this.onSuccess,
reject: this.onReject,
},
ref: 'uploadRef', ref: 'uploadRef',
attrs: this.$attrs, ...this.$attrs,
}; };
const uploadList = showUploadList ? ( const uploadList = showUploadList ? (
<LocaleReceiver <LocaleReceiver
componentName="Upload" componentName="Upload"
defaultLocale={defaultLocale.Upload} defaultLocale={defaultLocale.Upload}
scopedSlots={{ default: this.renderUploadList }} children={this.renderUploadList}
/> />
) : null; ) : null;
const children = this.$slots.default; const children = getSlot(this);
if (type === 'drag') { if (type === 'drag') {
const dragCls = classNames(prefixCls, { const dragCls = classNames(prefixCls, {

View File

@ -1,3 +1,4 @@
import { inject, TransitionGroup } from 'vue';
import BaseMixin from '../_util/BaseMixin'; import BaseMixin from '../_util/BaseMixin';
import { getOptionProps, initDefaultProps, getListeners } from '../_util/props-util'; import { getOptionProps, initDefaultProps, getListeners } from '../_util/props-util';
import getTransitionProps from '../_util/getTransitionProps'; import getTransitionProps from '../_util/getTransitionProps';
@ -29,8 +30,10 @@ export default {
showPreviewIcon: true, showPreviewIcon: true,
previewFile: previewImage, previewFile: previewImage,
}), }),
inject: { setup() {
configProvider: { default: () => ConfigConsumerProps }, return {
configProvider: inject('configProvider', ConfigConsumerProps),
};
}, },
updated() { updated() {
this.$nextTick(() => { this.$nextTick(() => {
@ -132,11 +135,9 @@ export default {
if (file.status === 'uploading') { if (file.status === 'uploading') {
const progressProps = { const progressProps = {
props: { ...progressAttr,
...progressAttr, type: 'line',
type: 'line', percent: file.percent,
percent: file.percent,
},
}; };
// show loading icon if upload progress listener is disabled // show loading icon if upload progress listener is disabled
const loadingProgress = 'percent' in file ? <Progress {...progressProps} /> : null; const loadingProgress = 'percent' in file ? <Progress {...progressProps} /> : null;
@ -160,10 +161,7 @@ export default {
) : null; ) : null;
const downloadIcon = const downloadIcon =
showDownloadIcon && file.status === 'done' ? ( showDownloadIcon && file.status === 'done' ? (
<DownloadOutlined <DownloadOutlined title={locale.downloadFile} onClick={() => this.handleDownload(file)} />
title={locale.downloadFile}
onClick={() => this.handleDownload(file)}
/>
) : null; ) : null;
const downloadOrDelete = listType !== 'picture-card' && ( const downloadOrDelete = listType !== 'picture-card' && (
<span <span
@ -250,7 +248,7 @@ export default {
<div class={infoUploadingClass} key={file.uid}> <div class={infoUploadingClass} key={file.uid}>
<div class={`${prefixCls}-list-item-info`}>{iconAndPreview}</div> <div class={`${prefixCls}-list-item-info`}>{iconAndPreview}</div>
{actions} {actions}
<transition {...transitionProps}>{progress}</transition> <Transition {...transitionProps}>{progress}</Transition>
</div> </div>
); );
const listContainerNameClass = classNames({ const listContainerNameClass = classNames({
@ -269,9 +267,9 @@ export default {
const animationDirection = listType === 'picture-card' ? 'animate-inline' : 'animate'; const animationDirection = listType === 'picture-card' ? 'animate-inline' : 'animate';
const transitionGroupProps = getTransitionProps(`${prefixCls}-${animationDirection}`); const transitionGroupProps = getTransitionProps(`${prefixCls}-${animationDirection}`);
return ( return (
<transition-group {...transitionGroupProps} tag="div" class={listClassNames}> <TransitionGroup {...transitionGroupProps} tag="div" class={listClassNames}>
{list} {list}
</transition-group> </TransitionGroup>
); );
}, },
}; };

View File

@ -1,6 +1,5 @@
import Vue from 'vue';
import ref from 'vue-ref';
import PropTypes from '../../_util/vue-types'; import PropTypes from '../../_util/vue-types';
import antRef from '../../_util/ant-ref';
import { initDefaultProps } from '../../_util/props-util'; import { initDefaultProps } from '../../_util/props-util';
import enhancer from './enhancer'; import enhancer from './enhancer';
import { propTypes, defaultProps } from './types'; import { propTypes, defaultProps } from './types';
@ -16,8 +15,6 @@ const circleDefaultProps = {
gapPosition: 'top', gapPosition: 'top',
}; };
Vue.use(ref, { name: 'ant-ref' });
let gradientSeed = 0; let gradientSeed = 0;
function stripPercentToNumber(percent) { function stripPercentToNumber(percent) {
@ -74,6 +71,7 @@ function getPathStyles(offset, percent, strokeColor, strokeWidth, gapDegree = 0,
const Circle = { const Circle = {
props: initDefaultProps(circlePropTypes, circleDefaultProps), props: initDefaultProps(circlePropTypes, circleDefaultProps),
directives: { antRef },
created() { created() {
this.paths = {}; this.paths = {};
this.gradientId = gradientSeed; this.gradientId = gradientSeed;
@ -113,25 +111,15 @@ const Circle = {
const pathProps = { const pathProps = {
key: index, key: index,
attrs: { d: pathString,
d: pathString, stroke,
stroke, 'stroke-linecap': strokeLinecap,
'stroke-linecap': strokeLinecap, 'stroke-width': ptg === 0 ? 0 : strokeWidth,
'stroke-width': ptg === 0 ? 0 : strokeWidth, 'fill-opacity': '0',
'fill-opacity': '0',
},
class: `${prefixCls}-circle-path`, class: `${prefixCls}-circle-path`,
style: pathStyle, style: pathStyle,
directives: [
{
name: 'ant-ref',
value: c => {
this.paths[index] = c;
},
},
],
}; };
return <path {...pathProps} />; return <path v-antRef={c => (this.paths[index] = c)} {...pathProps} />;
}); });
}, },
}, },

View File

@ -1,13 +1,11 @@
import Vue from 'vue';
import ref from 'vue-ref';
import { initDefaultProps } from '../../_util/props-util'; import { initDefaultProps } from '../../_util/props-util';
import antRef from '../../_util/ant-ref';
import enhancer from './enhancer'; import enhancer from './enhancer';
import { propTypes, defaultProps } from './types'; import { propTypes, defaultProps } from './types';
Vue.use(ref, { name: 'ant-ref' });
const Line = { const Line = {
props: initDefaultProps(propTypes, defaultProps), props: initDefaultProps(propTypes, defaultProps),
directives: { antRef },
created() { created() {
this.paths = {}; this.paths = {};
}, },
@ -78,17 +76,9 @@ const Line = {
}, },
class: `${prefixCls}-line-path`, class: `${prefixCls}-line-path`,
style: pathStyle, style: pathStyle,
directives: [
{
name: 'ant-ref',
value: c => {
this.paths[index] = c;
},
},
],
}; };
return <path {...pathProps} />; return <path v-antRef={c => (this.paths[index] = c)} {...pathProps} />;
})} })}
</svg> </svg>
); );

View File

@ -6,7 +6,7 @@ import defaultRequest from './request';
import getUid from './uid'; import getUid from './uid';
import attrAccept from './attr-accept'; import attrAccept from './attr-accept';
import traverseFileTree from './traverseFileTree'; import traverseFileTree from './traverseFileTree';
import { getListeners } from '../../_util/props-util'; import { getListeners, getSlot } from '../../_util/props-util';
const upLoadPropTypes = { const upLoadPropTypes = {
componentTag: PropTypes.string, componentTag: PropTypes.string,
@ -223,20 +223,15 @@ const AjaxUploader = {
const events = disabled const events = disabled
? {} ? {}
: { : {
click: openFileDialogOnClick ? this.onClick : () => {}, onClick: openFileDialogOnClick ? this.onClick : () => {},
keydown: openFileDialogOnClick ? this.onKeyDown : () => {}, onKeydown: openFileDialogOnClick ? this.onKeyDown : () => {},
drop: this.onFileDrop, onDrop: this.onFileDrop,
dragover: this.onFileDrop, onDragover: this.onFileDrop,
}; };
const tagProps = { const tagProps = {
on: { ...events,
...getListeners(this), role: 'button',
...events, tabIndex: disabled ? null : '0',
},
attrs: {
role: 'button',
tabIndex: disabled ? null : '0',
},
class: cls, class: cls,
}; };
return ( return (
@ -254,7 +249,7 @@ const AjaxUploader = {
multiple={multiple} multiple={multiple}
onChange={this.onChange} onChange={this.onChange}
/> />
{this.$slots.default} {getSlot(this)}
</Tag> </Tag>
); );
}, },

View File

@ -3,6 +3,7 @@ import BaseMixin from '../../_util/BaseMixin';
import classNames from 'classnames'; import classNames from 'classnames';
import getUid from './uid'; import getUid from './uid';
import warning from '../../_util/warning'; import warning from '../../_util/warning';
import { getSlot } from '../../_util/props-util';
const IFRAME_STYLE = { const IFRAME_STYLE = {
position: 'absolute', position: 'absolute',
@ -268,7 +269,7 @@ const IframeUploader = {
return ( return (
<Tag className={cls} style={{ position: 'relative', zIndex: 0 }}> <Tag className={cls} style={{ position: 'relative', zIndex: 0 }}>
<iframe ref="iframeRef" onLoad={this.onLoad} style={iframeStyle} /> <iframe ref="iframeRef" onLoad={this.onLoad} style={iframeStyle} />
{this.$slots.default} {getSlot(this)}
</Tag> </Tag>
); );
}, },

View File

@ -1,5 +1,5 @@
import PropTypes from '../../_util/vue-types'; import PropTypes from '../../_util/vue-types';
import { initDefaultProps, getListeners } from '../../_util/props-util'; import { initDefaultProps, getSlot } from '../../_util/props-util';
import BaseMixin from '../../_util/BaseMixin'; import BaseMixin from '../../_util/BaseMixin';
import AjaxUpload from './AjaxUploader'; import AjaxUpload from './AjaxUploader';
import IframeUpload from './IframeUploader'; import IframeUpload from './IframeUploader';
@ -13,10 +13,10 @@ const uploadProps = {
name: PropTypes.string, name: PropTypes.string,
multipart: PropTypes.bool, multipart: PropTypes.bool,
directory: PropTypes.bool, directory: PropTypes.bool,
// onError: PropTypes.func, onError: PropTypes.func,
// onSuccess: PropTypes.func, onSuccess: PropTypes.func,
// onProgress: PropTypes.func, onProgress: PropTypes.func,
// onStart: PropTypes.func, onStart: PropTypes.func,
data: PropTypes.oneOfType([PropTypes.object, PropTypes.func]), data: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),
headers: PropTypes.object, headers: PropTypes.object,
accept: PropTypes.string, accept: PropTypes.string,
@ -24,7 +24,7 @@ const uploadProps = {
disabled: PropTypes.bool, disabled: PropTypes.bool,
beforeUpload: PropTypes.func, beforeUpload: PropTypes.func,
customRequest: PropTypes.func, customRequest: PropTypes.func,
// onReady: PropTypes.func, onReady: PropTypes.func,
withCredentials: PropTypes.bool, withCredentials: PropTypes.bool,
supportServerRender: PropTypes.bool, supportServerRender: PropTypes.bool,
openFileDialogOnClick: PropTypes.bool, openFileDialogOnClick: PropTypes.bool,
@ -40,10 +40,10 @@ export default {
headers: {}, headers: {},
name: 'file', name: 'file',
multipart: false, multipart: false,
// onReady: empty, onReady: empty,
// onStart: empty, onStart: empty,
// onError: empty, onError: empty,
// onSuccess: empty, onSuccess: empty,
supportServerRender: false, supportServerRender: false,
multiple: false, multiple: false,
beforeUpload: empty, beforeUpload: empty,
@ -80,21 +80,18 @@ export default {
render() { render() {
const componentProps = { const componentProps = {
props: { ...this.$props,
...this.$props,
},
on: getListeners(this),
ref: 'uploaderRef', ref: 'uploaderRef',
attrs: this.$attrs, ...this.$attrs,
}; };
if (this.supportServerRender) { if (this.supportServerRender) {
const ComponentUploader = this.Component; const ComponentUploader = this.Component;
if (ComponentUploader) { if (ComponentUploader) {
return <ComponentUploader {...componentProps}>{this.$slots.default}</ComponentUploader>; return <ComponentUploader {...componentProps}>{getSlot(this)}</ComponentUploader>;
} }
return null; return null;
} }
const ComponentUploader = this.getComponent(); const ComponentUploader = this.getComponent();
return <ComponentUploader {...componentProps}>{this.$slots.default}</ComponentUploader>; return <ComponentUploader {...componentProps}>{getSlot(this)}</ComponentUploader>;
}, },
}; };

View File

@ -1,44 +1,7 @@
import '@babel/polyfill'; import '@babel/polyfill';
import { createApp } from 'vue'; import { createApp } from 'vue';
import App from './App.vue'; import App from './App.vue';
import Avatar from 'ant-design-vue/avatar'; import { Button, Upload, Icon, notification, message } from 'ant-design-vue';
import Breadcrumb from 'ant-design-vue/breadcrumb';
import Button from 'ant-design-vue/button';
import Comment from 'ant-design-vue/comment';
import Drawer from 'ant-design-vue/drawer';
import Affix from 'ant-design-vue/affix';
import Alert from 'ant-design-vue/alert';
import Divider from 'ant-design-vue/divider';
import Anchor from 'ant-design-vue/anchor';
import Radio from 'ant-design-vue/radio';
import ConfigProvider from 'ant-design-vue/config-provider';
import Result from 'ant-design-vue/result';
import Spin from 'ant-design-vue/spin';
import PageHeader from 'ant-design-vue/page-header';
import Skeleton from 'ant-design-vue/skeleton';
import Empty from 'ant-design-vue/empty';
import Timeline from 'ant-design-vue/timeline';
import Statistic from 'ant-design-vue/statistic';
import Checkbox from 'ant-design-vue/checkbox';
import Col from 'ant-design-vue/col';
import Row from 'ant-design-vue/row';
import Tooltip from 'ant-design-vue/tooltip';
import Descriptions from 'ant-design-vue/descriptions';
import BackTop from 'ant-design-vue/back-top';
import Tag from 'ant-design-vue/tag';
import Popconfirm from 'ant-design-vue/popconfirm';
import Popover from 'ant-design-vue/popover';
import notification from 'ant-design-vue/notification';
import message from 'ant-design-vue/message';
import Modal from 'ant-design-vue/modal';
import Menu from 'ant-design-vue/menu';
import Mentions from 'ant-design-vue/mentions';
import Dropdown from 'ant-design-vue/dropdown';
import Steps from 'ant-design-vue/steps';
import Switch from 'ant-design-vue/switch';
import Layout from 'ant-design-vue/layout';
import Tabs from 'ant-design-vue/tabs';
import Card from 'ant-design-vue/card';
import 'ant-design-vue/style.js'; import 'ant-design-vue/style.js';
const basic = { const basic = {
@ -55,40 +18,7 @@ app
.component('api', { ...basic }) .component('api', { ...basic })
.component('CN', { ...basic }) .component('CN', { ...basic })
.component('US', { ...basic }) .component('US', { ...basic })
.use(Avatar) .use(Upload)
.use(Breadcrumb)
.use(Button) .use(Button)
.use(Comment) .use(Icon)
.use(ConfigProvider)
.use(Drawer)
.use(Affix)
.use(Alert)
.use(Radio)
.use(Divider)
.use(Result)
.use(PageHeader)
.use(Anchor)
.use(Skeleton)
.use(Spin)
.use(Empty)
.use(Checkbox)
.use(Timeline)
.use(Statistic)
.use(Col)
.use(Row)
.use(Tooltip)
.use(Descriptions)
.use(BackTop)
.use(Tag)
.use(Popconfirm)
.use(Popover)
.use(Modal)
.use(Menu)
.use(Mentions)
.use(Dropdown)
.use(Steps)
.use(Switch)
.use(Layout)
.use(Tabs)
.use(Card)
.mount('#app'); .mount('#app');

View File

@ -19,6 +19,7 @@ module.exports = {
test: /\.(js|jsx)$/, test: /\.(js|jsx)$/,
loader: 'babel-loader', loader: 'babel-loader',
options: { options: {
cacheDirectory: true,
presets: [ presets: [
[ [
'@babel/preset-env', '@babel/preset-env',
@ -37,6 +38,14 @@ module.exports = {
], ],
], ],
plugins: [ plugins: [
[
'babel-plugin-import',
{
libraryName: 'ant-design-vue',
libraryDirectory: '', // default: lib
style: true,
},
],
['@ant-design-vue/babel-plugin-jsx', { transformOn: true }], ['@ant-design-vue/babel-plugin-jsx', { transformOn: true }],
'@babel/plugin-proposal-optional-chaining', '@babel/plugin-proposal-optional-chaining',
'@babel/plugin-transform-object-assign', '@babel/plugin-transform-object-assign',