VueRouter

209 阅读2分钟

修改url却不刷新网页的方法

  1. location.hash = 'newUrl'
  2. html5模式,history.pushState({},'','newUrl') 入栈操作 history.back() 出栈操作
  3. html5模式,history.replaceState({},'','newUrl')

安装

npm install vue-router --save

使用

  1. 导入路由对象,并且调用Vue.use(VueRouter)

  2. 创建路由实例,并且传入路由映射配置

  3. Vue实例中挂载创建的路由实例

    src文件夹下创建router文件夹,再创建index.js文件,若用脚手架选择则会自动生成

    import VueRouter from 'vue-router'
    import Vue from 'vue'
    
    //1.通过Vue.use(插件) 安装插件
    Vue.use(VueRouter)
    
    //2.创建VueRouter实例
    const router = new VueRouter({
    	//配置映射关系
    	routes:[
    		
    	]
    })
    
    //3.将router对象传入Vue实例
    export default router
    
    

    main.js

    import Vue from 'vue'
    import App from './App'
    import router from './router'
    //默认会找文件夹下的index.js
    Vue.config.productionTip = false
    
    /* eslint-disable no-new */
    new Vue({
      el: '#app',
      //挂载路由实例
    	router,
      render:h => h(App)
    })
    
    

路由跳转的方法

  1. router-link

     <router-link to="keyframes">点击验证动画效果 </router-link>
    
  2. this.$router.push({ path:'/user'})

  3. this.$router.replace{path:'/' }

重要提示:一定不要用location.href或者history对象的方法跳转,否则无法实现SPA的效果,数据会被直接刷新重置!!!!

举例-静态路由和动态路由

components文件夹下新建home.vueabout.vue

<template>
    <div>
        <h2>我是用户:{{userId}}</h2>
        <p>请多多指教!</p>
    </div>
</template>

<script>
    export default {
        name:'user',
        computed:{
            userId(){
                return this.$route.params.id
                //$route 表示目前正在活跃的路由
            }
        }
    }
</script>

<style>
</style>

App.vue也就是组件树的根中

<template>
  <div id="app">
	<router-link to='/home'>首页</router-link>
	<router-link to='about'>关于</router-link>
	<!-- router-link 是已经被注册好的全局组件 必须有 to 属性 指定url 渲染为a标签 -->
	<!-- 其他属性 
		tag = 'button':指定渲染成什么元素 
                replace:不用写值,点击有该属性的标签切换url时,前进后退不可选
		active-class = 'active':替换下面的 router-link-active 为 active,统一替换所有的话,需要在index.js中new实例中指定 linkActiveClass:'active'
	-->
	<!-- class属性 
		router-link-active: 正在活跃,'首页'被点击后,'首页'的class中会有该类名
		可以通过css选择器,修改样式
        -->
	<router-link :to='"/user/" + userId'>用户</router-link>
	<!-- 动态路由,使用 v-bind 动态绑定 -->
	<router-view></router-view>
	<!-- router-view 同上 指定显示的组件位置 -->
  </div>
</template>
<!-- 假设不通过router-link标签跳转页面 使用自己指定的原生标签 并且指定方法跳转
    在每个对象中会有 this.$router 对象,这个对象就是index.js中的router实例
	this.$router.push('url')等价于 to
	this.$router.replace('url')等价于 replace
-->
<script>

export default {
    name: 'App',
    data(){
        return {
            userId:'zhansan'
        }
    }
}
</script>

<style>

</style>

router文件夹下的index.js

import VueRouter from 'vue-router'
import Vue from 'vue'
import home from '../components/home.vue'
import about from '../components/about.vue'
// 导入组件
//1.通过Vue.use(插件) 安装插件
Vue.use(VueRouter)

//2.创建VueRouter实例
const router = new VueRouter({
//配置映射关系
    routes:[//每个映射关系为一个对象
        {
             path:'/',
             redirect:'/home',
             // 为了默认显示首页 当路径为根路径则自动重定向到/home
         },
         {
             path:'/home',//url
             component:home//组件
         },
         {
             path:'/about',
             component:about
         },
         {
             path:'/user/:id',
             // :id 为动态绑定的属性
             component:user ,
             // 可以在user组件所在vue文件中 使用this.$route.params.id获取
         }
   ],
    mode:'history'
    //不写默认为哈希模式 localhost:XXXX/#/home
    //指定history模式   localhost:XXXX/home
})

//3.将router对象传入Vue实例
export default router

打包文件的解析

​ 通常打包后,会形成一个js文件,我们通常设置为bundles.js,因为所有js代码都在一个文件中,所有当用户请求网页时,这个js文件过大,导致网页会有短暂空白。

