refactor(upload): createThumbnailUrl

This commit is contained in:
07akioni 2022-11-21 01:26:35 +08:00
parent 67d6bf3fd4
commit 9829b714fe
13 changed files with 48 additions and 27 deletions

View File

@ -127,7 +127,8 @@ export default defineComponent({
const handleError = (e: Event): void => {
if (!shouldStartLoadingRef.value) return
hasLoadErrorRef.value = true
const { onError } = props
const { onError, imgProps } = props
imgProps?.onError?.(e)
if (onError) {
onError(e)
}
@ -240,8 +241,9 @@ export default defineComponent({
shouldStartLoading: shouldStartLoadingRef,
loaded: loadedRef,
mergedOnLoad: (e: Event) => {
const { onLoad } = props
const { onLoad, imgProps } = props
onLoad?.(e)
imgProps?.onLoad?.(e)
loadedRef.value = true
}
}
@ -287,8 +289,9 @@ export default defineComponent({
</VResizeObserver>
)
} else if (src) {
const { imgProps } = this
return h('img', {
...this.imgProps,
...imgProps,
loading: isImageSupportNativeLazy && lazy ? 'lazy' : 'eager',
src: isImageSupportNativeLazy
? src
@ -299,6 +302,7 @@ export default defineComponent({
'data-image-src': src,
onError: this.handleError,
style: [
imgProps?.style,
{ objectFit: this.objectFit },
placeholderNode
? {

View File

@ -547,7 +547,7 @@ const Button = defineComponent({
}
},
render () {
const { mergedClsPrefix, renderIcon, tag: Component, onRender } = this
const { mergedClsPrefix, tag: Component, onRender } = this
onRender?.()
const children = resolveWrappedSlot(
this.$slots.default,
@ -591,7 +591,7 @@ const Button = defineComponent({
resolveWrappedSlot(
this.$slots.icon,
(children) =>
(this.loading || renderIcon || children) && (
(this.loading || this.renderIcon || children) && (
<span
class={`${mergedClsPrefix}-button__icon`}
style={{
@ -614,7 +614,7 @@ const Button = defineComponent({
class={`${mergedClsPrefix}-icon-slot`}
role="none"
>
{renderIcon ? renderIcon() : children}
{this.renderIcon ? this.renderIcon() : children}
</div>
)
}}

View File

@ -1,6 +1,6 @@
# Equation
No one will think of that a component library should have this component. however a friend of me need this.
No one will think of that a component library should have this component. However a friend of me need this.
<n-alert title="Note" type="warning" style="margin-bottom: 16px;" :bordered="false">
Due to package size, Naive UI doesn't include katex. If you want to use Equation, make sure you have setup katex before using it.

View File

@ -1,7 +1,7 @@
<markdown>
# 字素计数
浏览器默认的 `maxlength` `minlength` 以及 naive-ui 自带的字数统计功能并不能准确拆分所有的字符串你可以使用 `count-graphemes` 属性来精确的测量文字长度
浏览器默认的 `maxlength` `minlength` 以及 naive-ui 自带的字数统计功能并不能准确拆分所有的字符串你可以使用 `count-graphemes` 属性来精确的测量文字长度
</markdown>
<template>

View File

@ -74,7 +74,7 @@ export interface InternalDropInfo {
dropPosition: DropPosition
}
export type RenderSwitcherIcon = (options: {
export type RenderSwitcherIcon = (props: {
expanded: boolean
selected: boolean
}) => VNodeChild

View File

@ -50,7 +50,8 @@ export default defineComponent({
])
return {
fileList: fileListRef,
createThumbnailUrl (file: File): Promise<string> {
createThumbnailUrl (file: File | null): Promise<string> | undefined {
if (!file) return undefined
message.info(() => [
'`createThumbnailUrl` changes the thumbnail image of the uploaded file.',
h('br'),

View File

@ -28,7 +28,7 @@ download.vue
| abstract | `boolean` | `false` | Whether or not DOM wrapping does not exist. Not supported for `image-card` type. | |
| accept | `string` | `undefined` | The accept type of upload. See <n-a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#accept" target="_blank">accept</n-a>. | |
| action | `string` | `undefined` | The URL to submit data to. | |
| create-thumbnail-url | `(file: File) => Promise<string>` | `undefined` | Customize file thumbnails. | |
| create-thumbnail-url | `(file: File \| null, fileInfo: UploadSettledFileInfo) => (Promise<string> \| string \| undefined)` | `undefined` | Customize file thumbnails. If `undefined` is returned, the file would use default thumbnail display logic. | `fileInfo` NEXT_VERSION |
| custom-request | `(options: UploadCustomRequestOptions) => void` | `undefined` | Customize upload request. For types, see <n-a href="#UploadCustomRequestOptions-Type">UploadCustomRequestOptions</n-a> | |
| data | `Object \| ({ file: UploadFileInfo }) => Object` | `undefined` | The additional fileds data of HTTP request's form data. | |
| default-file-list | `Array<UploadFileInfo>` | `[]` | The default file list in uncontrolled manner. | |
@ -47,7 +47,9 @@ download.vue
| method | `string` | `'POST'` | The HTTP request method. | |
| multiple | `boolean` | `false` | Allow multiple files to be selected. | |
| name | `string` | `'file'` | The field name for the file(s) in the HTTP request's form data. | |
| render-icon | `(file: UploadSettledFileInfo) => VNodeChild` | `undefined` | Render function of file icon. It works when `list-type="image"`. | NEXT_VERSION |
| response-type | `'' \| 'arraybuffer' \| 'blob' \| 'document' \| 'json' \| 'text'` | `''` | Response type of `XMLHttpRequest` used by `n-upload` | 2.33.3 |
| should-use-thumbnail-url | `(file: UploadSettledFileInfo) => boolean` | A function that only returns `true` for image typed file. | A function that determines whether to show thumbnail for the file. It only works when `list-type="image"` or `list-type="image-card"`. | NEXT_VERSION |
| show-cancel-button | `boolean` | `true` | Show a cancel button (while uploading). Use the `on-remove` callback for this event. | |
| show-download-button | `boolean` | `false` | Show a download button (after upload is finished). | |
| show-file-list | `boolean` | `true` | Show a file list. | |

View File

@ -50,7 +50,8 @@ export default defineComponent({
])
return {
fileList: fileListRef,
createThumbnailUrl (file: File): Promise<string> {
createThumbnailUrl (file: File | null): Promise<string> | undefined {
if (!file) return undefined
message.info(
'createThumbnailUrl 产生了图片的 URL你传什么都会变成 07akioni'
)

View File

@ -29,7 +29,7 @@ debug.vue
| abstract | `boolean` | `false` | 是否不存在 DOM 包裹,不支持 `image-card` 类型的 Upload | |
| accept | `string` | `undefined` | 接受的文件类型,参考 <n-a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#accept" target="_blank">accept</n-a> | |
| action | `string` | `undefined` | 请求提交的地址 | |
| create-thumbnail-url | `(file: File) => Promise<string>` | `undefined` | 自定义文件缩略图 | |
| create-thumbnail-url | `(file: File \| null, fileInfo: UploadSettledFileInfo) => (Promise<string> \| string \| undefined)` | `undefined` | 自定义文件缩略图,如果返回了 `undefined`,会使用默认的缩略图展示逻辑 | `fileInfo` NEXT_VERSION |
| custom-request | `(options: UploadCustomRequestOptions) => void` | `undefined` | 自定义上传方法,类型参考 <n-a href="#UploadCustomRequestOptions-Type">UploadCustomRequestOptions</n-a> | |
| data | `Object \| ({ file: UploadFileInfo }) => Object` | `undefined` | 提交表单需要附加的数据 | |
| default-file-list | `Array<UploadFileInfo>` | `[]` | 非受控状态下默认的文件列表 | |
@ -48,7 +48,9 @@ debug.vue
| method | `string` | `'POST'` | HTTP 请求的方法 | |
| multiple | `boolean` | `false` | 是否支持多个文件 | |
| name | `string` | `'file'` | 文件在提交表单中的字段名 | |
| render-icon | `(file: UploadSettledFileInfo) => VNodeChild` | `undefined` | 文件图标的渲染函数,在 `list-type="image"` 时生效 | NEXT_VERSION |
| response-type | `'' \| 'arraybuffer' \| 'blob' \| 'document' \| 'json' \| 'text'` | `''` | `n-upload` 使用的 `XMLHttpRequest``responseType` | 2.33.3 |
| should-use-thumbnail-url | `(file: UploadSettledFileInfo) => boolean` | 只对图片类文件返回 `true` 的函数 | 是否要对文件使用预览图的判定函数,只在 `list-type="image"``list-type="image-card"` 时生效 | NEXT_VERSION |
| show-cancel-button | `boolean` | `true` | 是否显示取消按钮(在 pending、uploading、error 的时候展示),点击取消按钮会触发 `on-remove` 回调 | |
| show-download-button | `boolean` | `false` | 是否显示下载按钮(在 finished 后展示) | |
| show-remove-button | `boolean` | `true` | 是否显示删除按钮(在 finished 后时候展示),点击删除按钮会触发 `on-remove` 回调 | |

View File

@ -347,7 +347,7 @@ export const uploadProps = {
shouldUseThumbnailUrl: {
type: Function as PropType<ShouldUseThumbnailUrl>,
default: (file: SettledFileInfo) => {
if (!environmentSupportFile || !(file.file instanceof File)) return false
if (!environmentSupportFile) return false
return isImageFile(file)
}
},
@ -595,11 +595,20 @@ export default defineComponent({
warn('upload', 'File has no corresponding id in current file list.')
}
}
async function getFileThumbnailUrl (file: SettledFileInfo): Promise<string> {
function getFileThumbnailUrlResolver (
file: SettledFileInfo
): Promise<string> | string {
if (file.thumbnailUrl) return file.thumbnailUrl
const { createThumbnailUrl } = props
return createThumbnailUrl
? await createThumbnailUrl(file.file, file)
: await createImageDataUrl(file.file)
if (createThumbnailUrl) {
return createThumbnailUrl(file.file, file) ?? (file.url || '')
}
if (file.url) {
return file.url
} else if (file.file) {
return createImageDataUrl(file.file)
}
return ''
}
const cssVarsRef = computed(() => {
const {
@ -662,7 +671,7 @@ export default defineComponent({
doChange,
showPreviewButtonRef: toRef(props, 'showPreviewButton'),
onPreviewRef: toRef(props, 'onPreview'),
getFileThumbnailUrl,
getFileThumbnailUrlResolver,
listTypeRef: toRef(props, 'listType'),
dragOverRef,
openOpenFileDialog,

View File

@ -190,7 +190,9 @@ export default defineComponent({
return
}
if (NUpload.shouldUseThumbnailUrlRef.value(props.file)) {
thumbnailUrlRef.value = await NUpload.getFileThumbnailUrl(props.file)
thumbnailUrlRef.value = await NUpload.getFileThumbnailUrlResolver(
props.file
)
}
}

View File

@ -102,7 +102,9 @@ export interface UploadInjection {
onRender: undefined | (() => void)
submit: (fileId?: string) => void
shouldUseThumbnailUrlRef: Ref<ShouldUseThumbnailUrl>
getFileThumbnailUrl: (file: SettledFileInfo) => Promise<string>
getFileThumbnailUrlResolver: (
file: SettledFileInfo
) => Promise<string> | string
renderIconRef: Ref<RenderIcon | undefined>
handleFileAddition: (files: FileAndEntry[] | null, e?: Event) => void
openOpenFileDialog: () => void
@ -137,7 +139,7 @@ export type OnPreview = (file: SettledFileInfo) => void
export type CreateThumbnailUrl = (
file: File | null,
fileInfo: SettledFileInfo
) => Promise<string>
) => Promise<string> | string | undefined
export interface CustomRequestOptions {
file: SettledFileInfo

View File

@ -16,6 +16,7 @@ const getExtname = (url: string = ''): string => {
return (/\.[^./\\]*$/.exec(filenameWithoutSuffix) || [''])[0]
}
// Do not need File object
export const isImageFile: ShouldUseThumbnailUrl = (file) => {
if (file.type) {
return isImageFileType(file.type)
@ -34,18 +35,15 @@ export const isImageFile: ShouldUseThumbnailUrl = (file) => {
if (extension) {
return false
}
return true
return false
}
export async function createImageDataUrl (file: File | null): Promise<string> {
if (!file) return ''
export async function createImageDataUrl (file: File): Promise<string> {
return await new Promise((resolve) => {
if (!file.type || !isImageFileType(file.type)) {
resolve('')
return
}
resolve(window.URL.createObjectURL(file))
})
}