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>
作者 {{ post.author_id.username }} 发布时间 {{ post.published_at }} 类型 {{ 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>
这样就可以实现了。