不调用Vue v-model和代理第一组

问题描述 投票:1回答:1

目前我正在开发一个Vue项目,我想要一个模型类,它将所有初始数据存储在两个属性中:originalattributes。但是我遇到了通过v-model将属性绑定到输入的困难。

可以说我有以下课程:

class Model
{
    constructor () {
        return new Proxy(this, {
            get: (target, property, receiver) => {
                console.log('get');
                return target[property];
            },

            set: (target, property, value, receiver) => {
                console.log('set');
                target[property] = value + 123;
                return true;
            }
        });
    }
}

这个类将在获取属性时记录get,在设置属性时记录set。同时设置它会在值的末尾添加123。将执行以下操作:

let model = new Model();

model.name = 'test'; // Logs: 'set'

console.log(model.name); // Logs: 'get' and 'test123'

这按预期工作。

当我通过v-model将这些属性绑定到输入时,问题就开始了。发生以下情况:

操作执行于:

<input v-model="model.name" />
...
data () {
    return {
        model: new Model
    };
}

在第一次更改时,属性name将被添加到model对象中。根本没有日志。没有在值的末尾添加123。模型值已更改为{ model: 't' }

第二次更改它将记录set,它将添加123。模型值已更改为{ model: 'te123' }

在第二次更改期间记录set调用的参数:Model {__ob__: Observer}, "name", "te", Proxy {__ob__: Observer}

以前有人遇到过这个问题,或者知道这里发生了什么?

回答@sphinx之后

谢谢您的回答!有用!

为了使事情变得更复杂,我希望在一个名为fillable的属性中设置某个attributes数组中的属性。但是返回相同的行为。

class Model
{
    constructor () {
        this.attributes = {};
        this.fillable = ['name'];

        return new Proxy(this, {
            get: (target, property, receiver) => {
                console.log('get', property);

                if (target.fillable.indexOf(property) > -1) { // Check if in fillable
                    if (!(property in  target.attributes)) {
                        Vue.set(target.attributes, property, null);
                    }

                    return target.attributes[property];
                }

                return target[property];
            },
            set: (target, property, value, receiver) => {
                console.log('set', property, value);

                if (target.fillable.indexOf(property) > -1) {
                    Vue.set(target.attributes, property, value + 123);
                } else {
                    target[property] = value
                }

                return true;
            }
        });
    }
}
Vue.config.productionTip = false

new Vue({
  el: '#app',
  data() {
    return {
      test: new Model
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>

<div id="app">
  <span>{{test.name}}</span>
    <input v-model="test.name" type="text">
</div>

在第一次更改期间,name属性直接设置在model对象上。但是没有调用set方法。

在第二次更改期间,name属性正在改变,并且调用set方法。

为何会出现这种情况的建议?

javascript vue.js proxy
1个回答
1
投票

在你的例子中,getter将创建一个属性,但它不是反应性(检查Vue Guide: Reactivity In Depth)。

所以Vue无法跟踪变化。

解决方案很容易,如上面的指南介绍,使用Vue.setvm.$set来确保您的对象是反应性。

如下演示:

class Model
{
    constructor () {
        return new Proxy(this, {
            get: (target, property, receiver) => {
                console.log('get', property);
                if(!(property in target)) Vue.set(target, property, null)
                return target[property]
            },
            set: (target, property, value, receiver) => {
                console.log('set', property, value);
                Vue.set(target, property, value + 123)
                return true;
            }
        });
    }
}
Vue.config.productionTip = false
new Vue({
  el: '#app',
  data() {
    return {
      test: new Model
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>

<div id="app">
  <span>{{test.name}}</span>
    <input v-model="test.name" type="text">
</div>
© www.soinside.com 2019 - 2024. All rights reserved.