Joseph
Joseph

Reputation: 4705

Can I assign Vue.js data property to a local variable along with it's setter?

Please see this minimum example:

<template>
  <div>
    {{ count }}
    <button @click="click">Click</button>
  </div>
</template>

<script>

export default {
  data() {
    return {
      count: 0
    }
  },
  methods: {
    click() {
      this.count++
    }
  }
};
</script>

I have a count data property and a button that will increase the count.

Now, I want to do this a little differently like this(for some reason)

click() {
  let count = this.count
  count += 1
}

I want to assign my data property to my local variable first, and then increase the local variable count, and hopefully, triggers Vue's reactivity.

I know Vue use Object.defineProperty's setter to data property, how can I clone those setters?

Is it possible to do this?

Update

What I want to do is trying to simplify below code

<script lang="ts">
export default {
  data() {
    return {
      isALoading: false,
      isBLoading: false
    };
  },
  methods: {
    hitAPI(type: "A" | "B") {
      if (type === "A") {
        this.isALoading = true;
        fetch(someAPI)
          .then(() => {
            this.isALoading = false;
          })
          .catch(() => {
            this.isALoading = false;
          });
      } else {
        this.isBLoading = true;
        fetch(someAPI)
          .then(() => {
            this.isBLoading = false;
          })
          .catch(() => {
            this.isBLoading = false;
          });
      }
    }
  }
};
</script>

Upvotes: 1

Views: 443

Answers (1)

Decade Moon
Decade Moon

Reputation: 34286

It's not possible to "copy" a setter like that into a local variable.

You can abstract the property behind a method or another object with its own setter:

click() {
  const self = this
  const wrapper = {
    get count() { return self.count },
    set count(x) { self.count = x }
  }

  wrapper.count++
}

I sense this is an XY problem; why do you want to do this? What are you trying to achieve?

You are best to just reassign back the local variable to the data property to trigger the update:

click() {
  let count = this.count

  // Modify local var
  count++

  // Assign back to trigger the update
  this.count = count
}

UPDATE

You can dynamically access the property by its string name:

hitAPI(type: "A" | "B") {
  const prop = type === "A" ? "isALoading" : "isBLoading"
  this[prop] = true

  fetch(someAPI).finally(() => {
    this[prop] = false
  })
}

Alternatively with async/await:

async hitAPI(type: "A" | "B") {
  const prop = type === "A" ? "isALoading" : "isBLoading"
  this[prop] = true

  try {
    await fetch(someAPI)
  } finally {
    this[prop] = false
  }
}

Upvotes: 1

Related Questions