除非刷新页面,否则我的搜索按钮不会呈现新信息

问题描述 投票:0回答:1

我正在使用 Vue3 为我在学校的项目创建一个天气网络应用程序。它工作得很好,直到您搜索城市时它仍然为您提供有关最后渲染的城市的信息。假设我搜索俄亥俄州并单击搜索按钮,它就会呈现。现在,如果我搜索伦敦并单击搜索按钮,呈现的信息仍然是俄亥俄州的信息。刷新页面时,现在会呈现有关伦敦的正确信息。

我正在关注 John Komanicki 在 Vue3 上的系列文章。

这是我的 Navigation.vue 组件,其中包含搜索栏:

<template>
  <header class="sticky top-0 shadow-md z-50 bg-background">
    <nav class="px-24 flex items-center justify-between gap-3 text-text py-5 max-md:py-4 max-sm:px-2">
      <RouterLink :to="{name: 'home'}">
        <div class="flex items-center gap-3">
          <i class="fa-solid fa-cloud-meatball fa-2xl text-primary"></i>
          <p class="text-3xl font-semibold text-primary max-md:text-xl">ClearVue</p>
        </div>
      </RouterLink>

      <!-- Search Bar -->
      <div class="relative w-[46%]">
        <input v-model="searchQuery" type="text" placeholder="Search for a City" class="py-2 px-2 w-full bg-transparent rounded-md border border-gray-300 focus:border-secondary focus:outline-none placeholder:text-sm placeholder:font-Lexend" @input="getSearchResults">

        <div class="flex items-center justify-center absolute bg-accent w-9 h-9 right-[3px] top-[3px] rounded-[4px] cursor-pointer hover:opacity-80" @click="previewCityFromButton">
          <i class="fa-solid fa-magnifying-glass text-white"></i>
        </div>

        <ul v-if="geoCodingSearchResults && showDropdown" class="absolute bg-gray-200 text-text w-full shadow-sm py-1 px-1 top-[44px] rounded-md">

          <p v-if="searchError">Sorry, something went wrong. Please, try again!</p>
          <p v-if="!searchError && geoCodingSearchResults.length === 0" class="py-1 px-1">No results found. Try a different City.</p>

          <template v-else>
            <li v-for="searchResult in geoCodingSearchResults" :key="searchResult.id" class="py-1 px-1 rounded-[4px] cursor-pointer hover:bg-gray-300 duration-150 ease-out" @click="pushSearchQuery(searchResult)">
              {{ `${searchResult.name}, ${searchResult.state}, ${searchResult.country}` }}
            </li>
          </template>
        </ul>
      </div>

      <!-- Nav Links -->
      <ul class="flex items-center gap-8 font-semibold text-text max-md:text-sm max-sm:hidden">
        <li class="hover:text-secondary duration-150 ease-out cursor-pointer" @click="openModal('about')">About ClearVue</li>
        <li class="hover:text-secondary duration-150 ease-out cursor-pointer" @click="openModal('how')">How it works</li>
      </ul>

      <Modal :modalActive="modalActive" @close-modal="toggleModal">
        <div class="text-text" v-if="selectedLink === 'about'">
          <h1 class="text-xl mb-4 font-semibold">
            About ClearVue:
          </h1>
          <p>ClearVue is a user-friendly and intuitive weather application designed to provide you with up-to-date weather information at your fingertips.<br><br> Whether you're planning your day, a trip, or simply want to stay informed about the weather conditions, ClearVue has you covered.</p>
        </div>
        <div class="text-text" v-if="selectedLink === 'how'">
          <h1 class="text-xl mb-4 font-semibold">
            How it works:
          </h1>
          <p>
            ClearVue is a user-friendly weather application that provides accurate and real-time weather information. Here's how it works:
          </p>
          <ul>
            <li>1. Start by entering a location to search for.</li>
            <li>2. View current weather conditions, including temperature, wind speed, humidity, and more.</li>
            <li>3. Track a City to view at a later time.</li>
          </ul>
        </div>
      </Modal>

    </nav>
  </header>
