【问题标题】:Vue - Dynamic properties from external TypeScript Class are not reactiveVue - 来自外部 TypeScript 类的动态属性不是响应式的
【发布时间】:2021-03-16 16:02:28
【问题描述】:

我有一个小问题,我创建了一个包来管理表单,一切正常,直到我需要基于 API 响应创建一个动态表单。

这是包裹:https://github.com/nulvem/js-form

可以用npm安装:

npm install @nulvem/js-form

这是我调用 Form 类的 Vue 组件:

<script>
import {Form} from '@nulvem/js-form'

export default {
  data() {
    return {
      form: new Form({
        template: {
          value: null,
          validation: {
            rules: 'required',
            messages: {
              required: 'You must select the type of report'
            }
          }
        }
      })
    }
  },
  mounted() {
    this.form.template = 'random-id'

    // These data will be obtained from an API
    let fields = [
      'start_date',
      'end_date',
      'wallets',
    ]

    fields.forEach((field) => {
      let fieldData = {
        value: null,
        validation: {
          rules: 'required',
          messages: {
            required: `You must enter the field ${field.description}`
          }
        }
      }

      this.form.$addField(field, fieldData)
    })

    // Here we can only see the getter/setter of the template property that was passed when instantiating the Form class
    console.log(this.form)
  }
}
</script>

问题是:我在创建 new Form ({...}) 实例期间传递给表单的字段是反应性的,因为当我通过调用 this.form.$AddField() 函数添加新字段时,这些字段没有反应性。

有趣的是Form类的construct调用了一个名为this.form.$AddFields()的函数,该函数多次调用this.form.$AddField()函数。

为什么它在构造函数中起作用而在分开调用时不起作用?如何解决这个问题?

知道会发生什么吗?这让我发疯了,我一直试图找到问题几个小时,但我找不到它。

编辑

作为快速修复,我们在包中进行了更改,可以将 Form 实例作为第三个参数传递给 $addFields 函数,因此属性是反应性的,但是我们希望它在没有的情况下工作必须传递这个参数。

【问题讨论】:

  • Vue 2 不会检测到对象属性的添加/删除,因此您必须为此使用Vue.set()/Vue.delete()。如果您仅使用 API 中的所有字段初始化 mounted() 中的表单,那么一旦您拥有所有可用字段,我将在 mounted() 中设置 form = new Form()。那么你就不需要传递上下文了。
  • 您必须将 form 实例替换为包含字段的新实例。我认为最简单的方法是在data: () =&gt; { form: null } 中放置一个null 占位符,并在您拥有API 中的所有字段时设置表单类实例。 Vue 反应性的意思是:所有属性都替换为 getter/setter,但这仅发生在顶层,而不是针对每个单独的嵌套 prop。除非您替换 form,否则 Vue 不会知道更改。而Vue.set() 正是这样做的。它替换了道具中的实例。

标签: javascript typescript vue.js


【解决方案1】:

VueJS 在渲染后失去了添加到 data 的属性的反应性。您可以在此处阅读更多相关信息:https://br.vuejs.org/v2/guide/reactivity.html

尝试解决此问题的一种快速方法是在每次添加新属性时添加this.$forceUpdate(),但根据您的上下文,它也可能带来其他问题。

或者您可以尝试使用Vue.set() 方法,而不是您的$addField 方法。您可以在上面的同一链接中阅读更多内容。

【讨论】:

  • 我需要打电话给$addField(),因为它会解析我的验证规则和类内的消息
  • 无论如何,我认为您可以尝试使用Vue.set 并将属性添加到您的form
【解决方案2】:

删除上下文并更改此行以进行反应:

this.$initialValues[field] = fieldDeclaration.value;

=>>>

this.$initialValues[field] = fieldDeclaration.value;
this.$initialValues = Object.assign({}, this.$initialValues);

【讨论】:

  • $initialValus 是反应式的,问题是访问 Form 实例中的元素
猜你喜欢
  • 2018-04-27
  • 2021-11-09
  • 2016-10-07
  • 1970-01-01
  • 2017-09-06
  • 2018-12-18
  • 2019-07-09
  • 2018-10-26
  • 1970-01-01
相关资源
最近更新 更多