【问题标题】:Setting nested object property by string path通过字符串路径设置嵌套对象属性
【发布时间】:2019-04-13 10:47:08
【问题描述】:

我有 3 个选择框,我希望它们在选择时重置某个字段。如何使其动态化,以便可重复使用?

这是我的代码的摘录:

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

getDate(url, obj, obj2, event){

     let current = this

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

}

obj 位于Vue 实例的根级别(即current[obj])时,它会正确设置属性;但当obj 是嵌套对象时则不然。

【问题讨论】:

    标签: javascript vue.js vuejs2 vue-component


    【解决方案1】:

    在 JavaScript 中,property accessors 不允许嵌套 对象路径,这是您在点分隔字符串中所拥有的。通过使用该字符串,您实际上是在根 Vue 实例上创建一个属性,而不是设置一个嵌套属性,类似于:

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

    要通过路径设置对象值,您可以创建一个方法,使用对象路径通过this 导航当前 Vue 实例的数据属性:

    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: {
            company: {
              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.com/vue@2.6.10"></script>
    
    <div id="app">
      <input v-model="input1">
      <input v-model="form.company.input2">
      <input v-model="form.company.input3">
    
      <button @click="getDate(route('api.v1.get.date'), 'input1', ['form.company.input2', 'form.company.input3'], $event)">
        Reset data
      </button>
    </div>

    或者,您可以使用库(例如 lodash_.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: {
            company: {
              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.com/lodash@4.17.11/lodash.js"></script>
    <script src="https://unpkg.com/vue@2.6.10"></script>
    
    <div id="app">
      <input v-model="input1">
      <input v-model="form.company.input2">
      <input v-model="form.company.input3">
    
      <button @click="getDate(route('api.v1.get.date'), 'input1', ['form.company.input2', 'form.company.input3'], $event)">
        Reset data
      </button>
    </div>

    【讨论】:

      【解决方案2】:

      尝试使用this.$set函数如下:

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

      了解更多关于该功能here

      【讨论】:

      • 似乎我在使用 set 方法时遇到了这个错误,数据已经设置但我仍然收到这个错误“[Vue 警告]:避免将反应属性添加到 Vue 实例或其根 $运行时的数据 - 在 data 选项中预先声明它。"
      • current[obj] 是通过 props 传递的?
      • 函数在同一个实例中,我通过 v-select "form.compay.input2"
      【解决方案3】:

      此库允许您使用嵌套对象路径。

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

      您的摘录如下所示:

      v-on:select="getDate('{{ route('api.v1.get.date') }}', 'input1', ['form.company.input2', 'form.company.input3'], $event)"
      
      getDate(url, obj, obj2, event){
      
           let current = this
      
           current.$op.set(obj, '')
           current.$op.set(obj2[0], '')
           current.$op.set(obj2[1], '')
      
      }
      

      【讨论】:

        【解决方案4】:

        用于 gettingsetting 嵌套值在 object 内,路径为 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
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-12-23
          • 2014-04-11
          • 1970-01-01
          • 2011-09-23
          相关资源
          最近更新 更多