必背-11.vue-router

必背-11.vue-router

什么是vue-router

  • vue-router:Vue的路由
  • 网址:

多页面/单页面

前端路由有哪些?

  • 前端路由(vue-router/react-router-dom)
  • 实现SPA(single page application):单页面应用
    • 一个项目只有一个页面,我们基于路由,控制页面展示不同的代码片段(或组件),当展示内容改变的时候,页面并不会刷新
  • MPA(multi page application):多页面应用
    • 一个项目有很多页面,我们做的是页面之间的跳转【每一次跳转都是打开新的页面(相当于页面刷新了)】

单页面应用和多页面应用的项目?

  • 单页面应用的项目
    • 移动端大部分都是(追求原生App的操作体验)
    • PC端管理系统。。。
  • 多页面应用的项目
    • PC端非管理系统的产品

基于JS动态绑定的内容(vue框架都是这样处理)在页面的源代码中是看不到内容的,不利于SEO搜索引擎优化!想做SEO优化,需要服务器渲染(前后端不分离、现在主流的服务器渲染SSR:nide+vue(nuxt.js)+react(next.js))

  • 现在流行的模式:首屏服务器渲染[骨架屏]其余屏幕还是交给客户端渲染

前端路由模式

  • 哈希路由(hash router):监听URL地址后面的哈希值

    • 样式:http://www.xxx/com/index.html#home
    • 原理:改变url的哈希值不会刷新页面,通过指定的哈希值使用window.onhashchange事件来控制更改页面渲染的内容
  • 浏览器路由(browser/history router):基于H5中的historyAPI实现的

    • 样式http://www.xxx.com/home
    • 缺点:需要服务器的支持:(当手动刷新的时候,这个页面不存在,不要返回404,依然返回主页面内容)
    • 原理:通过history.pushState()方法改变网址,页面不会刷新,再通过window.onpopstate事件监听网址的改变
  • 哈希路由和浏览器路由的区别:

    • hash路由地址不好看,browser路由不好看
    • 实现机制不同:hash路由每次跳转,修改的是URL的hash值(页面不刷新);金婷hashchange事件,获取最新的hash值,去路由规则表中,找到对应的组件拿过来渲染!!
    • browser路由每次跳转,修改的是url地址(页面不刷新history.pushState);监听popstate事件,根据最新的地址找到对应的组件渲染!!
    • browser路由跳转的地址并不真实存在,所以页面手动刷新,会出现404,此时需要服务器的配合[后台:如果访问的地址不存在,返回主页内容]

  • vue脚手架基于webpack-dev-server启动的服务(开发环境)、已经完成了"服务器应该对history模式的支持"的相关操作;但是打包部署到服务器上(生产环境),没有webpack-dev-server,需要服务器的支持(有指定的页面)

