提交 7eccb3f4 编写于 作者: D DCloud_LXH

feat: useAttrs

上级 e6ba5dad
import { getCurrentInstance, reactive, shallowRef, watchEffect } from 'vue'
type Hash<T> = {
[key: string]: T
}
function entries<T>(obj: Hash<T>): [string, T][] {
return Object.keys(obj).map((key: string) => [key, obj[key]])
}
interface Params {
excludeListeners?: boolean
excludeKeys?: string[]
}
const DEFAULT_EXCLUDE_KEYS = ['class', 'style']
const LISTENER_PREFIX = /^on[A-Z]+/
export const useAttrs = (params: Params = {}) => {
const { excludeListeners = false, excludeKeys = [] } = params
const instance = getCurrentInstance()
const attrs = shallowRef({})
const listeners = shallowRef({})
const excludeAttrs = shallowRef({})
const allExcludeKeys = excludeKeys.concat(DEFAULT_EXCLUDE_KEYS)
// Since attrs are not reactive, make it reactive instead of doing in `onUpdated` hook for better performance
instance!.attrs = reactive(instance!.attrs)
watchEffect(() => {
const res = entries(instance!.attrs).reduce(
(acc, [key, val]) => {
if (allExcludeKeys.includes(key)) {
;(acc.exclude as any)[key] = val
} else if (LISTENER_PREFIX.test(key)) {
if (!excludeListeners) {
;(acc.attrs as any)[key] = val
}
;(acc.listeners as any)[key] = val
} else {
;(acc.attrs as any)[key] = val
}
return acc
},
{
exclude: {},
attrs: {},
listeners: {},
}
)
attrs.value = res.attrs
listeners.value = res.listeners
excludeAttrs.value = res.exclude
})
return { $attrs: attrs, $listeners: listeners, $excludeAttrs: excludeAttrs }
}
......@@ -12,23 +12,3 @@ export function checkMinWidth(minWidth: number) {
]
return Math.max.apply(null, sizes) > minWidth
}
export function separateAttrs(attrs: Data) {
const ignore = ['style', 'class']
let $listeners: Data = {} // 事件
let $ignoreAttrs: Data = {} // ignore
let $otherAttrs: Data = {} // 事件 和 ignore
let $attrs: Data = {} // 除去 ignore 和 事件
for (const key in attrs) {
if (/^on[A-Z]+/.test(key)) {
$listeners[key] = attrs[key]
$otherAttrs[key] = attrs[key]
} else if (ignore.includes(key)) {
$ignoreAttrs[key] = attrs[key]
$otherAttrs[key] = attrs[key]
} else {
$attrs[key] = attrs[key]
}
}
return { $attrs, $otherAttrs, $listeners, $ignoreAttrs }
}
......@@ -14,10 +14,12 @@ import {
import { passive } from '@dcloudio/uni-shared'
import { useI18n, initI18nVideoMsgsOnce } from '@dcloudio/uni-core'
import { getRealPath } from '@dcloudio/uni-platform'
import { useSubscribe } from '@dcloudio/uni-components'
import { useCustomEvent } from '@dcloudio/uni-components'
import { useUserAction } from '@dcloudio/uni-components'
import { separateAttrs } from '../../../helpers/dom'
import {
useSubscribe,
useCustomEvent,
useUserAction,
useAttrs,
} from '@dcloudio/uni-components'
type CustomEventTrigger = ReturnType<typeof useCustomEvent>
type UserActionState = ReturnType<typeof useUserAction>['state']
......@@ -803,6 +805,9 @@ export default /*#__PURE__*/ defineComponent({
const containerRef = ref(null)
const trigger = useCustomEvent(rootRef, emit as SetupContext['emit'])
const { state: userActionState } = useUserAction()
const { $attrs: videoAttrs } = useAttrs({
excludeListeners: true,
})
const { t } = useI18n()
initI18nVideoMsgsOnce()
const {
......@@ -862,8 +867,6 @@ export default /*#__PURE__*/ defineComponent({
)
return () => {
const videoAttrs = separateAttrs(attrs).$attrs
return (
<uni-video ref={rootRef} id={props.id}>
<div
......@@ -886,7 +889,7 @@ export default /*#__PURE__*/ defineComponent({
src={videoState.src}
poster={props.poster}
autoplay={!!props.autoplay}
{...videoAttrs}
{...videoAttrs.value}
class="uni-video-video"
webkit-playsinline
playsinline
......
......@@ -7,10 +7,9 @@ import {
onDeactivated,
Teleport,
} from 'vue'
import { ResizeSensor } from '@dcloudio/uni-components'
import { ResizeSensor, useAttrs } from '@dcloudio/uni-components'
import { getRealPath } from '@dcloudio/uni-platform'
import { updateElementStyle } from '@dcloudio/uni-shared'
import { separateAttrs } from '../../../helpers/dom'
const props = {
src: {
......@@ -29,6 +28,9 @@ export default /*#__PURE__*/ defineComponent({
const rootRef: RootRef = ref(null)
const iframeRef: RootRef = ref(null)
const _resize = useWebViewSize(rootRef, iframeRef)
const { $attrs, $excludeAttrs, $listeners } = useAttrs({
excludeListeners: true,
})
onMounted(() => {
_resize()
......@@ -43,11 +45,13 @@ export default /*#__PURE__*/ defineComponent({
})
return () => {
const webViewAttrs = separateAttrs(attrs)
return (
<>
<uni-web-view {...webViewAttrs.$otherAttrs} ref={rootRef}>
<uni-web-view
{...$listeners.value}
{...$excludeAttrs.value}
ref={rootRef}
>
<ResizeSensor onResize={_resize} />
</uni-web-view>
......@@ -55,7 +59,7 @@ export default /*#__PURE__*/ defineComponent({
<iframe
ref={iframeRef}
src={getRealPath(props.src)}
{...webViewAttrs.$attrs}
{...$attrs.value}
></iframe>
</Teleport>
</>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册