useAttrs().style and useAttrs().class - How to bind attrs.style and attrs.class to external HTMLDivElement instance?
#14555
Replies: 2 comments 1 reply
-
|
@rtcpw Nice integration scenario. Since that div is created outside Vue template rendering, fallthrough attrs (class / style) are not auto-applied there. Practical approach:
That keeps Vue as source-of-truth while still supporting third-party DOM ownership. References: |
Beta Was this translation helpful? Give feedback.
-
|
Vue does have normalization helpers for this, but I would be careful about treating them as a public “apply this to any DOM element” API. For classes, import { normalizeClass } from "vue";
div.className = normalizeClass(attrs.class);For styles, import { normalizeStyle } from "vue";
const normalized = normalizeStyle(attrs.style);Then you can apply it manually: import { normalizeClass, normalizeStyle, watchEffect } from "vue";
watchEffect(() => {
const el = div.value;
if (!el) {
return;
}
el.className = normalizeClass(attrs.class);
const style = normalizeStyle(attrs.style);
el.removeAttribute("style");
if (typeof style === "string") {
el.style.cssText = style;
} else if (style) {
for (const [key, value] of Object.entries(style)) {
if (value == null) {
continue;
}
el.style.setProperty(
key.startsWith("--")
? key
: key.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`),
String(value),
);
}
}
});That said, the more Vue native approach is to let Vue render a small wrapper element and pass that actual DOM element to the mapping library: <script setup lang="ts">
import { ref, onMounted } from "vue";
const el = ref<HTMLDivElement>();
onMounted(() => {
if (!el.value) {
return;
}
mapLibrary.useElement(el.value);
});
</script>
<template>
<div ref="el" />
</template>Then consumers can use normal Vue bindings: <MapDiv
:class="{ active: isActive }"
:style="{ width: '100px', height: '100px' }"
/>If the library absolutely requires you to create the element yourself with The short version is: use |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
I have created a native div element:
I need to create an element like this because of the third-party mapping library that I use.
I would like to use Vue's
:classand:stylebinding to bind the class/style to this element. To achieve this, I have wrapped thedivelement above in a custom component, and useduseAttrstogether withdefineOptionsto grab the attributes:The
attrs.styleis of typeStyleValue, andattrs.classis of typeClassValue:I have not found a way to easily take
attrs.classandattrs.styleand bind it to thediv(HTMLDivElement) above. Is there any utility function or perhaps some other approach I could take to achieve this?Alternatively, is there a utility function that would convert these rather complex types (which are not the easiest to work with manually), and turn them into something easier to digest, eg. a simple
Record<string, string>in the case ofattrs.style, and perhapsSet<string>in case ofattrs.class? This would at least give me the option to loop over these objects and calldiv.style.setPropertymyself.Beta Was this translation helpful? Give feedback.
All reactions