【问题标题】:Vue: Accessing data from an unmounted componentVue:从未安装的组件访问数据
【发布时间】:2018-08-09 18:55:30
【问题描述】:

我有一个问题,我想从子组件中检索数据,但父组件需要使用该数据,子组件被挂载。

我的父母长这样

<template>
    <component :is="childComp" @mounted="setData"/>
</template>
<script>
    data : {
        childComp : null,
        importantData : null
    },
    methods : {
        addComponent : function() {
            this.prepareToAdd(this.importantData);
            this.childComp = "componentA"; //sometimes will be other component
        },
        setData : function(value) {
            this.importantData = value;
        },
        prepareToAdd : function(importantData){
            //something that has to be run before childComp can be mounted.
        }
    }
</script>

我的孩子(或者更确切地说,所有潜在的孩子)会包含这样的内容:

<script>
    data : {
        importantData : 'ABC',
    },
    created: function() {
        this.$emit('mounted', this.importantData);
    },
</script>

这显然行不通 - importantData 是在子组件挂载时设置的,但 prepareToAdd 首先需要该数据。

在挂载之前,是否有其他方法可以访问子组件并访问其数据?

【问题讨论】:

  • 为什么要将检索数据的责任委托给子组件而不是父组件?
  • 您能更清楚地描述一下需求是什么吗?父母是否在自己的状态下设置了一些东西?将作为道具传递给孩子的东西? DOM中的东西?为什么需要在孩子挂载之前运行?

标签: javascript vue.js vue-component


【解决方案1】:

您可以使用$options 来存储您的重要数据并在beforeCreate 中提供。您还可以使用它来初始化data 项目,并且可以在created 中发出data 项目(您不必从$options 初始化以在created 中发出,我只是指出可以做的两件事)。 $options 值本身是响应式的(令我惊讶的是),可以像任何 data 项目一样使用,另外还有一个好处是它可以在其他 data 项目之前使用。

new Vue({
  el: '#app',
  methods: {
    doStuff(val) {
      console.log("Got", val);
    }
  },
  components: {
    theChild: {
      template: '<div>Values are {{$options.importantData}} and {{otherData}}</div>',
      importantData: 'abc',
      data() {
        return {
          otherData: this.$options.importantData
        };
      },
      beforeCreate() {
        this.$emit('before-create', this.$options.importantData);
      },
      created() {
        this.$emit('on-created', this.otherData + ' again');
        // It's reactive?!?!?
        this.$options.importantData = 'changed';
      }
    }
  }
});
<script src="//unpkg.com/vue@latest/dist/vue.js"></script>
<div id="app">
  <the-child @before-create="doStuff" @on-created="doStuff"></the-child>
</div>

【讨论】:

  • 太棒了!非常感谢,这正是我所追求的。
【解决方案2】:

我的错:(

我们无法在 beforeCreated() 钩子中获取数据。

使用 beforeCreate() 钩子而不是 created() 钩子:

beforeCreate: function() {
   this.$emit('mounted', this.importantData);
},

我们可以使用观察者或计算选项,所以现在你的父组件看起来:

data: {
  childComp: null,
  importantData: null,
  isDataSet: false
 },
 methods: {
  addComponent: function() {
   this.prepareToAdd(this.importantData);
   this.childComp = "componentA"; //sometimes will be other component
  },
  setData: function(value) {
   this.importantData = value;
   this.isDataSet = true;
  },
  prepareToAdd: function(importantData) {
   //something that has to be run before childComp can be mounted.
  }
 },
 watch: {
  isDataSet: function(newValue, oldValue) {
   if (newValue) {
    this.addComponent();
   }
  }
 }

我建议使用计算方法,因为它会缓存结果。当你必须执行异步代码时使用 watcher。

【讨论】:

  • 这不会有同样的问题 - importantData 是在安装 childComponent 时设置的
  • importantData 在子级发出 mounted 事件时设置。这是在孩子的beforeCreate 钩子中完成的。
  • 我以为data 中的孩子直到create 钩子才被初始化?看看heresetData在使用beforeCreate时得到null
  • @sklingler93 你是对的,beforeCreate 钩子不是办法......更新了我的答案。
猜你喜欢
  • 2018-08-03
  • 2017-10-17
  • 2020-07-23
  • 2018-11-03
  • 2020-06-15
  • 2019-11-05
  • 2022-01-22
  • 1970-01-01
  • 2016-08-14
相关资源
最近更新 更多