首页 > 解决方案 > 如何在vue中检测对象中属性值的变化?

问题描述

仅在从VueJS中的 API 初始加载之后如何观看?,我想检测 json 对象中属性值的任何变化。

最初的用户对象是

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

我有两个输入字段,

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

和一个按钮<button :disabled="isLoaded">Update</button>

如果输入值均未更改,则该按钮仍应处于禁用状态。例如,如果 userId 更改为 1,则应启用按钮,但如果将值更改回 0,则应禁用按钮。我提到了 Vue js 比较 2 个对象并删除了观察者中的差异,我尝试了以下但失败了。

<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: "",
        completed: 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.com/todos/1")
      .then((response) => response.json())
      .then((json) => {
        this.user = json;
        this.isLoaded = true;
      })
      .finally(() => (this.isFetching = false));
  },
};
</script>

这是一个现场演示:https ://codesandbox.io/embed/friendly-hopper-ynhxc?fontsize=14&hidenavigation=1&theme=dark

标签: javascriptvue.js

解决方案


这是您可以解决此问题的一种方法。所以下面我存储了两个用户对象,一个是我的基线比较compareUser,另一个是user正在编辑的。当深度观察user会通知我的某些变化时,我使用isEqual来自 lodash 之类的实用函数来执行基线对象和当前用户对象的语义比较,并查看是否有任何差异。

如果我想更新我正在比较的基线,那么我通过克隆它来更新compareUser当前的基线。user

如果这是一个问题,您当然可以通过滚动自己来替换类似的东西isEqual以避免额外的库。cloneDeep

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

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

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

演示: https ://codesandbox.io/s/modern-tdd-yg6c1


推荐阅读