vue-router使用

  • 第一步:安装:$npm i vue-router

  • 第二步:建立路由规则表:创建路由存放的路径以及index.js 和routes.js文件

    • //创建index.js文件并配置vue-router的模式和路由规则表
      //src/router/index.js    :作用是创建vue路由实例,并配置路由
      	import Vue from "vue";
      	import VueRouter from "vue-router"
      	import routes from './routes'
      	
      	Vue.use(VueRouter)
      	let router=new VueRouter({
          //设置路由模式hash、history(默认)
          mode:"hash",
          // 设置路由的匹配规则(路由表):从routes.js中导入
          routes
      	});
      
      export default router;
      
      
      
    • //src/router/routes.js	:作用是单独管理项目的路由表
      	import Home from '@/pages/Home.vue'
      	import Analyse from '@/pages/Analyse.vue'
      	import HomeRoutes from "@/router/homeRoutes"
      	
      	const routes=[{
          	path:"/",//HASH值(pathname值)
         	 component:Home//渲染的组件
      	},{
          	path:"/analyse",
          	component:Analyse,
              // 二级路由:如果感觉嵌套太乱,可以将二级路由单独拆为一个文件
         		children:HomeRoutes
      	},{
         		 path:'*',//以上规则都不匹配
         		 redirect:'/'//也可以重定向到首页(也可以渲染一个404组件)
      	}]
      
      export default routes
      
  • 第三步将router实例添加为全局Vue实例的私有属性

    • //main.js
      import Vue from 'vue';
      import App from '@/App.vue';
      import router from '@/router/index';
      
      let aaa=new Vue({
        //router会添加成为aaa实例的私有属性
        router,//=>this.$router && this.$route
        render: h => h(App),
      }).$mount('#app');
      console.log(aaa);
      
  • 第四步实现路由跳转(改变url地址或者哈希值)

    • <template>
        <div id="app">
          <nav class="nav-box">
            <!-- router-link  内置组件(路由跳转/路由切换)
              +点击实现路由跳转,基于“to”属性指定跳转地址
              +页面渲染的时候,会把router-link渲染为a标签
              +页面刷新或路由切换,都会拿最新的地址(或哈希值)和每一个router-link中to的值(或者path属性值)进行匹配;完全“精准”匹配的会给A标签设置:router-link-exact-active router-link-acive 两个样式名;非精准匹配的只设置:router-link-active这个样式类,一点都没匹配的,啥样式都不设置!!=>我们后期可以基于这个特点,给当前匹配的导航设置选中特殊样式
      
              精准匹配/非精准匹配/完全不匹配
                页面地址:/order
                to的地址:
                
                  / 非精准匹配 (包含一个完整的)
                      /  : 任何地址都包含一个完整的斜杠
                       /home2 VS /home 不算
                       /home/list VS /home 算
                  /analyse    完全不匹配
                  /order 精准匹配(一毛一样)
               -->
            <router-link to="/">首页</router-link>
            <router-link to="/analyse">分析页</router-link>
            <router-link :to="{ path: '/order' }">订单页</router-link>
          </nav>
          <main class="main-box">
            <!-- router-view  内置组件(路由容器)
                用来渲染“基于路由规则匹配组件的” :
                当页面刷新或者路由跳转后,vue都会拿url最新的地址(或者hash值)去路由表中进行匹配,把匹配到的组件,放到router-view容器中渲染
                而每一次的路由切换,都是把上一个渲染的组件释放(或销毁 beforeDestroy destroyed),把新匹配的组件进行渲染(beforeCreate->created->beforeMount->mounted)-->
            <router-view></router-view>
          </main>
        </div>
      </template>
      
  • 第五步设置一个容器,可以在指定的位置,把基于路由规则匹配的组件进行渲染

    • 以上的<router-view></router-view>就是我们制定的位置

router-link

  • router-link 内置组件(路由跳转/路由切换)

  • 实现页面跳转:点击实现路由跳转,基于“to”属性指定跳转地址

    •   <router-link to="/">首页</router-link>
        <router-link to="/analyse">分析页</router-link>
        <router-link :to="{ path: '/order' }">订单页</router-link>
      
  • 页面渲染的时候,会把router-link渲染为a标签

  • 页面刷新或路由切换:都会拿最新的地址(或哈希值)与每一个router-link中to属性的值(或者path属性值)进行匹配;完全“精准”匹配的会给A标签设置:router-link-exact-active router-link-acive两个样式名;非精准匹配的只设置:router-link-active这个样式类,一点都没匹配的,啥样式都不设置!!=>我们后期可以基于这个特点,给当前匹配的导航设置选中特殊样式

精准匹配/非精准匹配/完全不匹配:

  页面地址:/order
  to的地址:
		/ 非精准匹配 (包含一个完整的)
    	/  : 任何地址都包含一个完整的斜杠
     		/home2 VS /home 不算
     		/home/list VS /home 算
		/analyse    完全不匹配
		/order 精准匹配(一毛一样)

router-view

  • router-view 内置组件(路由容器):用来渲染“基于路由规则匹配组件的” :

    • 当页面刷新或者路由跳转后,vue都会拿url最新的地址(或者hash值)去路由表中进行匹配,把匹配到的组件,放到router-view容器中渲染
    • 而每一次的路由切换,都是把上一个渲染的组件释放(或销毁 beforeDestroy=>destroyed),把新匹配的组件进行渲染(beforeCreate->created->beforeMount->mounted)
  • 用法:

    •     <main class="main-box">
            <router-view></router-view>
          </main>
      

