最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Setting nested object property by string path - Stack Overflow

programmeradmin4浏览0评论

I have 3 select boxes, and I would like them to reset a certain field on select. How can I make it dynamic, so that it is reusable?

Here's an excerpt of my code:

v-on:select="getDate('{{ route('api.v1.get.date') }}', 'input1', ['formpany.input2', 'formpany.input3'], $event)"

getDate(url, obj, obj2, event){

     let current = this

     current[obj] = ''
     current[obj2[0]] = ''
     current[obj2[1]] = ''

}

When obj is at the root level of the Vue instance (i.e., current[obj]), it sets the property correctly; but not when obj is a nested object.

I have 3 select boxes, and I would like them to reset a certain field on select. How can I make it dynamic, so that it is reusable?

Here's an excerpt of my code:

v-on:select="getDate('{{ route('api.v1.get.date') }}', 'input1', ['form.pany.input2', 'form.pany.input3'], $event)"

getDate(url, obj, obj2, event){

     let current = this

     current[obj] = ''
     current[obj2[0]] = ''
     current[obj2[1]] = ''

}

When obj is at the root level of the Vue instance (i.e., current[obj]), it sets the property correctly; but not when obj is a nested object.

Share Improve this question edited Aug 22, 2019 at 10:10 Boussadjra Brahim 1 asked Apr 13, 2019 at 10:47 Karl WongKarl Wong 6052 gold badges9 silver badges23 bronze badges
Add a ment  | 

4 Answers 4

Reset to default 6

In JavaScript, property accessors do not allow nested object paths, which is what you have in the dot-separated string. By using that string, you're actually creating a property on the root Vue instance instead of setting a nested property, similar to this:

this['form.pany.input2'] = ''  // XXX: creates `form.pany.input2` prop
this.form.pany.input2 = ''     // sets `input2`

To set the object value by path, you could create a method that uses the object path to navigate the current Vue instance's data properties via this:

methods: {
  getDate(url, obj, obj2, event) {
    this.setValue(obj, '')
    this.setValue(obj2[0], '')
    this.setValue(obj2[1], '')
  },
  setValue(path, value) {
    let obj = this
    const parts = path.split('.')
    while (parts.length > 1 && obj.hasOwnProperty(parts[0])) {
      obj = obj[parts.shift()]
    }
    obj[parts[0]] = value
  }
}

new Vue({
  el: '#app',
  data() {
    return {
      input1: 'input1',
      form: {
        pany: {
          input2: 'input2',
          input3: 'input3'
        }
      }
    }
  },
  methods: {
    getDate(url, obj, obj2, event) {
      this.setValue(obj, '')
      this.setValue(obj2[0], '')
      this.setValue(obj2[1], '')
    },
    setValue(path, value) {
      let obj = this
      const parts = path.split('.')
      while (parts.length > 1 && obj.hasOwnProperty(parts[0])) {
        obj = obj[parts.shift()]
      }
      obj[parts[0]] = value
    },
    route(prop) {
      return prop
    }
  }
})
<script src="https://unpkg./[email protected]"></script>

<div id="app">
  <input v-model="input1">
  <input v-model="form.pany.input2">
  <input v-model="form.pany.input3">

  <button @click="getDate(route('api.v1.get.date'), 'input1', ['form.pany.input2', 'form.pany.input3'], $event)">
    Reset data
  </button>
</div>

Alternatively, you could use a library (such as lodash's _.set):

methods: {
  getDate(url, obj, obj2, event) {
    _.set(this, obj, '')
    _.set(this, obj2[0], '')
    _.set(this, obj2[1], '')
  }
}

new Vue({
  el: '#app',
  data() {
    return {
      input1: 'input1',
      form: {
        pany: {
          input2: 'input2',
          input3: 'input3'
        }
      }
    }
  },
  methods: {
    getDate(url, obj, obj2, event) {
      _.set(this, obj, '')
      _.set(this, obj2[0], '')
      _.set(this, obj2[1], '')
    },
    route(prop) {
      return prop
    }
  }
})
<script src="https://unpkg./[email protected]/lodash.js"></script>
<script src="https://unpkg./[email protected]"></script>

<div id="app">
  <input v-model="input1">
  <input v-model="form.pany.input2">
  <input v-model="form.pany.input3">

  <button @click="getDate(route('api.v1.get.date'), 'input1', ['form.pany.input2', 'form.pany.input3'], $event)">
    Reset data
  </button>
</div>

Try to use this.$set function as follows:

  this.$set(current,obj,'');
 this.$set(current,obj2[0],'');
 this.$set(current,obj2[1],'');

learn more about that function here

This library allows you to use nested object paths.

https://www.npmjs./package/vue-data-object-path

Your excerpt would look like this:

v-on:select="getDate('{{ route('api.v1.get.date') }}', 'input1', ['form.pany.input2', 'form.pany.input3'], $event)"

getDate(url, obj, obj2, event){

     let current = this

     current.$op.set(obj, '')
     current.$op.set(obj2[0], '')
     current.$op.set(obj2[1], '')

}

For getting or setting nested values inside an object having the path as string

function getNestedValue(obj, path){
    return path.split('.').reduce((o,i)=> o[i] || '', obj)
}

function setNestedValue(obj, path, value) {
    let i;
    path = path.split('.');
    for (i=0;i<path.length-1;i++) obj = obj[path[i]];
    obj[path[i]] = value
}

const obj = { a:{ b: [{c: 1 },{ d: 2 }] }}

setNestedValue(obj,'a.b.0.c',3)
console.log(getNestedValue(obj, 'a.b.0.c'))  // 3
发布评论

评论列表(0)

  1. 暂无评论