You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Vue.js与Nuxt.js页面加载后向组件传递数据无法正常渲染的问题咨询

问题分析与解决方案

这个问题我之前开发Vue项目时也碰到过,核心原因是异步数据加载和组件生命周期的时机不匹配,具体来说:

父组件的mounted钩子中是异步调用getUsersSettings获取数据,但子组件的mounted钩子会比父组件异步请求完成的时间更早执行——因为初始时currentSection === 'Public account'为true,子组件会立刻挂载。这时候父组件的personalSettings还是空对象,子组件把这个空对象赋值给了personalInfo

等父组件异步请求完成、personalSettings更新后,子组件的props虽然会变化,但data里的personalInfo是初始化时赋值的,不会自动跟着props更新。只有当你切换标签页时,子组件被v-if销毁后重新挂载,此时mounted再次执行,personalSettings已经有了完整数据,personalInfo才能拿到正确值,视图也就正常显示了。


修复方案(三种可选,推荐第一种)

方案1:监听props变化,同步更新personalInfo

在子组件中添加watch监听personalSettings的变化,当父组件数据更新时,自动同步到子组件的personalInfo中。如果是复杂对象,记得做深拷贝避免引用问题:

// 子组件的script部分
props: {
  personalSettings: {
    type: Object,
    default: () => {}
  }
},
data() {
  return {
    personalInfo: {},
    loading: false,
    showPopup: false
  }
},
watch: {
  personalSettings: {
    handler(newVal) {
      // 深拷贝避免直接修改父组件数据
      this.personalInfo = JSON.parse(JSON.stringify(newVal));
    },
    immediate: true, // 初始化时立即执行一次,确保首次加载就同步数据
    deep: true // 如果对象有嵌套属性,开启深度监听
  }
},
// 可以去掉原来的mounted赋值了,watch的immediate已经处理了初始化逻辑
// mounted() {
//   this.personalInfo = this.personalSettings
// }

方案2:用computed实现双向绑定(适合需要修改数据的场景)

如果需要在子组件中修改数据并同步回父组件,可以用带get/set的computed代替data,避免维护副本:

// 子组件的script部分
props: {
  personalSettings: {
    type: Object,
    default: () => {}
  }
},
computed: {
  personalInfo: {
    get() {
      return this.personalSettings;
    },
    set(newVal) {
      // 通过$emit通知父组件更新数据
      this.$emit('update:personalSettings', newVal);
    }
  }
}

然后父组件中使用.sync修饰符实现双向绑定:

<personal-information v-if="currentSection === 'Public account'" :personal-settings.sync="personalSettings" />

方案3:延迟渲染子组件,确保数据就绪后再挂载

在父组件的子组件v-if条件中,加上数据存在的判断,确保只有当personalSettings有数据时才渲染子组件:

<personal-information v-if="currentSection === 'Public account' && Object.keys(personalSettings).length" :personal-settings="personalSettings" />

这样子组件的mounted钩子执行时,personalSettings已经是完整的对象,直接赋值给personalInfo就能正常显示数据了。


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

火山引擎 最新活动