【问题标题】:Vue.js reactivity and Object.defineProperty with TypeScriptVue.js 反应性和 Object.defineProperty 与 TypeScript
【发布时间】:2019-11-14 01:04:02
【问题描述】:

我正在 TypeScript 中创建一个类来处理我的表单提交和服务器错误:

export default class Form<Model> {
    private readonly original: Model
    private changes: Partial<Model>

    constructor(data: Model) {
        this.original = data
        Object.keys(this.original).forEach(key => this.initialiseData(key))
    }

    private initialiseData(key) {
        Object.defineProperty(this, key, {
            get: () => this.data[key],
            set: (value) => this.changes[key] = value
        }
    }

    get data(): Model {
        return Object.assign({}, this.original, this.changes)
    }

    post(url: string) {
        // post logic
    }
}

这将在我的 Vue 组件中使用,如下所示:

import { Component, Vue } from 'vue-property-decorator'
import Form from '~/src/vform'

interface LoginForm {
    email: string
    password: string
}

@Component
export default class LoginView extends Vue {
    form: Form<LoginForm> = new Form<LoginForm>({
        email: '',
        password: ''
    })

    async submit() {
        await this.form.post('/auth/login')
    }
}

这可行,功能上,我可以填写表格并将数据提交到服务器。我遇到的问题是 Vue.js 的反应性。因为Form 类中不存在属性,所以数据不会传递给v-model,它只会在表单发生更改后在表单内更新。

除非我在屏幕上显示表单中的数据,否则这不是问题。我现在可以忍受它,但我想知道是否有办法让 Vue 识别我的 Form 类的反应属性,或者是否有更好的方法来实现此功能而不影响类型系统。

【问题讨论】:

    标签: typescript vue.js vuejs2 vue-reactivity


    【解决方案1】:

    嗯,你的操作比vuejs自己做的高多了。 Vuejs 使用 setter 中的 Object.defineProperty 处理响应式数据以重新渲染,但是,您提供的对象已经定义了其不可配置的属性,并且将无法触发 vuejs 的响应式系统。

    为了让它发挥作用:

    export default class Form<Model> {
    
        initialiseData(key) {
            Object.defineProperty(this, key, {
                get: () => this.data[key],
                set: (value) => {
                    this.changes[key] = value
                    this.onChange(key, value)
                },
            })
        }
    
        onChange(key, value) {}
    
    }
    
    import _Form from '~/src/vform'
    
    @Component
    export default class LoginView extends Vue {
        form: any = {}
    
        // Lifecycle hook
        mounted() {
            const vm = this
            class Form extends _Form {
              onChange() {
                  vm.$forceUpdate()
              }
            }
            const form = new Form({
                email: '',
                password: ''
            })
            this.$set('form', form)
        }
    }
    

    通知 vm.$forceUpdate 当你的 Form 属性改变时通知 vuejs 重新渲染。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-31
      • 1970-01-01
      • 2018-06-12
      • 1970-01-01
      • 2020-02-18
      • 1970-01-01
      • 2020-09-15
      • 1970-01-01
      相关资源
      最近更新 更多