2021-12-10 17:52:11 +08:00
|
|
|
import { isRef, ref } from 'vue'
|
2022-03-25 15:35:56 +08:00
|
|
|
import { hyphenate, isObject, isString } from '@vue/shared'
|
2021-12-10 17:52:11 +08:00
|
|
|
import { Loading } from './service'
|
|
|
|
import type { Directive, DirectiveBinding, UnwrapRef } from 'vue'
|
|
|
|
import type { LoadingOptions } from './types'
|
|
|
|
import type { LoadingInstance } from './loading'
|
2020-10-23 10:15:49 +08:00
|
|
|
|
2021-12-10 17:52:11 +08:00
|
|
|
const INSTANCE_KEY = Symbol('ElLoading')
|
2021-09-12 18:33:24 +08:00
|
|
|
|
2021-12-10 17:52:11 +08:00
|
|
|
export type LoadingBinding = boolean | UnwrapRef<LoadingOptions>
|
2021-09-12 18:33:24 +08:00
|
|
|
export interface ElementLoading extends HTMLElement {
|
2021-12-10 17:52:11 +08:00
|
|
|
[INSTANCE_KEY]?: {
|
|
|
|
instance: LoadingInstance
|
|
|
|
options: LoadingOptions
|
|
|
|
}
|
2021-09-12 18:33:24 +08:00
|
|
|
}
|
|
|
|
|
2021-12-10 17:52:11 +08:00
|
|
|
const createInstance = (
|
|
|
|
el: ElementLoading,
|
|
|
|
binding: DirectiveBinding<LoadingBinding>
|
|
|
|
) => {
|
2021-01-15 13:56:59 +08:00
|
|
|
const vm = binding.instance
|
2021-12-10 17:52:11 +08:00
|
|
|
|
|
|
|
const getBindingProp = <K extends keyof LoadingOptions>(
|
|
|
|
key: K
|
|
|
|
): LoadingOptions[K] =>
|
|
|
|
isObject(binding.value) ? binding.value[key] : undefined
|
|
|
|
|
|
|
|
const resolveExpression = (key: any) => {
|
|
|
|
const data = (isString(key) && vm?.[key]) || key
|
|
|
|
if (data) return ref(data)
|
|
|
|
else return data
|
|
|
|
}
|
|
|
|
|
|
|
|
const getProp = <K extends keyof LoadingOptions>(name: K) =>
|
|
|
|
resolveExpression(
|
|
|
|
getBindingProp(name) ||
|
|
|
|
el.getAttribute(`element-loading-${hyphenate(name)}`)
|
|
|
|
)
|
|
|
|
|
|
|
|
const fullscreen =
|
|
|
|
getBindingProp('fullscreen') ?? binding.modifiers.fullscreen
|
|
|
|
|
|
|
|
const options: LoadingOptions = {
|
|
|
|
text: getProp('text'),
|
|
|
|
svg: getProp('svg'),
|
|
|
|
svgViewBox: getProp('svgViewBox'),
|
|
|
|
spinner: getProp('spinner'),
|
|
|
|
background: getProp('background'),
|
|
|
|
customClass: getProp('customClass'),
|
|
|
|
fullscreen,
|
|
|
|
target: getBindingProp('target') ?? (fullscreen ? undefined : el),
|
|
|
|
body: getBindingProp('body') ?? binding.modifiers.body,
|
|
|
|
lock: getBindingProp('lock') ?? binding.modifiers.lock,
|
|
|
|
}
|
|
|
|
el[INSTANCE_KEY] = {
|
|
|
|
options,
|
|
|
|
instance: Loading(options),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const updateOptions = (
|
|
|
|
newOptions: UnwrapRef<LoadingOptions>,
|
|
|
|
originalOptions: LoadingOptions
|
|
|
|
) => {
|
|
|
|
for (const key of Object.keys(originalOptions)) {
|
|
|
|
if (isRef(originalOptions[key]))
|
|
|
|
originalOptions[key].value = newOptions[key]
|
|
|
|
}
|
2021-01-15 13:56:59 +08:00
|
|
|
}
|
|
|
|
|
2021-12-10 17:52:11 +08:00
|
|
|
export const vLoading: Directive<ElementLoading, LoadingBinding> = {
|
|
|
|
mounted(el, binding) {
|
2021-09-17 15:27:31 +08:00
|
|
|
if (binding.value) {
|
2021-01-15 13:56:59 +08:00
|
|
|
createInstance(el, binding)
|
|
|
|
}
|
2020-10-23 10:15:49 +08:00
|
|
|
},
|
2021-12-10 17:52:11 +08:00
|
|
|
updated(el, binding) {
|
|
|
|
const instance = el[INSTANCE_KEY]
|
2020-10-23 10:15:49 +08:00
|
|
|
if (binding.oldValue !== binding.value) {
|
2021-12-10 17:52:11 +08:00
|
|
|
if (binding.value && !binding.oldValue) {
|
2021-01-15 13:56:59 +08:00
|
|
|
createInstance(el, binding)
|
2021-12-10 17:52:11 +08:00
|
|
|
} else if (binding.value && binding.oldValue) {
|
|
|
|
if (isObject(binding.value))
|
|
|
|
updateOptions(binding.value, instance!.options)
|
2020-10-23 10:15:49 +08:00
|
|
|
} else {
|
2021-12-10 17:52:11 +08:00
|
|
|
instance?.instance.close()
|
2020-10-23 10:15:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
2021-12-10 17:52:11 +08:00
|
|
|
unmounted(el) {
|
|
|
|
el[INSTANCE_KEY]?.instance.close()
|
2020-10-23 10:15:49 +08:00
|
|
|
},
|
|
|
|
}
|