Vue V模型数据来自Ajax未定义值

时间:2019-10-05 08:56:42

标签: vue.js

我使用了vue2。我有一个来自ajax的数据,这是我的代码示例:

<template>
    <div>
        <input type="input" class="form-control" v-model="siteInfo.siteId">
        <input type="input" class="form-control" v-model="siteInfo.info.name">
        <input type="input" class="form-control" v-model="siteInfo.accountData.name">
    </div>
</template>

<script>
export default {
    name: 'Site',
    data() {
        return {
            siteInfo: {},
            /* siteInfoName: '', */
        }
    },
    /*computed: {
        siteInfoName: function() {
            return siteInfo.info.name || '';
        },
        ...
    },*/
    methods: {
        getData() {
            // do ajax get data
            this.$http.post('URL', {POSTDATA}).then(response => {
                /*
                   response example
                   { body: 
                       data: {
                           sitdeId: 1,
                           info: { name: 'test'},
                           accountData: { name: 'accountTest'},
                       }
                   }
                */
                this.siteInfo = response.body.data;
            })
        }
    },
    mounted() {
        this.getData();
    }
}
</script>

我收到了好战的消息

  

[Vue警告]:渲染错误:“ TypeError:无法读取属性'name'   的不确定”

  1. 我可以使用computed来修复它,但是如果我有很多模型,我应该 写很多计算。
  2. 我应该为这些模型创建很多数据吗?
  3. 我不应该使用对象来绑定很多模型吗?

对于这种情况,它还有其他解决方案吗?谢谢您的帮助。

2 个答案:

答案 0 :(得分:3)

在数据加载siteInfo.info之前为undefined,因此您无法在name中访问v-model

v-model="siteInfo.info.name"

siteInfo.accountData.name类似。

我的建议是将siteInfo的初始值设置为null,然后在主v-if="siteInfo"上放置一个div。另外,您可以在单独的v-if元素上放置input来检查siteInfo.infositeInfo.accountData

您可能还想考虑在加载数据时显示替代内容,例如加载掩码。

答案 1 :(得分:0)

不用担心太多的v模型-您可以在 Object 上进行迭代-就像使用Object.entries()一样。

Vue.component('list-input-element', {
  props: ['siteLabel', 'siteInfo'],
  template: '<div><label>{{siteLabel}}<input type="input" class="form-control" v-model="siteInfo"></label></div>'
})

new Vue({
  name: 'Site',
  el: '#app',
  data() {
    return {
      siteInfo: {},
    }
  },
  methods: {
    getData() {
      // using mockup data for this example
      fetch('https://jsonplaceholder.typicode.com/todos/1')
        .then(response => response.json())
        .then(json => {
          console.log(json)
          this.siteInfo = json
        })
      // do ajax get data
      /*this.$http.post('URL', {
        POSTDATA
      }).then(response => {
        this.siteInfo = response.body.data;
      })*/
    }
  },
  mounted() {
    this.getData();
  }
})
div {
  display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <list-input-element v-for="siteInfo in Object.entries(siteInfo)" :site-label="siteInfo[0]" :site-info="siteInfo[1]" />
</div>

向上环绕

因此,当您制作单个文件模板时,请使用 computing (计算值)值,然后从中返回 Object

基于该计算 v-,您不会有任何问题。

类似这样的东西:

<template>
    <div>
        <input type="input" class="form-control" v-for="infoEl in siteInfoComputed" v-model="infoEl">
    </div>
</template>

<script>
export default {
    name: 'Site',
    data() {
        return {
            siteInfo: {},
        }
    },
    computed: {
      siteInfoComputed: function() {
          // you could check for all the keys-values you want here, and handle
          // 'undefined' problem here
          // so, actually you "create" the Object here that you're going to use
          let ret = {}
          // checking if this.siteInfo exists
          if (Object.keys(this.siteInfo).length) ret = this.siteInfo
          return ret
      },
    },
    methods: {
        getData() {
            // do ajax get data
            this.$http.post('URL', {POSTDATA}).then(response => {
                /*
                   response example
                   { body: 
                       data: {
                           sitdeId: 1,
                           info: { name: 'test'},
                           accountData: { name: 'accountTest'},
                       }
                   }
                */
                this.siteInfo = response.body.data;
            })
        }
    },
    mounted() {
        this.getData();
    }
}
</script>