简体   繁体   中英

Vue Router Setup work when visited directly via URL

I'm looking for advice on how to go about this routing scenario:

I have the following HTML that loops category and items in the category. The <router-view> is inside the category so that when an item is clicked it will open only in the category that related to that item.

<ul>
    <li v-for="cat in categories">
        <ul>
            <li v-for="business in filteredByCat">{{business.name}}</li>
        </ul>
        <router-view v-if="..."></router-view>
    </li>
</ul>

My routes are as follows:

{
      path: '/businesses',
      name: 'Directory',
      component: Directory,
      children: [{
        path: ':listing',
        name: 'Listing',
        component: Listing
      }]
    }

Visualization:

布局可视化

How do I get the data of the item clicked to pass to the router-view ? I assume I'd use props but that wouldn't work if the user visited details directly by URL?

I tried getting the item like so:

methods: {
    finalItem ($route) {
      var match = this.businesses.filter((business) => {
        return business.link === $route.params.listing
      })
      return match[0]
    }
  }

This doesn't work, even if it did, this feels wrong. Is there a way to pass the data in a way that would preserve even when visited directly? This is my primary concern. (I understand the repeated <router-view> is bad code but am not sure how to get around doing that with my layout. Open to suggestions on that too though.)

The way you're using router-view , you might as well just drop a component in. As far as using multiple router-view s goes, it's very common, so idk what @varbrad is talking about there. Child routes are fine.

The not-so-common part is using multiple router-view 's in one component. The UI you're aiming for is nearly identical to Netflix. If you check out what they're doing, you'll see that they pass a movie ID (business id/shortname) as "jbv" and a row number (category name) as "jbr" in the route query.

Let's mimic this in your component:

I'm not sure what filteredByCat looks like, but the way you have it set up, it would list the same businesses for every category. Try something like this:

computed:{
  businessesByCategory(){
     let dictionary = {};
     this.businesses.forEach(business=>{
       business.categories.forEach(category=>{ // assuming each business has an array of categories
         dictionary[category] = dictionary[category] || [];
         dictionary[category].push(business)
       })
     })

     return dictionary;
  }
},
data(){
  return {
    activeBusiness:null
  }
},
methods:{
  setActiveBusiness(business){
    this.activeBusiness = business;
  },
  setUrlQuery(listing, category){
    this.$route.query.listing = listing;
    this.$route.query.category = category;
  },
  openListing(business, category){
    this.setActiveBusiness(business);
    this.setUrlQuery(business.link, category);
  }
}

-

<ul>
    <li v-for="cat in categories">
        <ul>
            <li 
              v-for="business in businessesByCategory[cat]"
              @click="openListing(business, cat)"
             >                     
                 {{business.name}}
            </li>
        </ul>
        <Listing :business="activeBusiness" v-if="$route.query.category == cat"></Listing>
    </li>
</ul>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM