我有一个演示Vue应用程序,该应用程序渲染了一些城市的一些天气数据。我将Vue哈希路由器用于3条路由:
/
(主页)/weather/:id
(用于特定位置的详细预测)/search/:term
(用于搜索位置)除/search/:term
路由外,其他所有功能均正常运行,当搜索词发生变化时以及在使用浏览器的后退按钮导航回上一个搜索页面时,都需要重新更新。
搜索页面看起来像(url:http://localhost/#/search/lon
):
搜索页面组件:
<template>
<div :key="'search_page_'+$route.params.term" class="page page-search">
<h2 class="page-header">Search Results</h2>
<div class="search-box">
<input type="text" placeholder="search.." v-model="text" />
<button type="button" @click="handleOnClick">Search!</button>
</div>
<Loader v-if="loading" text="Loading.." />
<template v-else-if="data && data.length">
<Weather v-for="place in data" :key="'weather_for_'+place.woeid" :woeid="String(place.woeid)" :city="place.title" />
</template>
<p v-else><b>No results found!</b></p>
</div>
</template>
<script>
// @ is an alias to /src
import Loader from '@/components/Loader.vue'
import Weather from '@/components/Weather.vue'
import store from '@/modules/Store'
const API_URL = '/weather.php?keyword=';
export default {
name: 'search',
components: {
Loader, Weather
},
data: function() {
return {
loading: true,
text: this.$route.params.term ? decodeURIComponent(this.$route.params.term) : '',
data: null
};
},
methods: {
handleOnClick: function() {
this.$router.push({ name: 'search', params: { term: encodeURIComponent(this.text) } });
},
loadData: function( withText ) {
let searchData = store.get('search_'+this.$route.params.term);
if ( searchData ) {
if ( withText ) this.text = decodeURIComponent(this.$route.params.term);
this.data = searchData;
this.loading = false;
} else {
fetch(API_URL+this.$route.params.term)
.then(response => response.json())
.then(jsonResponse => {
store.set('search_'+this.$route.params.term, searchData = jsonResponse);
if ( withText ) this.text = decodeURIComponent(this.$route.params.term);
this.data = searchData;
this.loading = false;
})
.catch(error => console.log(error));
}
}
},
watch: {
'$route': function(to, from) {
if ( from.params.term !== to.params.term )
{
this.loadData(true);
}
}
},
mounted: function() {
this.loadData();
}/*,
updated: function() {
this.loadData();
}*/
}
</script>
路由器配置:
import Vue from 'vue'
import Router from 'vue-router'
import HomePage from './views/HomePage.vue'
import SearchPage from './views/SearchPage.vue'
import WeatherPage from './views/WeatherPage.vue'
Vue.use(Router)
export default new Router({
mode: 'hash',
base: '/',
routes: [
{
path: '/',
name: 'home',
component: HomePage
},
{
path: '/search/:term',
name: 'search',
component: SearchPage
},
{
path: '/weather/:woeid',
name: 'weather',
component: WeatherPage
}
]
})
我已经做到了(尽管在同一页面上更新搜索词时搜索页面有些闪烁,并且不像我期望的那样被动),但是我想知道这是否是我可以采用的最佳方法?还有更好的吗?
例如,我使用生命周期挂钩从API中获取数据,并且还在路由上使用观察程序,以便在同一页面上的搜索字词发生更改时做出反应。还为整个组件添加了:key
属性。但是我有一个印象,可以用更简单/更好的方式来完成。也许我错过了某件事,并且/或者也许我在做两次事情(例如,我不确定loadData
在第一次进入搜索页面时是否被两次调用,因为我loadData
都在mounted
上挂钩和在$route
上进行更改)。
更新
来部分回答问题的2nd
部分:loadData
方法未在首次进入搜索页面时被调用了两次。第一次进入页面时调用mounted
生命周期挂钩,或者从页面内部(包括浏览器的后退按钮)更新搜索页面时触发$route
观察程序,但不能同时使用两个< / strong>。