问题
I've build a vue.js web app for an insurance brokerage where every agent has their own website that is generated from their profiles.
This is what the link looks like in my vue-router index file"
{
path: '/agents/:id',
name: 'AgentSite',
component: AgentSite
},
Everything works great EXCEPT that the urls are getting too long to fit on some business cards. I would like to change the URLs to be like this:
{
path: '/:id',
name: 'AgentSite',
component: AgentSite
},
However, then every other bit of dynamic content in the app loads our agent website template (AgentSite). Quotes, Clients, Policies... they won't load properly.
Is there a way to remove the "/agents" from the URLs without messing up the rest of our application? I could shorten it to "/a/:id but that ends up being more confusing than it's worth.
Thanks!
EDIT: a couple of people have mentioned solutions that work when the agent id is a number. That's a great idea except that we have built agent "slugs" to use instead.
On the agent website layout:
created() {
console.log(this.$route.params.id);
this.$store.dispatch("getAgentFromSlug", this.$route.params.id);
}
and in the store:
getAgentFromSlug({commit}, payload){
const db = firebase.database();
db.ref("users/").orderByChild("slug").equalTo(payload).once("value",
(snap) => {
console.log(snap.val());
var info = snap.val();
commit("setAgentSiteInfo", info[Object.keys(info)[0]])
})
}
So, our route Id is really a slug.
回答1:
Considering id
s are numbers, you could use:
{
path: '/:id(\\d+)',
name: 'AgentSite',
component: AgentSite
},
Which only matches if id
is made only of numbers.
Update: A couple of people have mentioned solutions that work when the agent id is a number. That's a great idea except that we have built agent "slugs" to use instead.
If the names can conflict with existing routes, declare the agent route last.
From the Matching Priority docs (emphasis mine):
Matching Priority
Sometimes the same URL may be matched by multiple routes. In such a case the matching priority is determined by the order of route definition: the earlier a route is defined, the higher priority it gets.
In other words, declare like:
routes: [
{
path: '/',
component: HomePage
},
{
path: '/quotes',
component: Quotes
},
{
path: '/clients',
component: Clients
},
{
path: '/:id',
component: AgentSite,
props: true
}
]
See CodeSandbox demo Here.
Handling 404 pages
Would I then declare the 404 page route above or below the "
AgentSite
" in your example?{ path: "*", component: PageNotFound }
The AgentSite
route would match any URL not matched previously, so you'll have to handle the 404s inside the AgentSite
component.
First, declare the 404 route after the AgentSite
:
routes: [
// ... (other routes)
{
path: "/:id",
component: AgentSite,
props: true
},
{
path: ":path",
name: "404",
component: p404,
props: true
}
]
Then, inside AgentSite
, get the agent :id
, check if it is a known agent and, if not, redirect to the 404
route by name (otherwise it would match agent again).
export default {
props: ["id"],
data() {
return {
availableAgents: ["scully", "bond", "nikita"]
};
},
created() {
let isExistingAgent = this.availableAgents.includes(this.id);
if (!isExistingAgent) {
this.$router.push({
name: "404",
params: { path: this.$route.fullPath.substring(1) }
});
}
}
};
The CodeSandbox demo Here already contains this handling.
回答2:
You can use regex matching if you :id
has a specific format (example from vue-router repository).
For example, if your :id
is a number:
const routes = [
{ path: '/:id(\\d+)', component: Foo },
{ path: '/bar', component: Bar }
]
const Foo = { template: '<div>foo</div>' }
const Bar = { template: '<div>bar</div>' }
const routes = [
{ path: '/:id(\\d+)', component: Foo },
{ path: '/bar', component: Bar }
]
const router = new VueRouter({
routes
})
const app = new Vue({
router
}).$mount('#app')
.router-link-active {
color: red;
}
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<div id="app">
<h1>Hello App!</h1>
<p>
<router-link to="/321321">Go to Foo</router-link>
<router-link to="/bar">Go to Bar</router-link>
</p>
<router-view></router-view>
</div>
来源:https://stackoverflow.com/questions/49416258/is-there-a-way-to-remove-a-directory-from-a-dynamic-url-using-vue-router