iT邦幫忙

2021 iThome 鐵人賽

DAY 19
0
Modern Web

我的Vue學習筆記系列 第 19

Day19-Vue Router 路由設定(part2)

  • 分享至 

  • xImage
  •  

巢狀路由

在原先的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


上一篇
Day18-Vue Router 路由設定(part1)
下一篇
Day20-<router-link> 建立路由連結
系列文
我的Vue學習筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言