【问题标题】:Vue search Ajax response array while typingVue在键入时搜索Ajax响应数组
【发布时间】:2017-07-20 11:22:28
【问题描述】:

我在输入从 Ajax 调用获得的文本框时尝试过滤列表。问题似乎是在 Ajax 准备好之前应用了过滤器。

HTML:

<input type="text" class="form-control" v-model="searchTerm">
<table>
    <tr v-for="food in filteredItems">
      <td>{{ food.name }}</td>
      <td>{{ food.energy }}</td>
    </tr>
</table>

helpers/index.js:

export default {
  getFoods() {
  return Vue.http.get('http://localhost:3000/foods/allfoods')
         .then((response) => {
             return response.data;
    });
  }
}

Vue 组件:

import helpers from '../helpers'
export default {
  name: 'Search',
  mounted() {
    helpers.getFoods().then((response) => {
      this.foodData = response;
    });
  },
  data() {
    return {
      searchTerm: '',
      foodData: [],
    }
  },
  computed: {
    filteredItems() {
      return this.foodData.filter(function(food){return food.name.toLowerCase().indexOf(this.searchTerm.toLowerCase())>=0;});
    }
  }

当我加载页面或开始输入时,我得到

'TypeError: undefined is not an object (evaluate 'this.searchTerm')'。

如果我对 foodData 数组进行硬编码,一切都会完美运行。

我是否误解了什么和/或我做错了什么?

【问题讨论】:

  • 两个问题: 1. 您是否尝试过修复filteredItems 中的this 引用? 2.你在哪里/如何设置searchTerm?我在您的模板中没有看到它。
  • 将丢失的 添加到我忘记在此处添加的 HTML 中。您能解释一下修复这些引用的含义吗?
  • 伯特说了什么;)

标签: javascript node.js ajax vue.js


【解决方案1】:

在计算中过滤器函数的回调中,this 没有指向 Vue。

computed: {
  filteredItems() {
    return this.foodData.filter(function(food){
      // in this next line, this.searchTerm is likely undefined
      // because "this" is not the Vue
      return food.name.toLowerCase().indexOf(this.searchTerm.toLowerCase()) >= 0;
    });
  }
}

这是因为您使用 function(food){...} 作为回调,而 this 将是包含范围。而是使用箭头函数、闭包或bind

computed: {
  filteredItems() {
    return this.foodData.filter(food => {
      // in this next line, this.searchTerm is likely undefined
      // because "this" is not the Vue
      return food.name.toLowerCase().indexOf(this.searchTerm.toLowerCase()) >= 0;
    });
  }
}

console.clear()

const foods = [{
    name: "orange",
    energy: 10
  },
  {
    name: "apple",
    energy: 8
  },
  {
    name: "banana",
    energy: 12
  },
  {
    energy: 1000
  }
]

const Search = {
    name: 'Search',
    template: `
      <div>
        <input type="text" class="form-control" v-model="searchTerm">
        <table>
          <tr v-for="food in filteredItems">
            <td>{{ food.name }}</td>
            <td>{{ food.energy }}</td>
           </tr>
         </table>   
      </div>
    `,
    mounted() {
      setTimeout(() => this.foodData = foods, 500)
    },
    data() {
      return {
        searchTerm: '',
        foodData: [],
      }
    },
    computed: {
      filteredItems() {
        const searchTerm = this.searchTerm.toLowerCase()
        return this.foodData
           .filter(food => food.name && food.name.toLowerCase().includes(searchTerm))
      }
    }
  }
new Vue({
  el:"#app",
  components: {Search}
})
<script src="https://unpkg.com/vue@2.2.6/dist/vue.js"></script>
<div id="app">
  <search></search>
</div>

How to access the correct this inside a callback

【讨论】:

  • 感谢您的回答。但不幸的是,这并没有解决它。通过切换到箭头函数,我得到'TypeError:undefined is not an object (evalating 'food.name.toLowerCase')' 感谢您提供链接。这绝对值得一读。
  • @ArtoSaarinen 你所有的food 对象都有name 吗?
  • @ArtoSaarinen 添加了一个工作示例(带有模拟的 API 调用)。看看你能不能看出区别在哪里。
  • 实际上可能有一个条目没有 name 属性。数据库显示有 1345 个条目,当在 atom 中查找 'name' 时,它仅显示 1344 个出现。现在必须浏览所有这些。
  • @ArtoSaarinen 缺少name 肯定会导致编写的代码出现问题,因为您无法在未定义时调用toLowerCase
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-11
  • 2023-03-24
  • 2021-11-23
  • 1970-01-01
相关资源
最近更新 更多