uni-app 微信小程序父组件更新数组数据(不改变内容,深拷贝或重赋)后传递给子组件,子组件无法监听数据变化,h5无此问题。

uni-app 微信小程序父组件更新数组数据(不改变内容,深拷贝或重赋)后传递给子组件,子组件无法监听数据变化,h5无此问题。

开发环境 版本号 项目创建方式
Windows 10 HBuilderX

产品分类:uniapp/小程序/微信

PC开发环境操作系统:Windows

HBuilderX类型:正式
HBuilderX版本号:3.2.16
第三方开发者工具版本号:1.05.2110290
基础库版本号:2.21.1

项目创建方式:HBuilderX

示例代码:

父组件

<template>  
    <testitem v-model="list" />  
</template>  

<script>  
import testitem from './testitem/testitem.vue';  

export default {  
    components: { testitem },  
    data() {  
        return {  
            list: []  
        };  
    },  
    onLoad() {  
        this.list = [{ name: '1' }, { name: '2' }];  

        setInterval(() => {  
            this.list = this.list.map(item => {  
                // 强制更新数据后才能监听到变化  
                // item._i = Date.now();  
                return item;  
            });  
            console.log('父组件重新赋值', this.list);  
        }, 2000);  
    },  
    methods: {}  
};  
</script>

子组件

<template>  
    <view></view>  
</template>  

<script>  
export default {  
    props: {  
        value: {  
            type: Array,  
            default: () => {  
                return [];  
            }  
        }  
    },  
    watch: {  
        value: {  
            deep: true,  
            immediate: true,  
            handler: val => {  
                console.log('子组件监听变化', val);  
            }  
        }  
    }  
};  
</script>

操作步骤:

直接运行代码示例

预期结果:

在微信小程序中每隔2s应在控制台输出以下信息

父组件重新赋值 子组件监听变化


实际结果:

控制台没有输出 "子组件监听变化" 信息

bug描述:

微信小程序在父组件内更新数组数据后(不改变数组的数据,深拷贝或重新赋值时),将数据传给子组件,子组件监听不到父组件数据的变化,h5没有此问题。


更多关于uni-app 微信小程序父组件更新数组数据(不改变内容,深拷贝或重赋)后传递给子组件,子组件无法监听数据变化,h5无此问题。的实战教程也可以访问 https://www.itying.com/category-93-b0.html

11 回复

你这是语法就有问题,还是多学学吧。。。 父组件: <template> <testitem :value="list" /> </template>

更多关于uni-app 微信小程序父组件更新数组数据(不改变内容,深拷贝或重赋)后传递给子组件,子组件无法监听数据变化,h5无此问题。的实战教程也可以访问 https://www.itying.com/category-93-b0.html


<template> <testitem :value="list" /> </template>

这个是自定义v-model的写法啊! 打开注释可以验证下

回复 9***@qq.com: 你用一下我发的代码 看一下

回复 a***@foxmail.com: 一样的问题 https:https://www.itying.com/uniimg.php?url=https://img-cdn-tc.dcloud.net.cn/uploads/answer/20211216/120700795641ed6355184d74d5bb90b4.png https:https://www.itying.com/uniimg.php?url=https://img-cdn-tc.dcloud.net.cn/uploads/answer/20211216/2a94ea915b74477c267fb4aef5319512.png

。。。,你就当我没说吧

你环境版本是多少呀! 我的Hbuilder X 是: 3.2.16 微信开发者工具版本是:1.05.2110290

回复 9***@qq.com: 不是环境的问题,而是你的父组件修改数据的问题。建议你看下vue watch的实现原理

<style type="text/css"> acqui_pin { font-weight: 600; font-size: 28px; font-family: "黑体"; color: #8c888b; background: -webkit-linear-gradient(45deg, #ee0505, #fb5001, #ffd500, #3e00fa, #74ff03); -moz-linear-gradient(45deg, #70f7fe, #fbd7c6, #fdefac, #bfb5dd, #bed5f5); -ms-linear-gradient(45deg, #70f7fe, #fbd7c6, #fdefac, #bfb5dd, #bed5f5); color: transparent; -webkit-background-clip: text; animation: ran 10s linear infinite; } [@keyframes](/user/keyframes) ran { from { backgroud-position: 0 0; } to { background-position: 2000px 0; } } </style> <body>

。。。(●ˇ∀ˇ●)

</body>

这是一个典型的微信小程序数据响应式问题。在微信小程序中,由于底层实现机制与H5不同,当父组件重新赋值数组时,如果数组内容没有实际变化,子组件的watch可能无法触发。

问题分析:

  1. 微信小程序的响应式限制:微信小程序底层使用setData更新数据,当新赋值的数组与旧数组在内容上完全相同时,小程序可能不会触发更新通知
  2. Vue响应式原理差异:在H5环境下,Vue通过Proxy/Object.defineProperty能够检测到数组引用的变化,而微信小程序环境下的实现有所不同

解决方案:

方案1:强制创建新数组引用(推荐)

setInterval(() => {
    // 使用扩展运算符或slice创建全新的数组引用
    this.list = [...this.list];
    // 或 this.list = this.list.slice();
    console.log('父组件重新赋值', this.list);
}, 2000);

方案2:添加时间戳或唯一标识

setInterval(() => {
    this.list = this.list.map(item => {
        return { ...item, _timestamp: Date.now() };
    });
    console.log('父组件重新赋值', this.list);
}, 2000);

方案3:使用Vue.set或this.$set(如果数组内容需要更新)

setInterval(() => {
    // 如果需要更新数组中的某个元素
    this.$set(this.list, 0, { ...this.list[0], updated: true });
}, 2000);

方案4:在子组件中使用computed属性

<script>
export default {
    props: {
        value: {
            type: Array,
            default: () => []
        }
    },
    computed: {
        // 通过computed强制重新计算
        watchValue() {
            return JSON.parse(JSON.stringify(this.value));
        }
    },
    watch: {
        watchValue: {
            handler(val) {
                console.log('子组件监听变化', val);
            },
            immediate: true
        }
    }
};
</script>
回到顶部