VueCLI会把项目打包成如下目录结构:

  • dist
    • static
      • css
        • css.XXXX.css 抽离整合的css文件
        • css.XXXX.css.map 压缩后的代码出错不好找位置,map文件帮助寻找bug位置
      • js
        • app.XXXX.js 当前应用程序开发的所有代码(业务代码)
        • manifest.XXXX.js 为了打包的代码做底层支持,如commonjs规范导入导出
        • vendor.XXXX.js 存放所有第三方的包代码
        • ....js.map
    • index.html

但是即便如此,js文件可能还是会很大,所以就有了路由的懒加载

路由的懒加载

  • 路由懒载的主要作用就是将路由对应的组件打包成一个个的js代码块
  • 只有在这个路由被访问到的时候才加载对应的组件

懒加载的方式

  • 方式一:结合Vue的异步组件和Webpack的代码分析

    const Home = resolve => { require.ensure(['../componets/Homne.vue'], () => { resolve(require('../componets/Homne.vue')) })}
    //这种代码是早期代码,非常不推荐写,在老项目中可能会出现,要求能看出这是懒加载
    
  • 方式二:AMD写法

    const About = resolve => require(['../componets/About.vue'],resolve)
    
  • 方式三:ES6写法

    const Home = () => import('../components/Home.vue')
    //推荐使用
    

将例子中的index.js进行改造(仅显示修改或添加的代码)

const home = () => import('../components/home.vue')
const about = () => import('../components/about.vue')
const user = () => import('../components/user.vue')

路由嵌套

​ 目标:点击首页下的新闻会跳转到home/news,点击消息会跳转到home/message,并且在home时默认跳转到home/news

修改home.vue(仅显示修改或添加的代码)

<template>
    <div>
        <h2>我是首页</h2>
        <p>请多多指教!</p>
        <router-link to='/home/news'>新闻</router-link>
        <router-link to='/home/message'>消息</router-link>
        <!-- 别忘了开头的'/'一定要加 -->
        <router-view></router-view>
        <!-- router-view 依旧显示内容 -->
    </div>
</template>

将例子中的index.js进行改造(仅显示修改或添加的代码)

const homeNews = () => import('../components/homeNews.vue')
const homeMess = () => import('../components/homeMess.vue')

const router = new VueRouter({
    //配置映射关系
    routes:[
            {
                path:'/',
                redirect:'/home',
                // 为了默认显示首页 当路径为根路径则自动重定向到/home
            },
            {
                path:'/home',
                component:home,
                children:[//使用 children 属性实现路由嵌套
                        {
                            path:'/',
                            redirect:'news'
                        },
                        {
                            path:'news',//children 中的子路由 路径开头不要有'/'
                            component:homeNews
                        },
                        {
                            path:'message',
                            component:homeMess
                        }
                ]
            },
            {
                path:'/about',
                component:about
            },
            {
                path:'/user/:id',
                // :id 为动态绑定的属性
                component:user ,
                // 可以在user组件所在vue文件中 使用this.$route.params.id获取
            }
    ],
    mode:'history'
})

传递参数

  • 传递参数主要有两种类型:paramsquery
  • params的类型
    • 配置路由格式:/router/:id
    • 传递的方式:在path后面跟上对应的值
    • 传递后形成的路径:/router/123/router/abc
  • query的类型
    • 配置路由格式:/router,也就是普通配置
    • 传递的方式:对象中使用querykey作为传递方式
    • 传递后形成的路径:/router?id=123/router?id=abc
query的两种用法
<router-link :to='{ path:"home", query:{name:"wang",age:18 } }'>消息</router-link>
<!-- 用query时,使用v-bind传递给to属性一个对象 -->
<!-- 对象中的path就是路由,query对象存放需要传递的数据 -->
<!-- 这时url会变成:http://localhost:8080/home?name=wang&age=18 -->
<!-- 在home.vue中 使用 this.$route.query.XX 使用 -->
<router-link @click='messClick'>消息</router-link>
<script>
   messClick(){
      this.$router.push({path:"home", query:{name:"wang",age:18 }})
   }
</script>

全局导航守卫

//index.js
//前置守卫(guard)
router.beforeEach(function(to,from,next){
  //从 from 跳转到 to 
  //两者皆为 route 对象
  document.title = to.matched[0].meta.title//自己手动在路由对象中定义meta属性 表示元数据
  //把跳转页面的title修改掉
  next()//必须调用
})
//后置钩子(hook)
router.afterEach((to, from) => {
  //无需调用next()
})  

keep-alive保持状态

<keep-alive exclude="user,home">
	<router-view></router-view>
</keep-alive>
<!-- 被keep-alive 包裹的元素在切换路由时,会缓存下来,不会销毁,下次切换回来不会再重新生成 -->
<!-- 只有被这个包裹,才能使用 activated 和 deactivated 方法 -->
<!-- 它拥有两个属性 exclude 和 include -->
<!-- exclude:字符串或正则表达式,填写组件返回的name属性值,这些组件将不会被缓存下来,多个用逗号隔开,逗号两边切记不要空格 -->
<!-- include:同上,只有匹配的组件将会被缓存 -->