Vue3中如何简化模板与代码里深层对象的长命名?
Vue3 简化深层对象长命名的正确姿势
问题根源
你遇到的toRefs解构后值为空的问题,核心是属性名不匹配:buttons.btnCancel的原始属性是inactive、inactiveClass、activeClass,而非你写的btnCancelInactive这类拼接后的名字,所以解构出来的变量对应了不存在的key,自然为空。
正确的响应式简化方案
方案1:toRefs解构+重命名(推荐)
通过toRefs解构原始属性,同时重命名为短变量,既保留响应式,又简化命名:
const { inactive: btnCancelInactive, inactiveClass: btnCancelInactiveClass, activeClass: btnCancelActiveClass } = toRefs(buttons.btnCancel)
这种方式下,所有变量都是响应式的ref对象,模板中可以直接使用,和你原本的模板代码完全兼容。
方案2:直接返回嵌套对象简化路径
如果不想解构,也可以把buttons.btnCancel直接返回给模板,因为reactive的嵌套属性本身就是响应式的:
const btnCancel = buttons.btnCancel // 返回时加入 return { // ...其他变量 btnCancel }
模板中直接简化路径:
<button :class="[btnCancel.inactive ? btnCancel.inactiveClass : btnCancel.activeClass]" type="button" @click.stop="clearSearch" > <i class="fas fa-x"></i> </button>
方案3:computed封装(适合带逻辑的场景)
如果需要对按钮状态或样式做逻辑转换,用computed封装更简洁:
const { computed } = Vue; const isBtnCancelInactive = computed(() => buttons.btnCancel.inactive) const btnCancelClass = computed(() => { return buttons.btnCancel.inactive ? buttons.btnCancel.inactiveClass : buttons.btnCancel.activeClass })
模板中直接使用封装后的变量:
<button :class="btnCancelClass" type="button" @click.stop="clearSearch" > <i class="fas fa-x"></i> </button> sss {{isBtnCancelInactive}}
修改后的完整代码
以下是用方案1修正后的完整代码:
//vueAddItemPanel.js const template = ` <div class="input-group input-group-sm"> <input type="text" class="form-control" placeholder="Select a role to add..." ref="searchInputRef" v-model="searchText" > <button class="btn disabled text-muted" type="button"> <i class="fas fa-check"></i></button> <button :class="[btnCancelInactive ? btnCancelInactiveClass : btnCancelActiveClass]" type="button" @click.stop="clearSearch"> <i class="fas fa-x"></i></button> </div> sss {{btnCancelInactive}} ` const {ref, reactive, watch, toRefs, } = Vue; const vueAddItemPanel = { setup(props, ctx) { const searchText = ref('') const searchInputRef = ref(null) const buttons = reactive({ btnCancel : { inactive : true, inactiveClass : "btn btn-outline-secondary disabled text-muted", activeClass : "btn btn-outline-secondary" } }) // 正确匹配原始属性名并重命名 const { inactive: btnCancelInactive, inactiveClass: btnCancelInactiveClass, activeClass: btnCancelActiveClass } = toRefs(buttons.btnCancel) // note: debounce is from lodash const debouncedSearch = _.debounce(() => { ctx.emit('searchChanged', searchText.value) }, 500) watch( searchText, () => { buttons.btnCancel.inactive = searchText.value.trim() === '' debouncedSearch() }) const clearSearch = () => { searchText.value = '' searchInputRef.value.focus() buttons.btnCancel.inactive = true } return { searchText, clearSearch, debouncedSearch, searchInputRef, btnCancelInactive, btnCancelInactiveClass, btnCancelActiveClass, } }, template: template, } export default vueAddItemPanel
关键注意事项
toRefs只能解构对象的原始属性名,否则会得到空的ref对象- 普通对象解构会丢失响应式,因为
reactive对象解构后会变成普通值,而非响应式ref reactive的嵌套属性本身就是响应式的,直接返回嵌套对象是最简单的路径简化方式
内容的提问来源于stack exchange,提问作者JeffP
相关产品推荐
相关产品推荐

