Правильное отображение списка задач с помощью onSnapshot после добавления / удаления элементов из списка - PullRequest
0 голосов
/ 10 ноября 2019

Что я делаю

Я делаю простое приложение для организации задач, используя vue и firestore. На данный момент я выполнил 5 функций.

  1. Логин
  2. Регистрация
  3. Получение и отображение списка задач
  4. Добавление / удаление задачи
  5. [Не работает!] Отображение любых изменений в списке задач в режиме реального времени

Не работает должным образом

Получает и загружает данные массива из хранилища и отображает в реальном времени, но неотображается неправильно

Сведения о проблеме

Эта проблема становится видимой при обновлении списка в результате добавления или удаления задачи из списка.

Пожалуйста, проверьте изображение, чтобы получить более четкое представление о проблеме.

Скриншоты вопроса

То, что я пытался

  • Решить, обновив страницу, но потеряв смысл обновления в реальном времени.
  • Увидел где-то, что set Vue () / new Vue () решит, но не сделал. (Или, скорее, я слишком новичок, чтобы понять эту концепцию, чтобы применять ее ...)

Скорее всего, я не понимаю, в чём заключается настоящая проблема ... Так что было бы здорово, если бы кто-то могукажите мне, в чем реальная проблемаТак что ждите ваших идей!

Код

В основном два файла отвечают за рендеринг списка задач.

  1. projectList.vue: где я получаю изагрузить данные массива и отобразить список задач
  2. projectCard.vue: куда я вставляю данные каждой задачи для projectList.vue для создания списка.

(я также добавлю скриптдля добавления проекта; addProject.js на всякий случай.)

projectList.vue: получить, загрузить, отобразить список задач

<template>
  <div class="projectList">
    <button class="home-buttons" @click="newProject">Add project</button>
    <div v-if="createNew">
      <projectAdd/>
    </div>
    <div v-show="loading">
      <Loader/>
    </div>
    <div v-show="!loading">

      <!--03 Pass array data to projectCard.vue then render the list of entries-->
      <projectCard v-for="project in projects" :key="project.id" :project="project"/>

    </div>
    <p v-show="noproject">There is no project</p>
  </div>

</template>

<script>
import firebase from '@/firebase/firestore';
import Loader from '@/components/loading.vue';
import projectCard from '@/components/projectCard.vue';
import projectAdd from '@/components/addProject.vue';

export default {
  components: {
    projectCard,
    Loader,
    projectAdd,
  },
  data() {
    return {
      userid: this.$route.params.userId,

      //02 Put array data here
      projects: [],

      loading: true,
      createNew: false,
    };
  },
  created() {
    //01 Get datas in realtime then pass an array data to projects: []
    const db = firebase.firestore()
    .collection('user')
    .doc(this.userid) //$route.params.userId
    .collection('projects')
    .orderBy('createdAt', 'desc');
    db
      .onSnapshot((querySnapshot) => {
        querySnapshot.forEach((doc) => {
            this.projects.push(doc.data());
        });
        if (this.projects.length >= 0) {
          this.loading = false;
        } else if (this.projects.length <= 0) {
          this.loading = false;
        }
      });
  },
  methods: {
    newProject() {
      if (this.createNew !== true) {
        this.createNew = true;
      } else {
        this.createNew = false;
      }
    },
  },
};
</script>

projectCard.vue: вставить все данные в массив

<template>
  <div class="projectCard">
    <div class="user-list">
      <div class="columns">
        <div class="column is-8">
          <h3>{{ project.projectname }}</h3>
          <p>{{ project.slug }}</p>
          <p>Why : {{ project.why }}</p>
          <p>{{ project.phase }}</p>
        </div>
        <div class="column is-4 right">
          <router-link class="button is-primary" :to="{ name: 'viewproject', params: { projectId: project.slug }}">
            Find out more!
          </router-link>
          <button @click="deleteProject"> Delete </button>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import firebase from '@/firebase/firestore';

export default {
  name: 'ProjectCard',
  props: {
    // Holds array data from parent-component; projectList.vue
    project: Object,
  },
  methods: {
    // Delete a task
    deleteProject() {
    firebase.firestore().collection('user').doc(this.project.userId)
    .collection('projects')
    .where('slug', '==', this.project.slug)
    .get()
    .then((snapshot) => {
      snapshot.forEach((doc => {
      console.log(doc.data().slug);
      doc.ref.delete();
      alert('You have deleted the project!' + doc.data().slug);
      })) 
    })
    },
  },

};

</script>

addProject.js: Добавить задачу (эта функция доступна из другого компонента, представленного в projectList.vue)

import firebase from '@/firebase/firestore';

export default {
  addProject(createdAt, userId,projectname,why,phase){
    const db = firebase.firestore().collection("user")
    .doc(userId).collection("projects"); // "Project"という名前のコレクションへの参照を作成
    db.add({
      createdAt: createdAt,
      userId: userId,
      projectname: projectname,
      why: why,
      phase: phase,
      slug: this.generateUUID(),
    })
      .then(function (docRef) {
        console.log('Document written with ID: ', docRef.id);
        alert('Well done! You have created a new project!');
      })
      .catch(function (error) {
        console.error('Error adding document: ', error);
      });
  },
  generateUUID() {
    let d = new Date().getTime();
    let uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
      let r = (d + Math.random() * 16) % 16 | 0;
      d = Math.floor(d / 16);
      return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
    });
    return uuid;
  },
};

Спасибо, что потратили ваше драгоценное время на чтение этого ичтобы помочь мне выйти из этого вопроса! Ждем ваших идей, ребята!

1 Ответ

0 голосов
/ 10 ноября 2019

Это потому, что каждый раз, когда слушатель срабатывает, вы получаете весь результат вашего запроса, то есть все документы, соответствующие ему.

У вас в основном есть две опции:

Вариант 1: повторная инициализация массива

Повторная инициализация массива перед его заполнением следующим образом:

  created() {

    const db = firebase.firestore()
    .collection('user')
    .doc(this.userid) //$route.params.userId
    .collection('projects')
    .orderBy('createdAt', 'desc');

    this.projects = [];  <-- See here

    db
      .onSnapshot((querySnapshot) => {
        querySnapshot.forEach((doc) => {
            this.projects.push(doc.data());
        });
        if (this.projects.length >= 0) {
          this.loading = false;
        } else if (this.projects.length <= 0) {
          this.loading = false;
        }
      });
  },

Вариант 2: прослушивание фактических изменений

Как объясняется в документ , вы можете обнаружить " фактические изменения для запроса результатов между моментальными снимками запроса ".

Например, выможет обрабатывать только дополнения, как указано ниже:

db
  .onSnapshot((querySnapshot) => {
    querySnapshot.docChanges().forEach((change) => {
        if (change.type === "added") {
            this.projects.push(change.doc.data());
        }
        //....
    });
    //....
  });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...