VueJS ввод Связывание с вложенными данными

Обновить

December 2018

Просмотры

1k раз

1

У меня есть сценарий, где у меня есть некоторые данные в моем состоянии, и некоторые поля ввода на мой взгляд. Какие данные свойства связаны с которой полем ввода определяются другим свойством данных.

Вот HTML:

<div id="app">
  <input v-model="details[fields.one]">
  <input v-model="details[fields.two]">
  <input v-model="details[fields.three]">
</div>

Вот Javascript:

App = new Vue({
  el: '#app',
  data: {
    d: 'Hello Vue.js!',
    details: {
      a: 'aa',
      b: 'bb',
      c: {
        x: 'xx'
      }
    },
    fields: {
      one:'a',
      two: 'b',
      three: 'c.x'
    }
  }
});

Как вы можете видеть данные «Подробнее» свойство быть привязанными к трем полям ввода. Но деталь имен полей в свойстве данных "полей. Связывание one:'a'и two: 'b'прекрасно работает. Тем не менее, 'fields.three'не удается, так как детали данных в C вложен. Как я могу это исправить?

Вот скрипка для этого: https://jsfiddle.net/n17n7b21/3/

2 ответы

2

This won't work because the details object has no property with the key "c.x".

I would recommend you restructure your data model into a flat object (without any nested objects) to make this easier to manage.

If you must have nested properties, then you will have to facilitate the reading and writing to these properties via helper methods:

new Vue({
  el: '#app',

  data: {
    details: {
      a: 'a value',
      b: {
      	a: 'b.a value',
      },
    },
    fields: {
      one: 'a',
      two: 'b.a',
    },
  },

  computed: {
    state() {
      return JSON.stringify(this.details, '\n', 2);
    },
  },

  methods: {
    getValue(object, path) {
      let obj = object;
      for (const key of path.split('.')) {
      	obj = obj[key];
      }
      
      return obj;
    },
    
    setValue(object, path, value) {
      const keys = path.split('.');
      let obj = object;
      for (let i = 0; i < keys.length - 1; i++) {
      	obj = obj[keys[i]];
      }
      
      obj[keys[keys.length - 1]] = value;
    },
  },
});
<script src="https://rawgit.com/vuejs/vue/dev/dist/vue.js"></script>

<div id="app">
  <input :value="getValue(details, fields.one)" @input="setValue(details, fields.one, $event.target.value)">
  <input :value="getValue(details, fields.two)" @input="setValue(details, fields.two, $event.target.value)">
  <pre>{{ state }}</pre>
</div>
1

Since your fields.three is an object and not a scalar value, you can not bind it to your input. One thing you can do is to create a function that checks if fields.one, fields.two and fields.three are each simple objects or have nested object.

You can use this function:

det (param) {
    let strlen = param.length
        if(1 === strlen){
    return param
  }
  let split = param.split('.')

  let details = JSON.parse(JSON.stringify(this.details))
  for (var key in details) {
    if(key == split[0]){
      for (var key2 in details[key]) {
       return details[key][key2]
      }
    }
  }
}

And bind your models to this function with param:

Here is a full working demo https://jsfiddle.net/n17n7b21/6/