[Vuejs]-How to put return value into another return value in JS vue

1👍

There are several problems here.

The data function is called just once, when the corresponding Vue instance is created. Within that function you can get a reference to its Vue instance via this. At that point some properties, such as those corresponding to props, will already exist. However, others won’t.

The object returned from data is used to create new properties on the instance. In this case you’re creating 4 properties: topic1, topic2, currentBreed and breeds. Vue creates those properties based on that returned object, so they won’t exist until after the data function is run.

So when you write { name: this.topic1 , key: this.topic1 }, within that data function you’re attempting to access a property called topic1 that doesn’t exist yet. As such it will have a value of undefined. So you’re creating an entry equivalent to { name: undefined , key: undefined },.

Further, there is no link back to topic1. That object won’t be updated when the value of topic1 changes.

It’s also worth noting a few points about timing.

  1. The data function will be called before the created hook, so the axios call isn’t made until after the data properties are populated.
  2. An axios call is asynchronous.
  3. Using await may make the code a little easier to read but the ‘waiting’ is mostly just an illusion. The remaining code inside the function won’t run until the awaited promise is resolved but that won’t cause anything outside of the function to wait. await is equivalent to using then.
  4. The component will render just after the created hook is called. This is synchronous, it won’t wait for the axios request. The mounted hook will then be called, all before the axios call has completed.

All of this means you may need to adjust your template to handle the case where the axios call hasn’t completed yet as it will initially render prior to the values of topic1 and topic2 being available.

Specifically addressing the breeds property you have a few options. One is to inject the values in once the value has loaded:

breeds: [
  { name: "" , key: "" }, // Initially empty values
  { name: "German Shepherd", key: "germanshepherd" },
  // ...
const res = await this.promise;
this.topic1 = res.data[0].Trends;
this.topic2 = res.data[1].Trends;  
this.breeds[0].name = this.breeds[0].key = this.topic1;

Another is to use a computed property for breeds (you’d remove it from the data for this):

computed: {
  breeds () {
    return [
      { name: this.topic1 , key: this.topic1 },
      { name: "German Shepherd", key: "germanshepherd" },
      { name: "Husky", key: "husky" },
      { name: "Pug", key: "pug" },
      { name: "(Error)", key: "error" },
    ]
  }
}

As we’re using a computed property it will be updated when topic1 changes as it’s a reactive dependency.

Using a computed property is probably the most natural solution in this case but there are other tricks you can use to get this to work.

For example, you could use property getters for the two properties in that first breed object (that’s JavaScript property getters, nothing to do with Vue):

data () {
  const vm = this;

  return {
    topic1: null,
    topic2: null,

    currentBreed: 0,
    breeds: [
      {
        get name () {
          return vm.topic1;
        },

        get key () {
          return vm.topic1;
        }
      },
      { name: "German Shepherd", key: "germanshepherd" },
      { name: "Husky", key: "husky" },
      { name: "Pug", key: "pug" },
      { name: "(Error)", key: "error" },
    ]
  }
},

I’m not advocating this approach for your use case but it is an interesting way to do it that can sometimes be useful. The key thing to note is how the dependency on topic1 is evaluated only when the properties name and key are accessed, not when the data function is executed. This allows topic1 to be registered as a dependency of whatever is accessing name and key, e.g. during rendering.

Leave a comment