【问题标题】:Element deleted from the array but v-for doesn't update VUEJS从数组中删除的元素但 v-for 不更新 VUEJS
【发布时间】:2021-12-21 16:29:23
【问题描述】:

伙计们,所以我正在尝试开发这个规则组件,它可以由我的主要组件生成任意多次,但问题是当我从跟踪规则数量的列表中删除一个索引时,vuejs布局不会相应更新。我的意思是,如果我检查它自己的数组,它会删除正确的项目,但是当我查看 vue 页面(HTML)时,它要么不删除任何内容,要么只删除最后一项,这可能是由v-for 没有更新列表更改,但我不知道如何解决这个问题。

NewTask.vue(父)

<template>
  <div class="mt-4">
      <div class="container">
          <div class="if-condition container-fluid d-flex flex-row ps-0">
              <span class="text-center me-2 condition rounded">IF</span>
              <select class="form-select form-select-sm me-2 if-select" v-model="if_condition">
                <option value="ALL">ALL</option>
                <option value="ANY">ANY</option>
                <option value="NONE">NONE</option>
              </select>
              <span>of these filters match</span>
          </div>
          <div class="mt-2 ps-3 pt-3 pb-3 border">
            <new-rule v-for="(item, index) in rules"
                      :key="JSON.stringify(index)" v-on:remove-rule="removeRule(index)"
                      :data="item" :index="index" v-on:data-changed="dataChanged"
                      class="mb-2"/>
            <div class="mt-2 add-rule-div">
              <button class="btn add-rule-btn" v-on:click="addRule">+</button>
            </div>
          </div>
      </div>
  </div>
</template>

<script>
import Rule from '@/components/rule'

export default {
    name: "NewTask",
    components: {
      'new-rule': Rule
    },
    data: function () {
      return {
        if_condition: 'ALL',
        rules: []
      }
    },
  methods: {
      dataChanged(data) {
        const rules = this.rules;
        const index = data.index;
        delete data['index'];
        rules.splice(index, 1, data)
        this.rules = rules;
      },
      removeRule(index) {
        const rules = this.rules;
        rules.splice(index, 1)
        this.rules = rules
      },
      addRule() {
        const new_rule = {
          type_input_text: null,
          type_input_show: null,
          rule_input_text: null,
          rule_input_show: null,
        }
        this.rules.push(new_rule)
        console.log(this.rules)
      }
    }
  }
</script>

rule.vue(子)

<template>
    <div class="if-condition d-flex flex-row">
      <select class="form-select form-select-sm me-2"
              v-on:change="checkTypeSelect" v-model="type_select">
        <option value="HTML">HTML</option>
        <option value="XPATH">XPATH</option>
        <option value="ID">ID</option>
        <option value="CLASS">CLASS</option>
      </select>
      <input v-if="type_input_show" type="text" class="form-control me-2" v-model="type_input_text" v-on:change="dataChanged">
      <select class="form-select form-select-sm me-2"
              v-on:change="checkRuleSelect" v-model="rule_select">
        <option value="CONTAINS">CONTAINS</option>
        <option value="EXISTS">EXISTS</option>
      </select>
      <input v-if="rule_input_show" type="text" class="form-control me-2" v-model="rule_input_text" v-on:change="dataChanged">
      <button class="btn remove-rule-btn pb-0 pt-0 ps-2 pe-2" v-on:click="this.$emit('remove-rule')">-</button>
    </div>
</template>

<script>
export default {
  name: "rule",
  props: {
    data: {
      type: Object,
      required: true
    },
    index: {
      type: Number,
      required: true
    }
  },
  data: function () {
    return {
      type_select: 'HTML',
      type_input_text: '',
      rule_select: 'CONTAINS',
      rule_input_text: '',
      //
      type_input_show: false,
      rule_input_show: true,
    }
  },
  beforeMount() {
    if (this.data.type_select) {
      this.type_select = this.data.type_select
      this.checkTypeSelect()
    }
    if (this.data.type_input_text) {
      this.type_input_text = this.data.type_input_text
    }
    if (this.data.rule_select) {
      this.rule_select = this.data.rule_select
      this.checkRuleSelect()
    }
    if (this.data.rule_input_text) {
      this.rule_input_text = this.data.rule_input_text
    }
  },
  methods: {
    dataChanged() {
      const new_data = {
        index: this.index,
        type_select: this.type_select,
        type_input_text: this.type_input_text,
        rule_select: this.rule_select,
        rule_input_text: this.rule_input_text
      }
      this.$emit('data-changed', new_data)
    },
    checkTypeSelect() {
      const type_select = this.type_select;
      this.type_input_show = type_select !== 'HTML';
      this.dataChanged()
    },
    checkRuleSelect() {
      const rule_select = this.rule_select;
      this.rule_input_show = rule_select !== 'EXISTS';
      this.dataChanged()
    }
  }
}
</script>

展示问题的一些图片:

索引删除前的数组:

索引删除后的数组:

如需进一步调查,请随时访问 repo:https://github.com/DEADSEC-SECURITY/Easy-Scraper

这不是宣传,我真的需要帮助

【问题讨论】:

  • :key="JSON.stringify(index)" JSON.stringify()?无论如何,这里的问题是使用index 作为密钥。当你这样做时,就 Vue 而言,当数组改变大小时,它只会从末尾添加/删除元素

标签: javascript arrays vue.js v-for


【解决方案1】:

目前,您在NewTask.vue 中的rules 值在data 之下。如果您将其移至computed,它将变为反应式并且列表应正确更新。

【讨论】:

  • 数据也是被动的。如果我没有记错保存在缓存中的能力,计算和数据之间的区别。
【解决方案2】:

您正在使用索引作为键。 VueJS 根据 key 的变化更新 DOM。所以你有两个选择:

  • 使用每个条目或组合中的一些不同数据作为键。
  • 不提供密钥,因为根据 Vuejs docs,您不再需要提供密钥。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-06-03
    • 2020-08-19
    • 2019-12-19
    • 2020-08-08
    • 2015-03-23
    • 2019-06-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多