首页 > 解决方案 > 无法在 vee-validate 组件中重新渲染 html

问题描述

Vue.js v2.6.11 / vee-validate v3.2.2

我有一个按钮,可以在点击事件时将新元素推送到form.demand(vue 应用程序中的数据)。如果form.demand更新,v-for中的 html也应该更新。在我将它包装在 vee-validate component 之后,它就不起作用了。 form.demand会更新,但v-for不会。我尝试将相同的 html 放在测试组件中,当form.demand更新时,v-for也更新。我想不通为什么...

以下是我的代码:

HTML

<div id="content">
<test-component>
  <div v-for="demand in form.demand">{{demand}}</div>
</test-component>

<validation-provider rule="" v-slot="v">
  <div @click="addDemand">new</div>

  <div v-for="(demand,index) in form.demand">
      <div>{{demand.name}}</div>
      <div>{{demand.count}}</div>
      <input type="text" :name="'demand['+index+'][name]'" v-model="form.demand[index].name" hidden="hidden" />
      <input type="text" :name="'demand['+index+'][count]'" v-model="form.demand[index].count" hidden="hidden" />
  </div>
</validation-provider>
</div>

javascript

Vue.component('validation-provider', VeeValidate.ValidationProvider);
Vue.component('validation-observer', VeeValidate.ValidationObserver);

Vue.component('test-component',{
    template: `
        <div>
            <slot></slot>
        </div>
    `
})

var app = new Vue({
    el: "#content",
    data: {
        form: {
            demand: [],
        },
    },
    methods: {
        addDemand(){
            this.form.demand.push({
                name : "demand name",
                count: 1
            })
        }
})

------------尝试使用 computed & Add :key---------------- 还是不行。更改后我得到相同的结果。

HTML

<validation-provider rule="" v-slot="v">
      <div @click="addDemand">new</div>

      <div v-for="(demand,index) in computed_demand" :key="index">
           <!--.........omitted.........-->
</validation-provider>

Javascript

var app = new Vue({
        el: "#content",
        // .......omitted
        computed:{
            computed_demand() {
                return this.form.demand;
            }
        },
    })

我想我发现了问题:从两个不同的来源导入 Vue。在 HTML 中,我从 cdn 导入 Vue。并导入 vee-validate 如下:

vee-validate.esm.js

import Vue from './vue.esm.browser.min.js';
/*omitted*/

验证器.js

 import * as VeeValidate from './vee-validate.esm.js';
    export { veeValidate };

main.js

// I didn't import Vue from vue in this file
import { veeValidate as VeeValidate } from './validator.js';

Vue.component('validation-provider', VeeValidate.ValidationProvider);

HTML

<head>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>

<body>
    <!-- at end of body -->
    <script src="/static/javascripts/main.js" type="module"></script>
</body>

修复此问题后(从 cdn 导入 vee-validate,或通过 ES6 模块导入 Vue)。它可以工作,尽管 vee-validate 仍然存在无限循环问题。

抱歉,我没有注意到来自两个不同来源的 import vue。

标签: javascripthtmlvue.jsvee-validate

解决方案


请在您的 v-for 中提供一个密钥。见下面的代码

<div v-for="(demand,index) in form.demand" :key="index">
      <div>{{demand.name}}</div>
      <div>{{demand.count}}</div>
      <input type="text" :name="'demand['+index+'][name]'" v-model="form.demand[index].name" hidden="hidden" />
      <input type="text" :name="'demand['+index+'][count]'" v-model="form.demand[index].count" hidden="hidden" />
  </div>

或者,创建一个计算属性来保存您的 form.demands 数组,就像这个

computed: {
   form_demands: function() {
     return this.form.demand
  }
}

然后在你的 v-for 中调用这个计算属性

<div v-for="(demand,index) in form_demands" :key="index">
      <div>{{demand.name}}</div>
      <div>{{demand.count}}</div>
      <input type="text" :name="'demand['+index+'][name]'" v-model="form.demand[index].name" hidden="hidden" />
      <input type="text" :name="'demand['+index+'][count]'" v-model="form.demand[index].count" hidden="hidden" />
</div>

或者,使用 vue forceUpdate 方法

import Vue from 'vue';
Vue.forceUpdate();

然后在你的组件中,添加需求后调用方法即可

this.$forceUpdate();

建议尽可能使用 v-for 提供一个键,除非迭代的 DOM 内容很简单,或者您有意依赖默认行为来提高性能。


推荐阅读