VueJS 對於 v-for 正確的寫法

文章留言的下方,一般會將所有的留言渲染出來,但奇怪的是為何只是輸入留言,還沒有按送出(Post Comment) ,所有的留言記錄為經由 v-for 全新渲染乙次?

image 7

程式段如下

<template>
<Textarea v-model="content" :rows="6" placeholder="Your comment"></Textarea>

<ul class="list-none p-0 m-0">
	<li v-for="(comment, i) in comments" :key="{ i }"
		class="flex p-3 mb-3 border-1 surface-border border-round">
		<img :src="comment.user?.avatar_url" class="w-3rem h-3rem mr-3 flex-shrink-0" :alt="'Image' + i" />
		<div>
			<span class="font-semibold text-900">{{ comment.user?.name }}</span>
			<p class="font-semibold text-600 m-0 text-sm">{{ useDateFormat(comment.created_at, 'YYYY-MM-DD HH:mm') }}</p>
			<p class="line-height-3 mb-0 my-3">{{ comment.content }}</p>
		</div>
	</li>
</ul>
</template>

在第5行的地方 :key="{ i }" 是錯的寫法,Vue 的 :key 不能給一個物件,否則會造成渲染效能問題與怪異行為。

改成這樣:

<li v-for="(comment, i) in comments" :key="i"

或更好:

:key="comment.id" // 如果你有留言的唯一 ID

完整程式碼示範如下:

<script setup>
import { ref } from 'vue'
import { useDateFormat } from '@vueuse/core'

const content = ref('')
const comments = ref([])

function postComment() {
  if (!content.value.trim()) return

  comments.value.push({
    content: content.value,
    created_at: new Date(),
    user: {
      name: '你自己',
      avatar_url: 'https://placekitten.com/64/64',
    },
  })

  content.value = ''
}
</script>

<template>
  <div class="mb-4">
    <Textarea
      v-model="content"
      :rows="6"
      placeholder="Your comment"
    />
    <button class="mt-2" @click="postComment">送出留言</button>
  </div>

  <ul class="list-none p-0 m-0">
    <li
      v-for="(comment, i) in comments"
      :key="i"
      class="flex p-3 mb-3 border-1 surface-border border-round"
    >
      <img
        :src="comment.user?.avatar_url"
        class="w-3rem h-3rem mr-3 flex-shrink-0"
        :alt="'Image' + i"
      />
      <div>
        <span class="font-semibold text-900">{{ comment.user?.name }}</span>
        <p class="font-semibold text-600 m-0 text-sm">
          {{ useDateFormat(comment.created_at, 'YYYY-MM-DD HH:mm') }}
        </p>
        <p class="line-height-3 mb-0 my-3">{{ comment.content }}</p>
      </div>
    </li>
  </ul>
</template>

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *