laravel - 使用 VueJS 和 Laravel 的实时搜索引擎

标签 laravel vue.js

我在 VueJS 和 Laravel 中做搜索引擎部分,但我有一个问题不允许我在其他部分中推进。搜索引擎打开,除了我写的时候,它只发送第一个字母或 2 个字母,但并非所有字母都像这张图片中这样:

image of the data you send

the data that I write

之后它在控制台中显示以下错误:

Uncaught (in promise) NavigationDuplicated: Avoided redundant navigation to current location: "/search?q=th"

现在显示我的搜索引擎代码:

<template>
  <div class="form_MCycW">
    <form autocomplete="off" @sumbit.prevent>
      <label class="visuallyhidden" for="search">Search</label>

      <div class="field_2KO5E">
        <input id="search" ref="input" v-model.trim="query" name="search" type="text" placeholder="Search for a movie, tv show or person..." @keyup="goToRoute" @blur="unFocus">

        <button v-if="showButton" type="button" aria-label="Close" @click="goBack">
          <svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 15 15"><g fill="none" stroke="#fff" stroke-linecap="round" stroke-miterlimit="10" stroke-width="1.5"><path d="M.75.75l13.5 13.5M14.25.75L.75 14.25"/></g></svg>
        </button>
      </div>
    </form>
  </div>
</template>

<script>
  import { mapState } from 'vuex';

  export default {
    data() {
      return {
        query: this.$route.query.q ? this.$route.query.q : ''
      }
    },

    computed: {
       showButton() {
           return this.$route.name === 'search';
       },

       ...mapState({
         search: state => state.event.fromPage
       })
     },

     mounted() {
       this.$refs.input.focus();
     },

     methods: {
       goToRoute() {
         if (this.query) {
           this.$router.push({
             name: 'search',
             query: { q: this.query },
           });
         } else {
           this.$router.push({
             path: this.fromPage,
           });
         }
       },

       goBack() {
         this.query = '';

         this.$router.push({
           path: '/',
         });
       },

       unFocus (e) {
         if (this.$route.name !== 'search') {
           const target = e.relatedTarget;

           if (!target || !target.classList.contains('search-toggle')) {
             this.query = '';
             this.$store.commit('closeSearch');
           } 
         }
       }
     }
   }
</script>

这是搜索引擎的另一部分:

<template>
  <main class="main">
    <div class="listing">
      <div class="listing__head"><h2 class="listing__title">{{ title }}</h2></div>
      <div class="listing__items">
        <div class="card" v-for="(item, index) in data.data" :key="index">
          <router-link :to="{ name: 'show-serie', params: { id: item.id }}" class="card__link">
            <div class="card__img lazyloaded"><img class="lazyload image_183rJ" :src="'/_assets/img/covers/posters/' + item.poster" :alt="item.name"></div>
            <h2 class="card__name">{{ item.name }}</h2>
            <div class="card__rating">
              <div class="card__stars"><div :style="{width: item.rate * 10 + '%'}"></div></div>
              <div class="card__vote">{{ item.rate }}</div>
            </div>
          </router-link>
        </div>
      </div>
    </div>
  </main>
</template>
<script>
  import { mapState } from 'vuex';
  let fromPage = '/';

  export default {
    name: "search",

    metaInfo: {
       bodyAttrs: {
        class: 'page page-search'
       }
    },

    computed: {
      ...mapState({
        data: state => state.search.data,
        loading: state => state.search.loading
      }),

      query() {
        return this.$route.query.q ? this.$route.query.q : '';
      },

      title() {
        return this.query ? `Results For: ${this.query}` : '';
      },
    },

    async asyncData ({ query, error, redirect }) {
      try {
        if (query.q) {
          this.$store.dispatch("GET_SEARCH_LIST", query.q);
        } else {
          redirect('/');
        }
      } catch {
         error({ message: 'Page not found' });
      }
    },

    mounted () {
      this.$store.commit('openSearch');
      this.$store.commit('setFromPage', fromPage);

      if (this.data.length == 0 || this.data === null) {
        this.$store.dispatch("GET_SEARCH_LIST", this.query);
      }
      setTimeout(() => {
          this.showSlideUpAnimation = true;
      }, 100);
    },

    beforeRouteEnter (to, from, next) {
      fromPage = from.path;
      next();
    },

    beforeRouteUpdate (to, from, next) {
      next();
    },

    beforeRouteLeave (to, from, next) {
      const search = document.getElementById('search');

      next();

      if (search && search.value.length) {
        this.$store.commit('closeSearch');
      }
    }
  };
</script>

在我的路由部分,它定义如下:

{
  name: 'search',
  path: '/search',
  component: require('../views/' + themeName + '/control/search/index').default
}

它应该是一个实时搜索引擎。非常感谢您帮助解决这个问题...

最佳答案

您需要的是 debounce .它所做的是等待或延迟,直到用户在模型更新或将其发送到服务器之前完成输入。

它如何工作的一个例子是 here

这是它的一个包。 https://github.com/vuejs-tips/v-debounce

关于laravel - 使用 VueJS 和 Laravel 的实时搜索引擎,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63949437/

相关文章:

vue.js - 如何从 NuxtJS 中的 fetch 或 asyncData 钩子(Hook)访问 vuex 存储?

laravel - 仅在需要时使用 Echo 在 Laravel-Vue js 应用程序中建立与 Pusher 的连接

php - Laravel - 将数据库值存储到 Controller 中的变量

php - Laravel 5.6 - 表单在验证后不会重新填充以前的值

php - 为什么我应该继续运行 artisan serve 命令来保持服务器正常工作?

javascript - 如何在递归组件中出现 "Avoid mutating a prop directly"

vue.js - 如何从 nuxt js 组件中的 node_modules 文件夹动态加载 svg 图标?

vue.js - 如何以正确的方式在 Nuxt 项目中添加 Vuepress?

php - 使用非零的数据库编号时,Laravel 6 redis session 不存储到 redis

php - 带有 keyBy 的 Laravel 响应返回对象和数组