使用 EventBus 通过单个文件组件传递 Vue js 搜索过滤器功能

Posted

技术标签:

【中文标题】使用 EventBus 通过单个文件组件传递 Vue js 搜索过滤器功能【英文标题】:Pass Vue js search filter functionality through single file components with EventBus 【发布时间】:2020-10-03 12:20:37 【问题描述】:

我有以下组件:

/components/SearchBlogs.vue 搜索组件以过滤 blog.titleblog.description

/components/BlogList.vue这里我列出了所有的博客项目。

SearchBlogs.vue

<template>
  <div>
    <input type="text" v-model="search" @change="emitSearchValue" placeholder="search blog">
  </div>
</template>

<script>
import  EventBus  from '../event-bus.js'

export default 
  name: 'SearchBlogs',
  data: () => 
    return 
      search: ''
    
  ,
  methods: 
    emitSearchValue() 
      EventBus.$emit('search-value', 'this.search')
    
  

</script>

BlogList.vue

<template>
<div>
  <div v-for="blog in filteredBlogs" :key="blog">
    <BlogListItem :blog="blog" /> 
  </div>
</div>
</template>

<script>
import BlogListItem from './BlogListItem'
import  EventBus  from '../event-bus.js'

export default 
  name: 'BlogList',
  components: 
    BlogListItem,
  ,
  data: () => 
    return 
      blogs: [],
      searchvalue: ''
    
  ,
  computed: 
    filteredBlogs() 
      return this.blogs.filter(blog =>
        blog.name.toLowerCase().includes(
          this.searchvalue.toLowerCase()
        )
      )
    
  ,
  created() 
    fetch('http://localhost:3000/blogs')
    .then(response => 
      return response.json();
    )
    .then(data => 
      this.blogs = data;
    ),
    EventBus.$on('search-value', (search) => 
      this.searchvalue = value;
    )
  

</script>

在另一个页面组件博客我注册了两个组件:

<template>
  <div>
    <h1>Blog</h1>
    <TheSidebar>
      <SearchBlogs />
    </TheSidebar>
    <BlogList/>
  </div>
</template>

任何人都可以看到这里缺少什么吗?我希望,一旦用户在搜索输入(来自SearchBlogs.vue 组件)中输入内容,它就会开始过滤和更新列表。

【问题讨论】:

嘿伙计,添加codesandbox我会为你编辑它并提供解决方案。 @Adam Orlov 这是codesandbox的链接希望你能弄清楚,非常感谢! 你想使用 EventBus 吗?没有必要。可以用它来完成,但没有意义。 我已经更新了我的答案。 【参考方案1】:

看看我的解决方案condesandbox

这里有一个解释: 您不需要使用 EventBus。您可以通过 v-model 与搜索组件通信,使用 prop value 并从 Input 发出更新的 value

那么你的主(列表)组件负责所有的逻辑。

    它保持搜索状态 它保留项目和过滤的项目

感谢您的搜索组件非常清晰,没有数据,这意味着它几乎没有责任。

如果我可以添加一些内容来帮助您理解,请提出问题?

更新

    EventBus 在某些情况下是一个很好的补充。您的案例很简单,无需添加。现在,您的架构“过度设计”。 当您在 EventBus 上添加侦听器时,created:hook您应该始终在组件为destroyed 时将其删除。否则你可能会遇到双重调用功能等问题。这很难调试,试试我他去过那里? 接受我的建议会让您感到“无需记住这个”,因为 Vue 正在为您做这件事。

希望有所帮助。

【讨论】:

好的,谢谢您的解释!我在this issue 上的复选框是否适用相同的原则。如果我得到这个工作,我必须在 List 组件上结合 Search 和 Checkbox 组件,它们应该同时工作。 一般来说应该使用什么或建议。有没有 EventBus? 谢谢解释,很清楚。根据您的示例,我尝试添加复选框。你能明白为什么它不工作吗?这是sandbox 的链接。谢谢 @meez 1. 您的过滤逻辑不正确。 2. 您的value:prop 已注册为字符串。它必须是数组。这里⏩codesandbox.io/s/busy-sun-efo5h?file=/src/components/List.vue 我有一个问题。为了构建我的布局和路线,我进行了以下调整:在路线组件中Blogs.vue 我注册了我的组件:&lt;Search v-model="search" /&gt; &lt;Checkbox v-model="checked" /&gt; &lt;List /&gt;。然后在数据对象中:search: "", checked: [], experiences: [], 这应该工作吗?因为它没有过滤?【参考方案2】:

几个问题,但基本上计算出来的 prop filteredData 看起来像:

computed: 
    filteredData() 
      return this.experiences.filter(
        el => el.category.indexOf(this.search) > -1
      );
    

此外,在将其值传回时,在 'this.search' 周围使用引号,使其成为字符串。

固定沙盒

https://codesandbox.io/s/reverent-lamarr-is8jz

【讨论】:

也可以使用el =&gt; el.category.startsWith(this.search) 只是为了理解这个概念。 el =&gt; el 这里发生了什么?您何时以及如何使用它? 它是一个缩短的箭头函数,相当于(el) =&gt; return el.category.startsWith(this.search) 根据您的示例,我尝试添加搜索框。 ToLowerCase 方法很重要。我还为搜索添加了第二个 EventBus 是否可取?这是sandbox的链接 imo 在主应用程序中使用事件总线是不好的做法(从全局插件公开的事件总线很好,即 this.$modal.open() 等),而是在组件上使用 vues @eventName=""广告用this.$emit('eventName', this.theValue)发出它

以上是关于使用 EventBus 通过单个文件组件传递 Vue js 搜索过滤器功能的主要内容,如果未能解决你的问题,请参考以下文章

EventBus的使用和源码解析

Android EventBus3.x 使用详解

从$emit 到 父子组件通信 再到 eventBus

vue 事件总线EventBus的概念、使用以及注意点

热门技术EventBus 3.0,让事件订阅更简单,从此告别组件消息传递烦恼~

EventBusEventBus 事件总线框架简介 ( EventBus 使用流程 )