使用路由器的Vue模态

时间:2020-08-13 14:20:43

标签: javascript jquery vue.js axios

我是Vue的新手。我正在构建一个简单的应用程序,它将列出所有国家/地区,当您单击特定国家/地区时,它会为您显示有关该国家/地区的更多详细信息。想法是以模式打开country details

我坚持显示该模式。模态打开,但在后台。它还会打开一个详细信息页面。

CountryDetail.vue

<script>
import axios from 'axios';
export default {
  name: 'country-detail',
  props: [ 'isDarkTheme' ],
  data () {
    return {
      pending: false,
      error: null,
      countryInfo: null,
      alpha3Code: [],
      alpha3CodetoString: [],
    }
  },
  mounted () {
    this.pending = true;
    axios
      .get(`https://restcountries.eu/rest/v2/name/${this.$route.params.country}?fullText=true`)
      .then((response) => {
        (this.countryInfo = response.data)
        this.alpha3CodetoString = this.alpha3Code.join(';');
      })
      .catch(error => (this.error = error ))
      .finally( () => { this.pending = false });
  },
  filters: {
    formatNumbers (value) {
      return `${value.toLocaleString()}`
    }
  }
}
</script>

<template>
<modal v-model="show">
        <div class="modal-mask" :class="{ darkTheme : isDarkTheme }" name="modal">
          <div class="modal-wrapper">
            <div  class="modal-container">
              <div class="modal-header">
                <slot name="header">
                   <h1 v-if="error !== null">Sorry, an error has occurred {{error}}</h1>
                  <div class="loaderFlex"><div v-if="pending" class="loader"></div></div>
                </slot>
              </div>

              <div v-for="country in countryInfo" class="countryTile modal-body" v-bind:key="country.id">
                <slot name="body">
                    <img v-bind:src="country.flag" alt="Country Flag" class="flag">
                  <div class="country-details">
                        <h1>{{country.name}}</h1>
                        <div class="listDiv">
                        <ul>      
                            <li><span>Population:</span> {{country.population | formatNumbers }}</li>
                            <li><span>Capital:</span> {{country.capital}}</li>
                            <li><span>Iso:</span> {{country.alpha3Code}}</li>
                        </ul>
                        <ul>   
                            <li><span>Currencies:</span> {{country.currencies['0'].name}}</li>
                            <li><span>Languages:</span> 
                            <span 
                                v-for="(language, index) in country.languages" 
                                v-bind:key="index" 
                                class="languages">
                                {{language.name}}<span v-if="index + 1 < country.languages.length">, </span>
                            </span>
                            </li>
                        </ul>
                        </div>    
                    </div>
                </slot>
              </div>

              <div class="modal-footer">
                <slot name="footer">
                <a @click="$router.go(-1)" class="backBtn"><i class="fas fa-arrow-left" />Go Back</a>
                </slot>
              </div>
            </div>
          </div>
        </div>
      </modal>
</template>

Home.vue

<script>
import axios from 'axios';
export default {
  name: 'home',
  props: [ 'isDarkTheme' ],
  data () {
    return {
      pending: false,
      error: null,
      countryInfo: null,
      search: '',   
      darkMode: false,
    }
  },
  mounted () {
    this.pending = true;
    axios
      .get('https://restcountries.eu/rest/v2/all')
      .then(response => (this.countryInfo = response.data))
      .catch(error => (this.error = error ))
      .finally( () => { this.pending = false });
  },
 
  filters: {
    formatNumbers (value) {
      return `${value.toLocaleString()}`
    }
  },
  computed: {
    filteredCountries: function () {
      return this.countryInfo.filter((country) => {
        if (this.region === '' ) {
          return country.name.toLowerCase().match(this.search.toLowerCase());
        } else if (this.search !== '') {
          return country.name.toLowerCase().match(this.search.toLowerCase());
        } else {
          return ('blbla');
        }
      })
    }
  }, 
}
</script>
<template>
  <div class="home" :class="{ darkTheme : isDarkTheme }">
    <div class="searchBar">
      <div class="searchContainer">
        <i class="fas fa-search searchIcon"></i>
        <input 
          class="searchInput" 
          type="text" 
          v-model="search"
          aria-label="Search for a country..."
          placeholder="Search for a country..."
        />
        <ul class="searchResults"></ul>
      </div>

    </div>
    <h1 v-if="error !== null">Sorry, an error has occurred {{error}}</h1> 
    <div class="loaderFlex"><div v-if="pending" class="loader"></div></div>

    <div v-if="countryInfo" class="tileGrid" @click="showModal = true">
      <div v-for="country in filteredCountries" class="countryTile" v-bind:key="country.id">
        <router-link 
          :to="{ name: 'country-detail', params: {country: country.name }}" 
          class="linkTile"
        >
          <img v-bind:src="country.flag" alt="Country Flag" class="flag">
          <div class="text">
            <h1>{{ country.name }}</h1>
          </div>
        </router-link>
      </div>
    </div>
  </div>
  
</template>

1 个答案:

答案 0 :(得分:0)

路由器链接将始终将您重定向到另一个页面,因为它的页面基本上是<a href="..."> see here。如果您只想显示模态上的详细信息,则不需要路由器,只需将模态组件添加到 Home.vue 组件内,然后将模态和countryName绑定即可带有道具,然后在单击按钮时将其传递。

Home.vue

<template>
 <div>
  <button @click="showDetail">
   Show Detail
  </button>

  <CountryDetail :countryName="countryName" :showModal="showModal"/>
 <div>
</template>

<script>
 import CountryDetail from './CountryDetail.vue'

 export default {
  name: 'Home',
  components: { CountryDetail },
  data: () => ({
   countryName: '',
   showModal: false,
  }),
  methods: {
   showDetail() {
    this.showModal = true;
   },
  },
 }
</script>

您可以使用mounted来进行类似watch道具的观察,而不是在showModal上发出请求,并在每次请求具有真实价值时发出请求。像这样:

CountryDetail.vue

<template>
 <modal v-model="showModal">
  <!-- modal content -->
 </modal>
</template>

<script>
 export default {
   name: 'CountryDetail',
   props: ['countryName', 'showModal'],
   watch: {
     'showModal': {
       deep: true,
       handler(val) {
         if (val && this.countryName !== '') {
           // Make request
         }
       }
     }
   }
 }
</script>