You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Vue I18n在setup中翻译数组导致内容需额外操作才渲染的问题求解

问题分析与解决方案

这个问题我之前也碰到过,核心原因是你在组件初始化时直接把翻译结果赋值给了faqs数组——这些值是一次性计算的静态快照,不会随着语言切换自动更新,因为它们没有绑定到i18n的响应式依赖上。只有<h1>里的t('FAQ.title')能正常更新,是因为它直接写在模板里,Vue会自动追踪它的依赖,语言变化时重新渲染。

修复方案:用computed包裹FAQ数据

faqs改成响应式的计算属性,这样每次语言切换时,计算属性会重新执行t()获取最新的翻译内容,模板也会自动同步更新。

修改后的代码如下:

<template>
  <div class="bg-white">
    <h1 class="text-4xl font-semibold my-10 text-center capitalize text-black dark:text-white" >
      {{ t('FAQ.title') }}
    </h1>
    <div class="space-y-4 mx-auto my-4 max-w-screen-lg">
      <details class="group" v-for="faq in faqs" :key="faq.question">
        <summary class="flex items-center list-none text-left justify-between p-4 rounded-lg cursor-pointer" >
          <h5 class="font-medium text-black">{{ faq.question }}</h5>
          <svg class="flex-shrink-0 ml-1.5 w-5 h-5 transition duration-500 group-open:-rotate-180" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" >
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
          </svg>
        </summary>
        <ul v-if="faq.list">
          <li class="px-4 my-2 ml-4 leading-relaxed text-secondary" v-for="answer in faq.answer" :key="answer" >
            {{ answer }}
          </li>
        </ul>
        <p class="px-4 my-2 ml-4 leading-relaxed text-secondary" v-else>
          {{ faq.answer }}
        </p>
      </details>
    </div>
  </div>
</template>
<script lang="ts">
import { defineComponent, computed } from 'vue' // 引入computed
import { useI18n } from 'vue-i18n'
export default defineComponent({
  name: 'FAQ',
  setup() {
    const { t } = useI18n()
    
    // 把faqs改成computed属性,响应语言变化
    const faqs = computed(() => [
      { question: t('FAQ.questions[0]'), answer: t('FAQ.answers.answer1') },
      { question: t('FAQ.questions[1]'), answer: [
          t('FAQ.answers.answer2[0]'),
          t('FAQ.answers.answer2[1]'),
          t('FAQ.answers.answer2[2]'),
          t('FAQ.answers.answer2[3]'),
          t('FAQ.answers.answer2[4]')
        ], list: true },
      { question: t('FAQ.questions[2]'), answer: t('FAQ.answers.answer3') },
      { question: t('FAQ.questions[3]'), answer: t('FAQ.answers.answer4') },
      { question: t('FAQ.questions[4]'), answer: t('FAQ.answers.answer5') },
      { question: t('FAQ.questions[5]'), answer: t('FAQ.answers.answer6') },
      { question: t('FAQ.questions[6]'), answer: t('FAQ.answers.answer7') },
      { question: t('FAQ.questions[7]'), answer: t('FAQ.answers.answer8') },
      { question: t('FAQ.questions[8]'), answer: t('FAQ.answers.answer9') },
      { question: t('FAQ.questions[9]'), answer: t('FAQ.answers.answer10') },
      { question: t('FAQ.questions[10]'), answer: t('FAQ.answers.answer11') },
      { question: t('FAQ.questions[11]'), answer: t('FAQ.answers.answer12') }
    ])
    
    return { faqs, t }
  }
})
</script>

为什么这样有效?

  • computed()会自动追踪内部用到的响应式依赖(这里就是i18n的locale和翻译函数t()
  • 当语言切换时,t()的返回值会变化,computed属性会自动重新计算整个faqs数组
  • 模板里的v-for会感知到faqs的变化,自动重新渲染所有FAQ条目,不需要手动切换语言或跳转页面

内容的提问来源于stack exchange,提问作者Tomas Gil Amoedo

火山引擎 最新活动