</template>
<script setup>
  import { RouterLink } from 'vue-router';
  import Modal from './Modal.vue';
  import { ref } from 'vue';
  import { useRouter } from 'vue-router';
  import axios from 'axios';

  // Modal scripts
  const modalActive = ref(false);
  const selectedLink = ref(null);

  const openModal = (link) => {
    selectedLink.value = link;
    modalActive.value = true;
  }

  const toggleModal = () => {
    modalActive.value = !modalActive.value;
  };

  // Input scripts
  const searchQuery = ref("");
  const queryTimeout = ref(null);
  const geoCodingAPIKey = 'e7a0834d5c68a78d2a20c4ade200a188';
  const geoCodingSearchResults = ref(null);
  const searchError = ref(null);

  const getSearchResults = () => {
    clearTimeout(queryTimeout.value);
    queryTimeout.value = setTimeout(async () => {
      if (searchQuery.value !== "") {
        try {
          const result = await axios.get(`http://api.openweathermap.org/geo/1.0/direct?q=${searchQuery.value}&limit=5&appid=${geoCodingAPIKey}`);
          geoCodingSearchResults.value = result.data;
        } catch {
          searchError.value = true;
        }
        return;
      };
      geoCodingSearchResults.value = null;
    }, 200)
  };

  let lastSelectedSearchResult = ref(null);

  const previewCityFromButton = () => {
    if (lastSelectedSearchResult.value) {
      previewCity(lastSelectedSearchResult.value);
    }
    searchQuery.value = ""
  };
  
  const showDropdown = ref(true);

  const pushSearchQuery = (searchResult) => {
    searchQuery.value = `${searchResult.name}, ${searchResult.state}, ${searchResult.country}`;
    showDropdown.value = false;
    lastSelectedSearchResult.value = searchResult;
  };

  const router = useRouter();

  const previewCity = (searchResult) => {
    console.log(searchResult);
    const city = searchResult.name;
    const state = searchResult.state;
    router.push({
      name: 'cityView',
      params: { state: state, city: city },
      query: {
        lat: searchResult.lat,
        lng: searchResult.lon,
        preview: true
      }
    });
  }

</script>

这是我的 AsyncCityView.vue 组件,其中呈现数据:

<template>
  <div class="flex flex-col flex-1 items-center text-text">
    <!-- Banner -->
    <div v-if="route.query.preview && showBanner" class="flex items-center justify-end gap-[380px] text-text py-3 px-8 bg-blue-100 w-full text-center max-sm:gap-0">
      <p>You are currently previewing this City. Click the "+" icon to track this City.</p>
      <i class="fa-solid fa-circle-xmark cursor-pointer hover:opacity-80 duration-300 ease-out" @click="closeBanner"></i>
    </div>

    <!-- Overview -->
    <div class="flex flex-col items-center text-text py-12">
      <div class="flex relative">
        <h1 class="text-4xl mb-4">{{ route.params.city }}</h1>
        <i class="fa-solid fa-circle-plus text-xl absolute top-2 right-[-6rem] cursor-pointer text-accent hover:text-2xl duration-200 ease-in-out"></i>
      </div>
      <p class="text-9xl mb-6">
        {{ Math.round(weatherData.data.main.temp) }}&deg;
      </p>
      <p>
        Feels like: {{ Math.round(weatherData.data.main.feels_like) }}&deg;
      </p>
      <p class="capitalize">
        {{ weatherData.data.weather[0].description }}
      </p>
      <img class="w-48 h-auto bg-secondaryLight rounded-full mt-6" :src="`http://openweathermap.org/img/wn/${weatherData.data.weather[0].icon}@2x.png`" alt="Image of Current Weather">
    </div>

    <hr class="border-text border-opacity-10 border w-[48rem]">

    <div class="flex items-center gap-8 py-8">
      <!-- Wind Readings -->
      <div class="flex flex-col items-center">
        <img class="w-10 h-auto p-2 bg-accent rounded-md m-2" src="../assets/img/wind.svg" alt="">
        <p class="font-bold text-lg">Wind</p>
        <p class="opacity-90"> {{ weatherData.data.wind.speed +'km/h' }}</p>
      </div>
      
      <!-- Humidity Readings -->
      <div class="flex flex-col items-center">
        <img class="w-10 h-auto p-2 bg-accent rounded-md m-2" src="../assets/img/humidity.svg" alt="">
        <p class="font-bold text-lg">Humidity</p>
        <p class="opacity-90"> {{ weatherData.data.main.humidity +'%' }}</p>
      </div>

      <!-- Pressure Readings -->
      <div class="flex flex-col items-center">
        <img class="w-10 h-auto p-2 bg-accent rounded-md m-2" src="../assets/img/pessure.svg" alt="">
        <p class="font-bold text-lg">Pressure</p>
        <p class="opacity-90"> {{ weatherData.data.main.pressure +'hPa' }}</p>
      </div>
    </div>
  </div>
</template>
<script setup>
  import axios from 'axios';
  import { useRoute } from 'vue-router';
  import { ref } from 'vue';

  const showBanner = ref(true);
  const closeBanner = () => {
    showBanner.value = false;
  };

  const apiKey = 'e7a0834d5c68a78d2a20c4ade200a188';
  const route = useRoute();
  const getWeatherData = async () => {
    try {
      const weatherData = await axios.get(`https://api.openweathermap.org/data/2.5/weather?lat=${route.query.lat}&lon=${route.query.lng}&appid=${apiKey}&units=metric`);

      return weatherData;

    } catch(err) {
      console.log(err);
    }
  }

  const weatherData = await getWeatherData();
  console.log(weatherData);
</script>

由于我不精通Vue3,所以我向ChatGPT寻求帮助。没练过。

javascript async-await vuejs3 vue-router vue-suspense
1个回答
0
投票

首先:你应该阅读 Vue 3 的生命周期钩子。 下一步:隐藏您的令牌,它必须是秘密的。 您的搜索应该是搜索、保存、清除。对于每个请求都是如此。

例如看这个项目代码

© www.soinside.com 2019 - 2024. All rights reserved.