带有嵌套数组的 Vue Js 搜索示例

Posted

技术标签:

【中文标题】带有嵌套数组的 Vue Js 搜索示例【英文标题】:Vue Js Search Example with Nested Arrays 【发布时间】:2021-07-11 23:50:15 【问题描述】:

我有一个有效的 Vue Js 搜索,但我还希望能够在我的 JSON 中搜索 tags 字段。我怎么做?我知道我必须使用|| this.list_search... 添加另一个过滤条件,但是如何遍历标签并返回标签的父级?

任何帮助将不胜感激。

<!doctype html>
<html lang="en" class="min-h-screen bg-gray-300 dark:bg-gray-900" hidden>
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="x-ua-compatible" content="ie=edge" />
    <title>Vue Search</title>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link href="https://unpkg.com/font-awesome@^4.0/css/font-awesome.min.css" rel="stylesheet" />
    <link href="https://fonts.gstatic.com" rel="preconnect" />
    <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@100;400;700&amp;display=swap" rel="stylesheet" />
  </head>
  <body class="min-h-screen bg-gradient-to-b from-gray-50 dark:from-gray-800 to-gray-300 dark:to-black bg-fixed text-gray-500">

    <div class="page min-h-screen flex flex-col" v-cloak>
      <header></header>
      <main class="py-8">
        <section class="mx-auto max-w-xl">
          <fieldset class="py-8 px-4 relative">
            <input type="search" id="search" v-model="list_search" class="appearance-none py-3 px-5 w-full bg-gray-500 bg-opacity-10 block rounded-md transition duration-300 focus:(bg-white outline-none shadow-xl ring(& current)) relative z-20" placeholder="Search" />
            <label for="search" class="w-8 h-8 flex items-center justify-center absolute z-10 right-5 top-1/2 transform -translate-y-1/2"><i class="fa fa-fw fa-search"></i></label>
          </fieldset>
          <section v-if="!list_results.length" class="text(gray-500 opacity-50) font-bold text-2xl uppercase tracking-wider text-center">No Results</section>
          <ul class="divide(y gray-500 opacity-10)">
            <li v-for="(item, index) in list_results" class="p-4">
               item.title 
              <ol v-if="item.tags" class="-mx-2 px-1 text-xs flex flex-wrap">
                <li v-for="(tag, index) in item.tags" class="p-1"><b class="px-1 py-px inline-block rounded bg-gray-500 bg-opacity-25"> tag.title </b></li>
              </ol>
            </li>
          </ul>
        </section>
      </main>
      <footer class="mt-auto py-8 px-4 border(t gray-500 opacity-10) text(gray-500 opacity-50) text-xs font-bold uppercase text-right">
        Made with <svg xmlns="http://www.w3.org/2000/svg" class="-mt-1 mx-1 text-red-500 inline-block"   viewBox="0 0 16 16" role="img" aria-labelledby="foot-love"><title id="foot-love">Love</title><polygon class="fill-current" fill-rule="evenodd" points="8 6 11 3 15 7 8 14 1 7 5 3"></polygon></svg> by <a href="http://craigerskine.com/" class="mx-1">Craig Erskine</a>
      </footer>
    </div>

    <script src="https://unpkg.com/vue/dist/vue.min.js"></script>
    <script>
      // data
      var app = new Vue(
        el: '.page',
        data() 
          return 
            list_search: null,
            list: [
              
                title: 'Colleries unexhaustibly',
                tags: [
                   title: 'Some Tag 1' ,
                   title: 'Ultra Tag 2' ,
                   title: 'Mega Tag 3' 
                ]
              ,
              
                title: 'Reliableness slippingly'
              ,
              
                title: 'Nyctalopy interacinous'
              ,
              
                title: 'Surculose lovesickness'
              ,
              
                title: 'Nonfrosted manicure'
              ,
            ],
          
        ,
        computed: 
          list_results()
            if(this.list_search)
              return this.list.filter((item)=>
                return this.list_search.toLowerCase().split(' ').every(v => item.title.toLowerCase().includes(v))
              )
             else 
              return this.list;
            
          
        
      );
    </script>

    <script type="module">
      import tw, setup, silent from "https://cdn.skypack.dev/pin/twind@v0.16.11-QeLZmrfZsMzGLVRytSNH/mode=imports,min/optimized/twind/shim.js"
      import css, theme, apply from "https://cdn.skypack.dev/pin/twind@v0.16.11-QeLZmrfZsMzGLVRytSNH/mode=imports,min/optimized/twind/css.js"
      import * as colors from "https://cdn.skypack.dev/pin/twind@v0.16.11-QeLZmrfZsMzGLVRytSNH/mode=imports,min/optimized/twind/colors.js"
      import typography from "https://cdn.skypack.dev/pin/@twind/typography@v0.0.2-CxlC88Z1FhV6a2lXcLpI/mode=imports,min/optimized/@twind/typography.js"
      setup(
        mode: silent,
        theme: 
          fontFamily: 
            sans: ['Roboto', 'sans-serif'],
          ,
          extend: 
            colors: 
              gray: colors.gray,
            ,
          ,
        ,
      )
      tw(() => (
        '@global': 
          ':root v-cloak': apply('hidden'),
        
      ))
    </script>

  </body>
</html>

【问题讨论】:

【参考方案1】:

搜索功能应包含标签标题:

new Vue(
  el: '.page',
  data() 
    return 
      list_search: null,
      list: [
          title: 'Colleries unexhaustibly',
          tags: [
              title: 'Some Tag 1'
            ,
            
              title: 'Ultra Tag 2'
            ,
            
              title: 'Mega Tag 3'
            
          ]
        ,
        
          title: 'Reliableness slippingly'
        ,
        
          title: 'Nyctalopy interacinous'
        ,
        
          title: 'Surculose lovesickness'
        ,
        
          title: 'Nonfrosted manicure'
        ,
      ],
    
  ,
  computed: 
    list_results() 
      if (this.list_search) 
        return this.list.filter((item) => 

          // create an array of tag titles (or [])
          const tags = item.tags?.map((
            title
          ) => title.toLowerCase()) ?? []

          // create the full array that must have a match
          const arr = [item.title.toLowerCase(), ...tags]

          // return true if some of the items include the search
          return arr.some(e => e.includes(this.list_search))
        )
       else 
        return this.list;
      
    
  ,
);
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>

<div class="page">
  <input type="text" v-model="list_search" />  list_search 
  <hr> FULL LIST:<br />
  <ul>
    <li v-for="(item, i) in list" :key="i">
       item.title , (
      <span v-for="(tag, j) in item.tags" :key="j">
         tag.title ,
      </span>)
    </li>
  </ul>
  <hr> SEARCHED LIST:<br />
  <ul>
    <li v-for="(item, i) in list_results" :key="i">
       item.title , (
      <span v-for="(tag, j) in item.tags" :key="j">
         tag.title ,
      </span>)
    </li>
  </ul>
</div>

【讨论】:

是的!这正是我一直在寻找的。非常感谢,@muka.gergely

以上是关于带有嵌套数组的 Vue Js 搜索示例的主要内容,如果未能解决你的问题,请参考以下文章

在嵌套数组中搜索列并返回行元素

Vue.js 在数组中搜索关键字

vue.js项目 el-input 组件 监听回车键实现搜索功能示例

vue.js - 使用原始 json 中的嵌套数组时,递归组件不会更新

vue3+typescript+vantUi 实现一个带有搜索功能的 picker选择器

vue 如何实现 Input 输入框模糊查询方法