Как вызвать функцию после обновления prop в дочернем компоненте. Vue3 composition API

#javascript #vue.js #vue-component #vuejs3 #vue-composition-api

#javascript #vue.js #vue-компонент #vuejs3 #vue-composition-api

Вопрос:

У меня есть список задач, который генерируется из цикла for . Каждый todo передается как реквизит <singleTodo /> дочернему компоненту. Как только я удалю a todo из <SingleTodo/> компонента, как я могу обновить страницу (имеется в виду: вызвать getTodos функцию). Использование onUpdated перехвата жизненного цикла работает, но проблема в том, что как только я удаляю один todo , возникает непреодолимый цикл получения для REST API. Есть мысли?

Компонент списка

 <template>
  <div>
    <CreateTodo />
    <hr />

    <div class="TodoContainer">
      <SingleTodo
        v-for="todo in todos"
        v-bind:key="todo.id"
        :todo="todo"
        class="TodoComponent"
      />
    </div>
    <hr />
  </div>
</template>

<script>
import CreateTodo from "./CreateTodo";
import SingleTodo from "./SingleTodo";
import { onMounted, ref } from "vue";

//
export default {
  components: {
    CreateTodo,
    SingleTodo,
  },

  props: {
    todo: Object,
  },

  setup() {
    const API_URL = "http://127.0.0.1:8000/api/todo-list/";
    const todos = ref([]);

    async function getTodos() {
      const response = await fetch(API_URL);
      const json = await response.json();
      todos.value = json;
    }


    onMounted(() => {
      getTodos();
    });

    // onUpdated(() => {
    //   getTodos();
    // });

    return {
      todos,
      getTodos,
    };
  },
};
</script>
  

дочерний компонент, SingleTodo.vue

 <template>
  <div>
    {{ todo.id }}{{ todo.completion }}{{ todo.todo }}
    <button @click="removeTodo(todo.id)">delete</button>
  </div>
</template>

<script>
// import { getTodos } from "./TodoHooks.js";
import { getCookie } from "./TodoHooks.js";

export default {
  props: {
    todo: Object,
  },

  setup() {
    const API_DELETE = "http://127.0.0.1:8000/api/todo-delete";
    const csrftoken = getCookie("csrftoken");

    //

    async function removeTodo(id) {
      var csrftoken = getCookie("csrftoken");
      fetch(`${API_DELETE}/${id}/`, {
        method: "DELETE",
        headers: {
          "Content-type": "application/json",
          "X-CSRFToken": csrftoken,
        },
      }).then((response) => {
        // NEEDED TO UPDATE AUTOMATICALLY.
        // getTodos();
        return response;
      });
    }

    return {
      removeTodo,
      csrftoken,
    };
  },
};
</script>
  

Ответ №1:

Попробуйте передать событие родительскому компоненту, чтобы обновить список, добавьте emits опцию, например :

 props: {
    todo: Object,
  },
  emits:['refresh'],
....
  

затем внутри then обратного вызова генерируется refresh событие :

  }).then((response) => {
        emit('refresh')
  

но прежде чем вы должны emit удалить свойство из контекста в параметрах настройки setup(_,{emit}) {

полный код :

 <script>
// import { getTodos } from "./TodoHooks.js";
import { getCookie } from "./TodoHooks.js";

export default {
  props: {
    todo: Object,
  },
  emits:['refresh'],
  setup(_,{emit}) {
    const API_DELETE = "http://127.0.0.1:8000/api/todo-delete";
    const csrftoken = getCookie("csrftoken");

    //

    async function removeTodo(id) {
      var csrftoken = getCookie("csrftoken");
      fetch(`${API_DELETE}/${id}/`, {
        method: "DELETE",
        headers: {
          "Content-type": "application/json",
          "X-CSRFToken": csrftoken,
        },
      }).then((response) => {
        emit('refresh')
        return response;
      });
    }

    return {
      removeTodo,
      csrftoken,
    };
  },
};
</script>
  

в родительском компоненте :

  <SingleTodo
        v-for="todo in todos"
        v-bind:key="todo.id"
        :todo="todo"
        class="TodoComponent"
        @refresh="getTodos"

      />