alestro
@alestro

Как сделать вложенные комментарии во vue?

Сейчас у меня есть 3 компонента: singlePost, commentsList, comment (рекурсивный);

В singlePost я получаю все корневые комментарии, передаю их в commentsList, который перебирает комментарии и подгружает comment.
В comment есть коллекция replies, которая подгружает дочерние комментарии при клике на кнопку, но возникают проблемы с добавлением новых комментариев.

При добавлении нового комментария, в singlePost по сокету прилетает последний комментарий, который при помощи provide улетает в comment.

часть компонента singlePost
const comments = ref<Collection<IComment>>(new Collection<IComment>())
const lastComment = ref<IComment>()

const commentsCount = ref<number>(0)

provide('lastComment', lastComment)
provide('commentsCount', commentsCount)

const connection = new WebSocket('ws://127.0.0.1:8080/comments');
connection.onmessage = function(r) {
    const comment = mapComment(JSON.parse(r.data))
    lastComment.value = comment
    commentsCount.value = commentsCount.value + 1

    if (comment.parentId === undefined) comments.value.add(comment)
    else {
      const el = comments.value.find((el: IComment) => {
        return el.id === comment.parentId
      })
      if (el !== undefined) {
        if (el.replies === undefined) el.replies = 1
        else el.replies += 1
      }
    }
  };
onMounted(async () => {
 
  const result = await getCommentsAsync(new CommentQuery({
    publicationId: article.value.id,
    parentId: 0
  }))

  if (result === null) comments.value = new Collection<IComment>()
  else {
    comments.value = result
    commentsCount.value = article.value.commentsCount ?? 0
  }
})


Кусок компонента commet
const lastComment = inject<Ref<IComment | undefined>>('lastComment') as Ref<IComment | undefined>;

const replies = ref<Collection<IComment>>(new Collection<IComment>())

const showReplies = ref(false)

const repliesCount = ref<number>(props.comment.replies)
const hasReplies = ref<boolean>(repliesCount.value > 0)

watch(lastComment, () => {
  if (lastComment.value !== undefined && lastComment.value?.parentId === props.comment.id) {
    replies.value.add(lastComment.value)
    repliesCount.value = repliesCount.value + 1

    showReplies.value = hasReplies.value = true
  }
})

const showRepliesHandler = async () => {
  showReplies.value = !showReplies.value
  if (!replies.value.isLoaded) {
      const result = await getCommentsAsync(new CommentQuery({
          parentId: props.comment.id
      }))
      if (result !== null) {
        replies.value = result
      }
  }
}

const repliesButtonText = computed(() => {
  return showReplies.value ?
      'Свернуть' : declension(repliesCount.value, ['ответ', 'ответа', 'ответов'])
})


Это работает для комментариев на n+1 уровень вложенности, то есть отображаются комментарии, в ветке, которая в данный момент раскрыта (корневые отображаются всегда).

Но если скрыть ветку, и раскрыть ее повторно, то теряются все комментарии, которые прилетели по сокету.
Кроме того, в случае, если подгружать новые комментарии по api, произойдет задвоение данных.

Как лучше сделать?
  • Вопрос задан
  • 92 просмотра
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы