Home > Software engineering >  Why computed property works on preserving the reactivity but attributes in data() {} does not
Why computed property works on preserving the reactivity but attributes in data() {} does not

Time:10-21

I'm following this tutorial, where they point out a small bug with the checkbox status of forgetting the state of the ticked/unticked which can be solved by using the computed property.

I would like to ask, even if the attribute isDone in Data (ToDoItem.vue) has been changed to true (by ticking the checkbox), why the box is still unticked after clicking edit then cancel, and why computed property could solve this bug.

Below are parts of the scripts.

ToDoItem.vue

    <template>
  <div  v-if="!isEditing">
    <div >
      <input
        type="checkbox"
        
        :id="id"
        :checked="isDone"
        @change="$emit('checkbox-changed')"
      />
      <label :for="id" >{{ label }}</label>
    </div>
    <div >
      <button
        type="button"
        
        ref="editButton"
        @click="toggleToItemEditForm"
      >
        Edit <span >{{ label }}</span>
      </button>
      <button type="button"  @click="deleteToDo">
        Delete <span >{{ label }}</span>
      </button>
    </div>
  </div>
  <to-do-item-edit-form
    v-else
    :id="id"
    :label="label"
    @item-edited="itemEdited"
    @edit-cancelled="editCancelled"
  ></to-do-item-edit-form>
</template>

<script>
import ToDoItemEditForm from "./ToDoItemEditForm";

export default {
  components: {
    ToDoItemEditForm,
  },

  props: {
    label: { required: true, type: String },
    done: { default: false, type: Boolean },
    id: { required: true, type: String },
  },

  data() {
    return {
      isEditing: false,
      isDone: this.done, // after deleting this line and use 
                         //computed: {} below, the bug is solved.
    };
  },
  
  // computed: {
  //   isDone() {
  //     return this.done;
  //   },
  // },
};
</script>

ToDoItem.vue

<template>
  <div id="app">
    <h1>To-Do List</h1>
    <to-do-form @todo-added="addToDo"></to-do-form>
    <h2 id="list-summary" ref="listSummary" tabindex="-1"> {{ listSummary }} </h2>
    <ul aria-labelledby="list-summary" >
      <li v-for="item in ToDoItems" :key="item.id">
        <to-do-item
          :label="item.label"
          :done="item.done"
          :id="item.id"
          @checkbox-changed="updateDoneStatus(item.id)"
          @item-deleted="deleteToDo(item.id)"
          @item-edited="editToDo(item.id, $event)"
        >
        </to-do-item>
      </li>
    </ul>
  </div>
</template>

 <script>
 import ToDoItem from "./components/ToDoItem.vue";
 import ToDoForm from "./components/ToDoForm.vue";
 import uniqueId from "lodash.uniqueid";

 export default {
    name: "app",
    components: {
    ToDoItem,
    ToDoForm,
    },

  data() {
    return {
      ToDoItems: [],
    };
  },

methods: {
  updateDoneStatus(toDoId) {
    const toDoToUpdate = this.ToDoItems.find((item) => item.id === toDoId);
    toDoToUpdate.done = !toDoToUpdate.done;
    console.dir(toDoToUpdate.done)
  },
};
</script>

CodePudding user response:

I'm not an expert in vue, but I believe that the this.done being assigned to isDone: is only done once in data(), and it wouldn't be done if the props change (the value of isDone in data() won't change when the prop done changes). While in computed, isDone will watch the done prop value, and if that prop value changes, the computed will be notified and thus changes the isDone data.

  • Related