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
相关产品推荐
相关产品推荐

