编写一个小的 demo, 对 router 基础的应用学习和理解.
效果图示:
说明: 点击 About 在右边显示相关信息.
说明: 点击 Home, 在下边显示相关信息, 且 Home 下有两个路由链接, 分别对应各自的路由组件.
说明: Message 下有三个路由链接, 对应的路由组件只有一个, 只是根据传入的参数不同显示不同数据.
项目目录:
代码:
1.index.html
- <!DOCTYPE HTML>
- <HTML>
- <head>
- <meta charset="utf-8">
- <meta name="viewport" content="width=device-width,initial-scale=1.0">
- <title>
- my-project
- </title>
- <link rel="stylesheet" href="./static/CSS/bootstrap.css">
- <style>
- .router-link-active { color: red !important; }
- </style>
- </head>
- <body>
- <div id="app">
- </div>
- <!-- built files will be auto injected -->
- </body>
- </HTML>
- 2.index.JS(router 模块)
- /**
- * 路由器对象模块
- */
- import vue from 'vue';
- import Router from 'vue-router'
- import Home from '../views/Home'
- import About from '../views/About'
- import News from '../views/News'
- import Message from '../views/Message'
- import MessageDetail from "../views/MessageDetail";
- // 声明使用 vue-router 插件
- /*
- 内部定义并注册了 2 个组件标签 (router-link/router-view),
- 给组件对象添加了 2 个属性:
- 1. $router: 路由器
- 2. $route: 当前路由
- */
- Vue.use(Router)
- export default new Router({
- // 注册应用中所有的路由
- routes: [
- {
- path: '/about',
- name: 'About',
- component: About
- },
- {
- path: '/home',
- name: 'Home',
- component: Home,
- children: [
- {
- path: '/home/news', // 绝对路径: path 左侧的'/'永远代表跟路由
- name: 'News',
- component: News
- },
- {
- path: 'message', // 相对路径
- name: 'Message',
- component: Message,
- children: [
- {
- path: 'detail/:id', // id 是变化的, :id 占位符来显示
- name: 'MessageDetail',
- component: MessageDetail
- }
- ]
- },
- {
- path: '',
- redirect: 'news'
- }
- ]
- },
- {
- path: '/',
- redirect: '/about'
- }
- ]
- })
3.main.JS
- /**
- * 入口 JS
- */
- import Vue from 'vue'
- import App from './App'
- import router2 from './router'
- new Vue({ // 配置对象的属性名都是一些确定的名称, 不能随便修改
- el: '#app',
- components: {App}, // 映射组件标签
- template: '<App/>', // 指定需要渲染到页面的模板
- router: router2 // 注册路由器
- })
4.App.vue
- <template>
- <div>
- <div class="row">
- <div class="col-xs-offset-2 col-xs-8">
- <div class="page-header"><h2>Router Test</h2></div>
- </div>
- </div>
- <div class="row">
- <div class="col-xs-2 col-xs-offset-2">
- <div class="list-group">
- <!-- 生成路由链接: 链接与路由配置中 path 一致 -->
- <router-link to="/about" class="list-group-item">About</router-link>
- <router-link to="/home" class="list-group-item">Home</router-link>
- </div>
- </div>
- <div class="col-xs-6">
- <div class="panel">
- <div class="panel-body">
- <!-- 缓存路由组件对象 -->
- <keep-alive>
- <!-- 显示当前组件, 并向路由组件传递数据 (属性携带数据), 与 props 用法类似 -->
- <router-view msg="abc"></router-view>
- </keep-alive>
- </div>
- </div>
- </div>
- </div>
- </div>
- </template>
- <script>
- export default {
- name: 'App',
- }
- </script>
- <style>
- </style>
5.About.vue
<template> <div> <h2>About</h2> <input type="text" /> <h4>{{msg}}</h4> </div> </template> <script> export default { name: "About", props: { // 声明接受数据 msg: String } } </script> <style scoped> </style>
6.Home.vue
<template> <div> <h2>Home</h2> <div> <ul class="nav nav-tabs"> <li><router-link to="/home/news">News</router-link></li> <li><router-link to="message">Message</router-link></li> </ul> <!-- 根据路由链接显示路由组件 --> <router-view></router-view> </div> </div> </template> <script> export default { name: "Header" } </script> <style scoped> </style>
7.News.vue
<template> <div> <ul> <li v-for="(news, index) in newsArr" :key="index">{{news}}</li> </ul> </div> </template> <script> export default { name: "News", data () { return { newsArr: ['news01','news02','news03','news04'] } } } </script> <style scoped> </style>
8.Message.vue
<template> <!-- 一个组件只能有一个根标签 --> <div> <ul> <li v-for="message in messages" :key="message.id"> <!-- 这里 to 绑定表达式, 链接是动态的; 不能用相对路径, 不然连续点链接时会出错 --> <router-link :to="`/home/message/detail/${message.id}`">{{message.title}}</router-link> <button @click="pushShow(message.id)">push 查看 </button> <button @click="replaceShow(message.id)">replace 查看 </button> </li> </ul> <hr> <button @click="$router.back()"> 回退 </button> <router-view></router-view> </div> </template> <script> export default { name: "Message", data() { return { messages: [] } }, mounted() { // 模拟 Ajax 异步从后台请求数据 setTimeout(() => { const messages = [ { id: 1, title: 'message01' }, { id: 2, title: 'message02' }, { id: 3, title: 'message03' }, ] this.messages = messages }, 1000) }, methods: { pushShow(id) { this.$router.push(`/home/message/detail/${id}`) }, replaceShow(id) { this.$router.replace(`/home/message/detail/${id}`) } } } </script> <style scoped> </style>
9.MessageDetail.vue
<template> <div> <ul> <li>id: {{$route.params.id}}</li> <li>title: {{detail.title}}</li> <li>content: {{detail.content}}</li> </ul> </div> </template> <script> export default { name: "MessageDetail", data() { return { detail: {}, } }, mounted() { // 改变当前路由组件参数数据时, 不会重新创建组件对象, mounted 不会重新执行 // setTimeout 含义是定时器, 到达一定的时间触发一次, 在代码的执行时间上加 1s // 但是 setInterval 含义是计时器, 到达一定时间触发一次, 并且会持续触发 setTimeout(() => { const messageDetails = [ { id: 1, title: 'message01', content: 'message01 content...' }, { id: 2, title: 'message02', content: 'message02 content...' }, { id: 3, title: 'message03', content: 'message03 content...' }, ] this.messageDetails = messageDetails // 初始化数据, 声明全局 messageDetails const id = this.$route.params.id * 1 // id 有可能为文本, 故乘以 1 this.detail = messageDetails.find(detail => detail.id === id) }, 1000) }, watch: { $route: function(value) { // 改变当前路由组件参数数据时自动调用 const id = value.params.id * 1 this.detail = this.messageDetails.find(detail => detail.id === id) } } } </script> <style scoped> </style>
总结
1. 路由组件跳转
路由跳转与页面跳转相似, 页面跳转是从一个页面跳到另一个页面, 但路由跳转是从一个路由组件跳到另一个路由组件, 类似 tab 页切换和导航栏效果.
页面跳转方式:
a 链接 -- HTML
Windows.location.href -- JS
路由组件跳转方式:
router-link -- HTML, 等同于 $router.push, replace 默认为 false
router-link replace -- 当添加 replace=true 时等同于 $router.replace
$router.push -- 在 history 栈中添加新记录
$router.replace -- 替换掉当前的 history 记录
$router.back() -- 回退
都是在 router-view 标签定义的地方显示 url 指向的路由组件
router.push(location)
这个方法会向 history 栈添加一个新的记录, 当用户点击浏览器后退按钮时, 则回到之前的 URL.
router.replace(location)
这个方法不会向 history 添加新记录, 而是跟它的方法名一样 -- 替换掉当前的 history 记录, 点击返回按钮也不会回到之前的 URL 页面.
2. 路由组件跳转时传递数据
声明式:
router-link :to="..." path 上传递参数
params: /home/message/detail/${ message.id } query: '/home/message/detail?id='+message.id
router-view :abc="data" 属性携带参数
类似与同 props 进行组件通信, 跳转的下一路由组件需声明接受属性 props
编程式:
router.push(...)
该方法的参数可以是一个字符串路径, 或者一个描述地址的对象.
// 字符串 router.push('/home') // 添加新记录 //push 方法也可以传 replace this.$router.push({ path: '/home', replace: true }) // 替换当前记录 // 对象 this.$router.push({ path: '/login?url=' + this.$route.path }); // 带查询参数, 变成 / backend/order?selected=2 this.$router.push({ path: '/backend/order', query: { selected: "2" } }); // 命名的路由 router.push({ name: 'user', params: { userId: 123 } })
params 与 query 传参区别
query 传参配置的是 path, 而 params 传参配置的是 name, 在 params 中配置 path 无效
query 在路由配置不需要设置参数, 而 params 必须设置
query 传递的参数会显示在地址栏中
params 传参刷新会无效, 但是 query 会保存传递过来的值, 刷新不变
路由配置:
query: { path: '/home', name: Home, component: Home } params: { path: '/home/:site/:bu', name: Home, component: Home }
获取路由参数
created () { let self = this self.getParams() }, watch () { '$route': 'getParams' }, methods: { getParams () { let site = this.$route.query.site let bu = this.$route.query.bu // 如果是 params 传参, 那就是 this.$route.params.site
上面就可以获取到传递的参数了
}
}
说明: 路由传递参数和传统传递参数是一样的, 命名路由类似表单提交而查询就是 url 传递.
命名路由搭配 params, 刷新页面参数会丢失
传递参数搭配 query, 刷新页面数据不会丢失
接受参数使用 this.$router 后面就是搭配路由的名称就能获取到参数的值
来源: http://www.bubuko.com/infodetail-3297058.html