You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Petite-Vue过滤数组及元素更新时reactivity失效,UI不更新求助

Petite-Vue响应式数组元素更新不触发UI重渲染问题

我认可Petite-Vue的响应式(reactivity)、UI更新能力,以及$el、$refs这类便于表单处理与数据绑定的工具。目前我在实现一个基于GunDB后端数据变更的实时响应式列表时遇到了问题:

  • 使用v-for渲染全部数组元素时,UI更新正常;
  • 但通过players.filter(...)按玩家的team属性过滤数组后,初始渲染正确,当玩家名称变更同步到Petite-Vue.reactive创建的players数组后,UI却不触发更新(元素已为Proxy对象)。

我已尝试在组件内使用getter、方法,以及直接在模板中写players.filter(...),均未解决问题。

同步GunDB后端变更到Petite-Vue响应式对象的函数

gunArray2vue = (gunNode, vueArray) => {
    gunNode.map().on((value, soul) => {
        item = vueArray.find(item => item && item._ && item._['#'] === soul)
        console.log('gunArray2vue', `soul=${soul}`, value, item)
        
        if(!!item && value === null) {
            // item in VUE but seems deleted... remove from vue array...
            console.log("ToDeleteItem", item)
            vueArray.splice(vueArray.indexOf(item), 1)
        } else if(!value) {
            console.log("Ignore creation of empty object")
            return // don't add empty object...
        } else if(item) {   
            //vueArray[vueArray.indexOf(item)] = value // update
            console.log("UpdateItem")
            item = value                // update                        
        } else {
            console.log("AddArrayItem")
            vueArray.push(value)        // add new
        }
    })
}

控制台已确认值已变更,但UI未刷新。

组件内测试的getter代码

//filteredPlayers: function() {
get filteredPlayers() {
    if(this.form.nr || this.form.name) {
        return this.players.filter(player =>
            player.name.includes(this.form.name) || player.nr == this.form.nr
        )
    } else {
        return this.players
    }
}

过滤对输入字段是响应式的,但名称变更被忽略。即使使用简单的getter:

get myPlayers() {
    page.players
}

元素变更时UI也不更新,仅刷新页面才生效。直接渲染未过滤的响应式对象:

<div v-for="player in page.players">{{player.nr}} {{player.name}}</div>

初始渲染正常,但元素变更时同样不更新。


更新1:测试发现直接修改原响应式对象page.players能触发更新,但使用该响应式对象的引用则不行,难道使用引用会丢失元素变更的响应性?

更新2:增删响应式数组元素正常,仅更新元素无效。我尝试了多种修改元素对象/键值的方式,均无响应:

gun2arrayListener = (name, table) => {
    console.log(`Register Listener Gun table "${name}"`)
    DB.get(name).map().on((value, soul) => {
        console.log("DEBUG", soul, value)
        item = table.find(item => item?._['#'] === soul)
        index = table.indexOf(item)
        console.log('gun2array', `soul=${soul}`, value, item)
        if(Object.is(item, value)) {
            console.log("Skip unchanged item")
        } else if(item && value === null) {
            console.log("ToDeleteItem", item)
            table.splice(index, 1)
        } else if(!value) {
            console.log("Ignore creation of empty object?!")
        } else if(item) {   
            console.log("UPDATE", "ARRAY", item, value)
            // !!! CHANGES NOT REACTIVE HERE !!!
            // !!!  method is triggered, changes looks good, but reload page needed to update UI !!!
            //item = value
            //TABLES[name][index] = value
            //Object.assign(item, value)
            //table.splice(index, 1, value)
            //table.splice(index, 1); table.push(value)
            for (const [key, val] of Object.entries(value)) {
                console.log(`${key}: ${val}`)
                //item[key] = val
                store.players[index][key] = val
                console.log(item)
            }
        } else {
            console.log("AddNewGunNodeItem", value)
            table.push(value)        // add new
        }
    })
}

奇怪的是,外部直接修改能触发响应性:

store.players[0].name = "BUM!"  // works as needed in function... ?!

我注意到Gun会触发两次监听器,但这应该只会让数组对象更新两次到正确值。另外,由于旧对象是Vue Proxy,新对象是普通对象,无法用Object.is比较来跳过未变更的对象。

请问如何触发过滤后的响应式对象数组变更时的UI重渲染?


内容的提问来源于stack exchange,提问作者pwFoo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 18:27:30