What Causes This Warning?
This warning occurs when you try to modify the attrs object from the setup context. The attrs object is reactive and readonly - it reflects attributes passed from the parent but cannot be directly modified.
The Problem
export default {
setup(props, { attrs }) {
// ❌ Trying to modify attrs
attrs.class = 'new-class'
delete attrs.id
}
}
The Fix
Copy Attrs When Needed
export default {
setup(props, { attrs }) {
// ✅ Create a copy if you need to modify
const modifiedAttrs = { ...attrs }
modifiedAttrs.class = 'modified-class'
return () => h('div', modifiedAttrs, 'Content')
}
}
Use Computed for Derived Attrs
<script setup>
import { computed, useAttrs } from 'vue'
const attrs = useAttrs()
// ✅ Computed property for modified attrs
const enhancedAttrs = computed(() => ({
...attrs,
class: `enhanced ${attrs.class || ''}`
}))
</script>
Common Scenarios
Adding Default Classes
<script setup>
import { computed, useAttrs } from 'vue'
const attrs = useAttrs()
// ✅ Merge with default classes
const buttonAttrs = computed(() => ({
...attrs,
class: ['btn', 'btn-primary', attrs.class].filter(Boolean).join(' ')
}))
</script>
<template>
<button v-bind="buttonAttrs">
<slot />
</button>
</template>
Filtering Attrs
<script setup>
import { computed, useAttrs } from 'vue'
const attrs = useAttrs()
// ✅ Filter out specific attributes
const filteredAttrs = computed(() => {
const { class: _, style: __, ...rest } = attrs
return rest
})
const styleAttrs = computed(() => ({
class: attrs.class,
style: attrs.style
}))
</script>
<template>
<div v-bind="styleAttrs">
<input v-bind="filteredAttrs" />
</div>
</template>
Options API
export default {
inheritAttrs: false,
setup(props, { attrs }) {
// ✅ Return function that uses attrs reactively
return () => {
const mergedAttrs = {
...attrs,
'data-custom': 'value'
}
return h('div', mergedAttrs, 'Content')
}
}
}
Watching Attrs
<script setup>
import { useAttrs, watch } from 'vue'
const attrs = useAttrs()
// ✅ You can watch attrs (they're reactive)
watch(() => attrs.class, (newClass) => {
console.log('Class changed:', newClass)
})
</script>
Quick Checklist
- Never directly modify
attrs - Use spread operator to create copies
- Use computed for reactive derived attrs
-
attrsis reactive, so it updates automatically - Use
useAttrs()in script setup