最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to detect changes in property values in object in vue? - Stack Overflow

programmeradmin1浏览0评论

On top of How to watch only after the initial load from API in VueJS?, I wanted to detect any changes in values of the properties in the json object.

Initially the user object is

user: {
        userId: 0,
        id: 0,
        title: "",
        pleted: false,
      },

I have two input fields,

 <input type="text" v-model="user.userId" /> <br />
 <input type="text" v-model="user.title" /> <br />

and a button <button :disabled="isLoaded">Update</button>

If none of the input values changed, the button should be still disabled. Example, if the userId is changed to 1, the button should be enabled but if the value is changed back to 0, the button should be disabled. I referred Vue js pare 2 object and remove differences in watcher and I tried following but failed.

<template>
  <div id="app">
    <div v-if="!isFetching">
      <input type="text" v-model="user.userId" /> <br />
      <br />
      <input type="text" v-model="user.title" /> <br />
      <br />
      <button :disabled="isLoaded">Update</button>
    </div>
    <div v-else>Loading...</div>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      user: {
        userId: 0,
        id: 0,
        title: "",
        pleted: false,
      },
      isFetching: false,
      isLoaded: true,
    };
  },
  watch: {
    user: {
      handler(oldVal, newVal) {
        this.checkObject(oldVal, newVal);
      },
      deep: true,
    },
  },
  methods: {
    checkObject: (obj1, obj2) => {
      const isEqual = (...objects) =>
        objects.every(
          (obj) => JSON.stringify(obj) === JSON.stringify(objects[0])
        );
      console.log(obj1, obj2);
      console.log(isEqual(obj1, obj2));
    },
  },
  created() {
    this.isFetching = true;
    fetch(";)
      .then((response) => response.json())
      .then((json) => {
        this.user = json;
        this.isLoaded = true;
      })
      .finally(() => (this.isFetching = false));
  },
};
</script>

Here's a live demo: ;hidenavigation=1&theme=dark

On top of How to watch only after the initial load from API in VueJS?, I wanted to detect any changes in values of the properties in the json object.

Initially the user object is

user: {
        userId: 0,
        id: 0,
        title: "",
        pleted: false,
      },

I have two input fields,

 <input type="text" v-model="user.userId" /> <br />
 <input type="text" v-model="user.title" /> <br />

and a button <button :disabled="isLoaded">Update</button>

If none of the input values changed, the button should be still disabled. Example, if the userId is changed to 1, the button should be enabled but if the value is changed back to 0, the button should be disabled. I referred Vue js pare 2 object and remove differences in watcher and I tried following but failed.

<template>
  <div id="app">
    <div v-if="!isFetching">
      <input type="text" v-model="user.userId" /> <br />
      <br />
      <input type="text" v-model="user.title" /> <br />
      <br />
      <button :disabled="isLoaded">Update</button>
    </div>
    <div v-else>Loading...</div>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      user: {
        userId: 0,
        id: 0,
        title: "",
        pleted: false,
      },
      isFetching: false,
      isLoaded: true,
    };
  },
  watch: {
    user: {
      handler(oldVal, newVal) {
        this.checkObject(oldVal, newVal);
      },
      deep: true,
    },
  },
  methods: {
    checkObject: (obj1, obj2) => {
      const isEqual = (...objects) =>
        objects.every(
          (obj) => JSON.stringify(obj) === JSON.stringify(objects[0])
        );
      console.log(obj1, obj2);
      console.log(isEqual(obj1, obj2));
    },
  },
  created() {
    this.isFetching = true;
    fetch("https://jsonplaceholder.typicode./todos/1")
      .then((response) => response.json())
      .then((json) => {
        this.user = json;
        this.isLoaded = true;
      })
      .finally(() => (this.isFetching = false));
  },
};
</script>

Here's a live demo: https://codesandbox.io/embed/friendly-hopper-ynhxc?fontsize=14&hidenavigation=1&theme=dark

Share Improve this question asked Nov 8, 2021 at 21:03 user16583522user16583522 4
  • 1 You could create a puted value with the given logic to evaluate whether disabled shall be true or false. puted: { disabled() { return //elaborated function which checks all necessary information }} and then bind it on the item :disabled="disabled" – D.Schaller Commented Nov 8, 2021 at 21:09
  • 1 FWIW, the problem with the answer you picked is that it adds plexity but doesn't solve problems with a watcher. You still use isLoaded property that serves no good purpose. – Estus Flask Commented Nov 8, 2021 at 21:09
  • @EstusFlask can you suggest a way? I am too confused – user16583522 Commented Nov 9, 2021 at 23:01
  • Loading state can be handled like I showed in previous answer, there's no need for a watcher for it. You preferably shouldn't enable a form before data is loaded, if a user starts to fill the form and then it's changed when initial data arrives, this results in bad UX. As for form changes, it's like current answer shows. You need to copy user and pare against it. – Estus Flask Commented Nov 10, 2021 at 8:18
Add a ment  | 

1 Answer 1

Reset to default 4

Here is one way you could solve this. So below I'm storing two user objects, one is my base line parison pareUser, and the other is the user that is under edit. When something changes which the deep watch on user will notify me about, I use a utility function like isEqual from lodash to perform a semantic parison of the base line object and the current user object, and see if there are any differences.

If I want to update my base line that I'm paring to, then I update the pareUser from the current user by cloning it.

You can of course replace things like isEqual and cloneDeep by rolling your own to avoid the extra library if that's an issue.

<script>
import { isEqual, cloneDeep } from "lodash";

const createDefault = function () {
  return {
    userId: 0,
    id: 0,
    title: "",
    pleted: false,
  };
};

export default {
  name: "App",
  data() {
    return {
      pareUser: createDefault(),
      user: createDefault(),
      isLoaded: false,
      isDifferent: false,
    };
  },
  watch: {
    user: {
      handler() {
        this.isDifferent = !isEqual(this.user, this.pareUser);
      },
      deep: true,
    },
  },
  methods: {
    setCompareUser(user) {
      this.pareUser = cloneDeep(user);
      this.isDifferent = false;
    },
  },
  async created() {
    const response = await fetch(
      "https://jsonplaceholder.typicode./todos/1"
    );
    const user = await response.json();
    this.user = user;
    this.setCompareUser(user);
    this.isLoaded = true;
  },
};
</script>

Demo: https://codesandbox.io/s/modern-tdd-yg6c1

发布评论

评论列表(0)

  1. 暂无评论