二级路由

  • 二级路由可以直接在一级路由表中配置,但这样会显得代码嵌套层数太多,我们可以将二级路由抽出来,放在一个js文件中,再进行导入引用:

  • import Home from '@/pages/Home.vue'
    import HomeRoutes from "@/router/homeRoutes"
    // 路由根据路由表时自上而下匹配的,只要有一个匹配就直接跳转,所以path:"*"不能在最前面匹配
    const routes=[{
        path:"/",//HASH值(pathname值)
        redirect:"/home"//重定向,直接跳转到/home
    },{
        path:"/home",
        component:Home,
        // 二级路由:如果感觉嵌套太乱,可以将二级路由单独拆为一个文件
        children:HomeRoutes//这里是我们导入的二级路由
        
    },]
    
    
  • 二级路由homeRoutes.js文件的写法:

    • 二级路由也是路由表的形式,只是里面的路径:

      • 如果不以斜杠开头,则表示拼接到父级路由后面
      • 如果以斜杠开头,则表示井号#后面的全部路径,不会拼接父路由路径
    • // 管理Home板块的路由表
      const homeRoutes=[
          
          {
          path:"",//如果/home后面没有跟路径,则默认将它重定向到'/home/customerlist',也就是让他第一次打开home就在custmerlist页面
          redirect:'/home/customerlist'
          },
          {
          path:"customerlist",//不是斜杠开头,就会拼在一级目录前:=>/home/customerlist
          component:()=>import("@/pages/home/CustomerList.vue")
          },
          {
          path:"/home/customeradd",//是斜杠开头,就认为这个路径是绝地路径:=>/home/customeradd
          component:()=>import("@/pages/home/CustomerAdd.vue")
          },
          {
          path:"visitList",
          component:()=>import("@/pages/home/VisitList.vue")
      }
      
      
      ];
      export default homeRoutes;
      

路由懒加载

  • vue性能优化方案之一:路由懒加载

    • 问题:如果在编写路由表的时候,事先导入了所有组件,根据规则渲染不同的组件,这样最后build打包的时候,会把所有组件全部打包到一个js中,js文件较大,页面第一次渲染请求js时间过长,延长了白屏事件~~~

    • 解决:路由懒加载依托于ES6中提供的import函数

      • 1、webpack打包的时候实现代码切割:在路由表中已经导入的组件(一般只导入默认需要展示的,就是第一次访问页面需要展示的),打包到一个js中,其余的组件根据情况,分割为一个或多个js文件!
      • 2、最开加载页面,只把主JS文件导入,当路由匹配了某个规则,需要渲染某个组件,再把这个js文件加载
  • **写法:**在路由表中各项的component属性后面用ES6函数:()=>import (/* webpackChunkName: 'analyse'的形式导入指定路径组件的就是==路由懒加载==

    • const routes=[{
          path:"/",//HASH值(pathname值)
          redirect:"/home"//重定向,直接跳转到/home
      },{
          path:"/home",
          //这是不做路由懒加载的
          component:Home,
          children:HomeRoutes
          
      },{
          path:"/analyse",
          //这是做路由懒加载的
          component:()=>import (/* webpackChunkName: 'analyse' */"@/pages/Analyse.vue"),
      }]
      

按组件打包js,按需导入

  • 问题:我们每通过import (/* webpackChunkName: 'analyse'的形式使组件路由懒加载,都会形成一个单独的js文件,这样就会导致项目中js文件很多。
  • 解决component:()=>import (/* webpackChunkName: 'analyse' */"@/pages/Analyse.vue"),
    • 在import内,最前面加上一句/* webpackChunkName: 'analyse'*/这样,它以及它子孙组件就会打包成一个js组件,实现了按包分割的功效,减少了js文件数量
上一篇:vue3.0 从入门到入土---复习 路由


下一篇:Vue.js官方的路由管理器 带你快速入门