Day19-Vue Router 路由设定(part2)

巢状路由

在原先的router-view中再放一个router-view

接续前一个案例,User.vue中放一个router-view给等一下要新增的Poster.vue

<template>
  <h1>User: {{ userId }} - {{ userInfo?.name }}</h1>
  <div>username: @{{ userInfo.username }}</div>
  <div>email: {{ userInfo.email }}</div>
  <div>phone: {{ userInfo.phone }}</div>
  <hr />

  Show
  <router-link :to="`/users/${userId}/posts`">
    /users/{{ userId }}/posts
  </router-link>

  <hr />

  <router-view></router-view>
</template>

接着,新增view/Post.vue

<template>
  <h1>Post from User-{{ userId }}</h1>
  <ol>
    <li v-for="post in posts" :key="post.id">
      <h3>{{ post.title }}</h3>
      <p>{{ post.body }}</p>
    </li>
  </ol>
</template>

<script>
export default {
  data() {
    return {
      posts: [],
    };
  },
  computed: {
    userId() {
      return this.$route.params.userId;
    },
  },
  methods: {
    async fetchUserPosts() {
      return await fetch(
        "https://jsonplaceholder.typicode.com/posts?userId=" + this.userId
      ).then((response) => response.json());
    },
  },
  async created() {
    this.posts = await this.fetchUserPosts(this.userId);
  },
};
</script>

最後,修改router.js,引入Post.vue,并在routes之下建立一个children

import { createRouter, createWebHistory } from "vue-router";
import User from "./views/User.vue";
import Post from "./views/Post.vue";

export const router = createRouter({
    history: createWebHistory(),
    routes: [
        {
            path: "/users/:userId",
            component: User,
            children: [
                {
                    path: "posts",
                    component: Post
                }
            ]
        }
    ]
});

画面中可以看到原先的http://localhost:8080/users/5在点击Show /users/5/posts後会变成http://localhost:8080/users/5/posts,这就是巢状的效果。

Untitled

具名路由

除了用path指定路径,还可以用name更直觉式的设定路径。

routes: [ 
	{ path: '/', name: 'home', component: Home }, 
	{ path: '/foo', name: 'foo', component: Foo }, 
	{ path: '/bar/:id', name: 'bar', component: Bar } 
]

router-link就可以使用name设定to

<ul> 
	<li><router-link :to="{ name: 'home' }">home</router-link></li> 
	<li><router-link :to="{ name: 'foo' }">foo</router-link></li> 
	<li><router-link :to="{ name: 'bar', params: { id: 123 }}">bar</router-link></li> 
</ul>
//result: /,/foo,/bar123

巢状具名视图

如书中的解释图,子层元件中可能也会有很多个router-view,具名方式和刚刚的差不多。

Untitled

给予一个name属性,并在routes中新增一个components属性在children里面。

<!-- Page.vue --> 
<div> <router-view class="view nav-block" name="Nav">
</router-view> <router-view class="view header-block" name="Header">
</router-view> <router-view class="view body-block"></router-view> </div>
import Page from './page.vue'; 
import Body from './body.vue'; 
import Header from './header.vue'; 
import Nav from './nav.vue'; 

const routes = [ 
	{ path: '/pages', 
		component: Page, 
		children: [
			 components: {
				  default: Body, 
					Header: Header, 
					Nav: Nav, 
				}, 
			] 
		} 
];

路由转址

使用redirect选项指定某个路由要转址到某个目标。

const routes = [ 
	//方法一: 直接使用 /home --> /
	{ path: '/home', redirect: '/' },

	//方法二: 使用name /app --> appPage
	{ path: '/app', redirect: { name: 'appPage' } },

	//方法三: 使用function /search/screens --> /search?q=screens
	{ path: '/search/:searchText', redirect: to => { 
			return { path: '/search', query: { q: to.params.searchText } } 
		}, 
	},
]

路由别名

redirect功能很像的alias,在点击path/的情况下依旧保持/home的样子,不会强制转到/

const routes = [ 
	//单一别名
	{ path: '/', 
		component: Homepage, 
		alias: '/home' },

	//多个别名
	{ path: '/users', 
		component: UsersLayout, 
		children: [ 
			// result : - /users // - /users/list // - /people 
			{ path: '', 
				component: UserList, 
				alias: ['/people', 'list'] 
			}, 
		], 

		//也可以加上参数(path与alias需保持一致)
		{ path: '/users/:id', 
			component: UsersByIdLayout, 
			children: [ 
				// result : - /users/24 // - /users/24/profile // - /24 
				{ path: 'profile', 
					component: UserDetails, 
					alias: ['/:id', ''] 
				}, 
			], 
		},
]

路由与props

如官方文件所说,routes和元件的紧密性使的元件不能弹性的重复使用,元件若没有Vue Router的情况下$route.params.id就没有办法使用。

//component
const User = {
  template: '<div>User {{ $route.params.id }}</div>'
}

//routes
const router = new VueRouter({
  routes: [{ path: '/user/:id', component: User }]
})

所以衍生出props用法,这样:id的属性就可以传入元件使用,达到重复利用的功能。

//component
const User = {
	props:['id'],
  template: '<div>User {{ id }}</div>'
}

//routes
const router = new VueRouter({
  routes: [{ path: '/user/:id', component: User, props:true }]
})

若是具名路由,则需要一个个指定props

const router = new VueRouter({
  routes: [
		//1. boolean样式
    { path: '/user/:id', component: User, props: true },

		//2. 物件样式
		{ path: '/promotion/from-newsletter', 
			component: Promotion, 
			props: { newsletterPopup: false }
		 }

		//3. funciton样式
    {
      path: '/user/:id',
      components: {
        default: User,
        sidebar: Sidebar
      },
      props: {
        default: true,
        sidebar: route => ({ search: route.query.q })
      }
    }
  ]
})

参考资料

HTML5 History 模式
https://router.vuejs.org/zh/guide/essentials/history-mode.html#后端配置例子
Vue Router – History mode, Catch all/404, Matching Syntax
https://jungtin.me/vue-router-history-mode-catch-all-404-matching-syntax/#ib-toc-anchor-1
[Vue.js] 笔记 - Vue-Route
https://dotblogs.com.tw/Null/2020/05/12/221249
[Vue] 跟着 Vue 闯荡前端世界 - 08 网站路由 vue-router
https://dotblogs.com.tw/wasichris/2017/03/06/235449
Vue Router
https://linwei5316.medium.com/vue-router-4c2aad1cc352


<<:  Day19 React Context API

>>:  Day27-"练习-2"

Day 02 : Python 基础观念 (1)

变数 变数基本上是用来暂时储存资料的地方,可以想像在我们执行程序的时候,需要用一个代号去代表我们需要...

Day24 订单金流 -- 叮咛

到昨天为止订单、订单金流已经谈的差不多了, 大部分的正常环节以及常用功能的应用, 订单写入的部份已经...

[Day13]程序菜鸟自学C++资料结构演算法 – 二元树的储存与实作

前言:上一篇介绍过了树状结构和二元树,今天要来介绍二元树存取资料的方法,其中有两种方法最常使用,这次...

从零开始学3D游戏开发 Roblox Studio 简介 Part.2

今天离开了起点,看到好多人都在赛道周边努力着 大家一起努力往终点进发吧! 这个单元我们继续学习 Ro...

D9 文件系统核心开始 系统页面功能规划

今天先来规划一下後续的系统架构 先用文字版 等做完了再补上图片 首先使用者进入会先到首页 首页 使用...