You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue向数组添加新元素后页面不重新渲染问题求助

问题根源

你当前的问题出在深度监听tempForm的watch逻辑:每次tempForm内部任何数据变化(包括点击按钮给options数组添加元素),watch的handler都会执行。而handler里只要当前question的type是select,就会把question.options重新赋值为[""],直接覆盖了你刚添加的新元素,导致v-for渲染的输入框看起来没更新——实际上是数组被重置了。

另外,addItems里用this.$set给数组加元素完全没必要,Vue原生就能检测数组的push操作。

修复方案

1. 重构watch逻辑,只监听type变化

不要监听整个tempForm的所有变化,而是只在question的type切换时才初始化或删除options。最直接的方式是给每个question单独添加type的监听:

初始化第一个question的监听

在created钩子中给第一个question加监听:

created() {
  const firstQ = this.tempForm.tempQuestions[0];
  this.$watch(() => firstQ.type, (newType) => {
    if (newType === 'select') {
      firstQ.options = [""];
    } else {
      delete firstQ.options;
    }
  }, { immediate: true });
}

新增question时自动加监听

修改addQuestion方法,给每个新创建的question添加上type监听:

addQuestion() {
  const newQ = {
    question: null,
    description: null,
    type: null,
  };
  this.tempForm.tempQuestions.push(newQ);
  
  // 给新question绑定type监听
  this.$watch(() => newQ.type, (newType) => {
    if (newType === 'select') {
      newQ.options = [""];
    } else {
      delete newQ.options;
    }
  }, { immediate: true });
  
  this.questions++;
}

这样只有当下拉框切换类型时才会处理options,修改数组元素时不会触发重置。

2. 简化addItems方法

直接用数组push添加元素,Vue能自动检测到这个变化并更新视图:

addItems() {
  this.tempForm.tempQuestions[0].options.push("");
}

3. 给v-for添加key(推荐)

为了让Vue更高效地更新列表,给循环的.option元素加上唯一key:

.option(v-for="(option, index) in tempForm.tempQuestions[0].options" :key="index")
  input(type="text" placeholder="Option" v-model="tempForm.tempQuestions[0].options[index]")
完整修复后的代码

模板(Pug)

.formHolder
  .quest
    input(type="text" placeholder="Question" v-model="tempForm.tempQuestions[0].question")
    input(type="text" placeholder="Description" v-model="tempForm.tempQuestions[0].description")
    select(name="category" v-model="tempForm.tempQuestions[0].type")
      option(value="text") text
      option(value="select") Dropdown
      option(value="number") Number
    .option(v-for="(option, index) in tempForm.tempQuestions[0].options" :key="index")
      input(type="text" placeholder="Option" v-model="tempForm.tempQuestions[0].options[index]")
    button(v-if="tempForm.tempQuestions[0].type === 'select'"  @click="addItems") Add Options   

脚本

import HelloWorld from "@/components/HelloWorld.vue";

export default {
  name: "HomeView",
  components: {
    HelloWorld,
  },
  data() {
    return {
      questions: 0,
      tempForm: {
        tempQuestions: [
          {
            question: null,
            description: null,
            type: null,
          },
        ],
      },
      form: {
        questions: [],
      },
    };
  },
  created() {
    // 初始化第一个问题的类型监听
    const firstQ = this.tempForm.tempQuestions[0];
    this.$watch(() => firstQ.type, (newType) => {
      if (newType === 'select') {
        firstQ.options = [""];
      } else {
        delete firstQ.options;
      }
    }, { immediate: true });
  },
  methods: {
    addQuestion() {
      const newQ = {
        question: null,
        description: null,
        type: null,
      };
      this.tempForm.tempQuestions.push(newQ);
      
      // 给新问题绑定类型监听
      this.$watch(() => newQ.type, (newType) => {
        if (newType === 'select') {
          newQ.options = [""];
        } else {
          delete newQ.options;
        }
      }, { immediate: true });
      
      this.questions++;
    },
    addItems() {
      this.tempForm.tempQuestions[0].options.push("");
    },
  },
};

内容的提问来源于stack exchange,提问作者Abdullah Ibn Shahin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 22:45:16