Vue.js中computed内includes方法失效问题及解决求助
Vue项目中v-model结合includes实现emoji搜索过滤的问题解决
一、报错原因
你在computed属性里用箭头函数定义了category_emojis,箭头函数没有自身的this上下文,会继承外层作用域的this,这里外层是模块级作用域而非Vue实例,导致this.search无法访问到Vue实例中的search变量,从而报错。而传入固定字符串时不需要依赖this,所以能正常运行。
二、正确实现搜索过滤
不需要用this.emojiesByCategory.push()处理,computed属性本身用于响应式计算,直接在内部完成过滤逻辑、返回符合条件的emoji数组即可。具体修改如下:
修正后的完整代码
<template> <div id="app"> <div class="emoji_picker"> <div class="picker_container"> <input v-model="search" placeholder="搜索emoji"> <div class="category" v-for="category in categories" :key="`category_${category}`" > <span>{{ category }}</span> <div class="emojis_container"> <button v-for="(emoji, index) in category_emojis(category)" :key="`emoji_${category}_${index}`" > {{ emoji }} </button> </div> </div> </div> </div> </div> </template> <script> import data from '../data.json' export default { name: 'App', data() { return { search: "" // 无需emojiesByCategory,直接用computed返回过滤结果 } }, computed: { categories() { return Object.keys(data); }, // 改为普通函数,让this指向Vue实例 category_emojis() { return (category) => { const emojiEntries = Object.entries(data[category]); // 搜索框为空时返回当前分类所有emoji if (!this.search.trim()) { return emojiEntries.map(([key, emoji]) => emoji); } // 筛选键名包含搜索关键词的emoji return emojiEntries .filter(([key]) => key.includes(this.search.toLowerCase())) .map(([key, emoji]) => emoji); } } }, } </script>
关键修改说明
- 替换箭头函数:将
category_emojis: () => (category) => {...}改为普通函数category_emojis() { return (category) => {...} },确保内部this能正确指向Vue实例,正常访问this.search。 - 优化过滤逻辑:
- 用
Object.entries()将分类下的emoji对象转为键值对数组,便于遍历筛选。 - 搜索框为空时返回全量emoji;否则筛选出键名(如"confused")包含关键词的项,提取emoji值返回。
- 加入
toLowerCase()实现不区分大小写的搜索,提升用户体验。
- 用
- 优化key值:将emoji的key改为
emoji_${category}_${index},避免不同分类下index重复导致的key冲突。
三、关于this.emojiesByCategory.push()的说明
不推荐这种实现方式,Vue应保持单向数据流:用户输入(search)驱动computed计算,直接返回结果渲染即可。修改data中的emojiesByCategory会增加数据维护复杂度,而computed本身可自动响应search的变化,无需手动修改data。
内容的提问来源于stack exchange,提问作者VueFrontend
相关产品推荐
相关产品推荐

