Vue(散列)路由器,当散列的一部分发生更改时以及使用浏览器后退按钮进行更新(更好的方法)

时间:2019-05-05 12:40:12

标签: javascript vuejs2 vue-router

我有一个演示Vue应用程序,该应用程序渲染了一些城市的一些天气数据。我将Vue哈希路由器用于3条路由:

  1. /(主页)
  2. /weather/:id(用于特定位置的详细预测)
  3. /search/:term(用于搜索位置)

/search/:term路由外,其他所有功能均正常运行,当搜索词发生变化时以及在使用浏览器的后退按钮导航回上一个搜索页面时,都需要重新更新。

搜索页面看起来像(url:http://localhost/#/search/lon):

enter image description here

搜索页面组件:

<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>。

0 个答案:

没有答案