Vue模糊搜索同页面下的实时更新显示难点

Vue模糊搜索同页面下的实时更新显示难点问题解决:
(走了很多坑纵欲解决了):
Home.vue页面通过路由导入使用了A和B两个页面A为输入搜索内容,B为实时显示内容结果。废话不多说实践是王道直接上代码:
先配置号路由:我的路由如下:

 {path: '/h', name: 'Homes', component:() => import('../components/view/Test/SUJU/Homes.vue')},
    {path: '/s', name: 'Sous', component:() =>import('../components/view/Test/SUJU/Sous.vue')},
    {path: '/x', name: 'Xs', component:() => import('../components/view/Test/SUJU/Xs.vue')},

Homes.vue导入使用Sous.vue和Xs.vue界面

<template>
  <lay-layout className="example">
    <lay-header>
      <Sous/>
    </lay-header>
    <lay-body>
      <Xs :key="componentKey"/> <!--Xs组件设置一个动态的key以触发其更新 -->
    </lay-body>
  </lay-layout>
</template>

<script>
import Sous from "@/components/view/Test/SUJU/Sous";
import Xs from "@/components/view/Test/SUJU/Xs";
import eventBus from "@/components/view/Test/SUJU/EventBus.js";

export default {
  name: "Homes",
  components: {Sous, Xs},
  data() {
    return {
      componentKey: 0 // 用于为Xs组件设置动态key以触发其更新
    };
  },
  created() {
    this.$watch(() => eventBus.searchResults, () => {
      this.componentKey += 1; // 当searchResults值变动时,增加componentKey以达到刷新Xs组件的效果
    });
  }
};
</script>

<style scoped>
.example .layui-header {
  line-height: 60px;
  text-align: center;
  background: #87ca9a;
  color: white;
}

.example .layui-body {
  display: flex;
  background: #5FB878;
  align-items: center;
  justify-content: center;
  color: white;
}
</style>

Sous.vue

<!--Header.vue-->
<template>
  <lay-menu class="layui-menu-body-header" v-model:selected-key="selectedKey" v-model:open-keys="openKeys1">


    <lay-menu-item class="search">
      <lay-input  allow-clear="false"
                  style="color: black;background: #2c3e50;"
                  placeholder="搜索输入"
                  prefix-icon="layui-icon-search"
                  v-model="searchInput"
                  @keydown.enter="searchPosts"/>
    </lay-menu-item>



  </lay-menu>
</template>
<script>
import { ref ,watch } from 'vue';
import { SearchFetch } from "@/components/js/header/Search.js";
import eventBus from "@/components/view/Test/SUJU/EventBus.js";
export default {
  name: "Sous",
  setup() {
    // 搜索
    const searchInput = ref("");
    const {searchPosts} = SearchFetch(searchInput);
    // 监听searchPosts函数的结果并将其发送到事件总线
    watch(searchPosts, (newResults) => {
      eventBus.searchResults = newResults;
    });

    return {
      searchInput,
      searchPosts,
    };
  }
}
</script>


<style scoped>
.layui-menu-body-header {
  margin-top: 0vh;
  margin-bottom: 1000vh;
}

.layui-menu-item-home {
  margin-left: 1vh;
}

.search {
  width: 300px;
  margin-left: 40vh;
  border-color: white;
  background-color: #393d49 /* 或其他明显颜色 */
}

</style>

封装好的外部js

import axios from "axios";
import { layer } from "@layui/layer-vue";
import { useStore } from 'vuex';

export function SearchFetch(searchInput) {
    const store = useStore();

    const searchPosts = async () => {
        try {
            const response = await axios.post('/api/posts/findPostsByTitle', { title: searchInput.value });

            if (response.data.message === "查询成功") {
                layer.msg(response.data.message);
                await store.dispatch('updateSearchResults', response.data.data);            } else {
                layer.msg(response.data.errorCode);
                console.log("查询失败");
                await store.dispatch('updateSearchResults', null);
            }
        } catch (error) {
            layer.msg("服务器错误");
            await store.dispatch('updateSearchResults', null);
            console.error(error);
        }
    };

    return {
        searchPosts
    };
}

在这里插入代码片
import { reactive } from 'vue';

// 创建一个新的事件总线
const eventBus = reactive({
    searchResults: []
});

export default eventBus;

将搜索到的结果存入Store当中再发送到浏览器本地进行存储

// store.js
import { createStore } from "vuex";

const store = createStore({
    state:{
        token: '',
        searchResults: [],
    },
    getters:{
        getToken(state){
            return state.token || localStorage.getItem("userToken");
        },
        getSearchResults(state) {
            return state.searchResults;
        },
    },
    mutations:{
        setToken(state, token){
            state.token = token;
        },
        delToken(state){
            state.token = '';
            localStorage.removeItem("userToken");
        },
        setSearchResults(state, results) {
            state.searchResults = results;
            localStorage.setItem("searchResults", JSON.stringify(results)); // Save searchResults to localStorage
        },
    },
    actions: {
        updateSearchResults({ commit }, results) {
            commit('setSearchResults', results);
        },
    },
});

export default store;

Xs.vue再从浏览器本地获取
Xs.vue

<template>
  <div>
    11111
    <ul v-if="hasValidSearchResults">
      <li v-for="post in searchResults" :key="post.post_id">
        <lay-panel shadow="hover">
          <h2>{{ post.title }}</h2>
          作者&nbsp;&nbsp;{{ post.author_id.username }}&nbsp;&nbsp;发布时间&nbsp;&nbsp;{{ post.published_at }}&nbsp;&nbsp;类型&nbsp;&nbsp;{{ post.category_id.name }}
          <p>简述:{{ post.excerpt }}</p>
          <p v-html="post.content"></p>
        </lay-panel>
      </li>
    </ul>
  </div>
</template>

<script>
import { ref, onMounted, watch } from 'vue';

export default {
  name: 'Test',
  setup() {
    const searchResults = ref([]);
    const hasValidSearchResults = ref(true);

    // 在组件挂载后从本地存储加载数据
    onMounted(() => {
      loadSearchResultsFromLocalStorage();
    });

    // 监听本地存储变化,更新searchResults
    window.addEventListener('storage', (event) => {
      if (event.key === 'searchResults') {
        const storedResults = event.newValue;
        if (storedResults) {
          try {
            const parsedResults = JSON.parse(storedResults);
            if (Array.isArray(parsedResults)) {
              searchResults.value = parsedResults;
              hasValidSearchResults.value = true;
            } else {
              console.error('从本地存储中获取的数据不是一个数组');
              hasValidSearchResults.value = false;
            }
          } catch (error) {
            console.error('从本地存储中获取的数据无法解析为有效的 JSON');
            hasValidSearchResults.value = false;
          }
        } else {
          hasValidSearchResults.value = false;
        }
      }
    });

    function loadSearchResultsFromLocalStorage() {
      const storedResults = localStorage.getItem("searchResults");
      if (storedResults) {
        try {
          const parsedResults = JSON.parse(storedResults);
          if (Array.isArray(parsedResults)) {
            searchResults.value = parsedResults;
            hasValidSearchResults.value = true;
          } else {
            console.error('从本地存储中获取的数据不是一个数组');
            hasValidSearchResults.value = false;
          }
        } catch (error) {
          console.error('从本地存储中获取的数据无法解析为有效的 JSON');
          hasValidSearchResults.value = false;
        }
      } else {
        hasValidSearchResults.value = false;
      }
    }

    return {
      searchResults,
      hasValidSearchResults
    };
  }
}
</script>

这样就可以实现了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值