vue路由

作者: 我写的代码绝对没有问题 | 来源:发表于2021-01-07 16:10 被阅读0次
    • 为啥我写的Vue应用在开发阶段都没问题,部署到服务端之后访问不了除了/的页面呢
    • 为啥我写的SPA页面的路由用hash模式都没问题,改成history模式就问题百出呢
    • 啥是前端路由啥是后端路由,要怎么配后端才能支持我的前端路由呢

    1、什么是路由
    在Web开发过程中,经常会遇到『路由』的概念。那么,到底什么是路由?简单来说,路由就是URL到函数的映射。
    访问的URL会映射到相应的函数里(这个函数是广义的,可以是前端的函数也可以是后端的函数),然后由相应的函数来决定返回给这个URL什么东西。路由就是在做一个匹配的工作。

    2、前端路由
    前端路由——顾名思义,页面跳转的URL规则匹配由前端来控制。而前端路由主要是有两种显示方式:

    • 带有hash的前端路由,优点是兼容性高。缺点是URL带有#号不好看
    • 不带hash的前端路由,优点是URL不带#号,好看。缺点是既需要浏览器支持也需要后端服务器支持

    前端路由应用最广泛的例子就是当今的SPA的web项目。不管是Vue、React还是Angular的页面工程,都离不开相应配套的router工具。前端路由带来的最明显的好处就是,地址栏URL的跳转不会白屏了——这也得益于前端渲染带来的好处。

    3、前端路由与前端渲染
    讲前端路由就不能不说前端渲染。我以Vue项目为例。如果你是用官方的vue-cli搭配webpack模板构建的项目,你有没有想过你的浏览器拿到的html是什么样的?是你页面长的那样有button有form的样子么?我想不是的。在生产模式下,你看看构建出来的index.html长什么样:

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Vue</title>
    </head>
    <body>
      <div id="app"></div>
      <script type="text/javascript" src="xxxx.xxx.js"></script>
      <script type="text/javascript" src="yyyy.yyy.js"></script>
      <script type="text/javascript" src="zzzz.zzz.js"></script>
    </body>
    </html>
    

    可以看到,这个其实就是你的浏览器从服务端拿到的html。这里面空荡荡的只有一个<div id="app"></div>这个入口的div以及下面配套的一系列js文件。所以你看到的页面其实是通过那些js渲染出来的。这也是我们常说的前端渲染。

    前端渲染把渲染的任务交给了浏览器,通过客户端的算力来解决页面的构建,这个很大程度上缓解了服务端的压力。而且配合前端路由,无缝的页面切换体验自然是对用户友好的。不过带来的坏处就是对SEO不友好,毕竟搜索引擎的爬虫只能爬到上面那样的html,对浏览器的版本也会有相应的要求。


    image.png

    需要明确的是,只要在浏览器地址栏输入URL再回车,是一定会去后端服务器请求一次的。而如果是在页面里通过点击按钮等操作,利用router库的api来进行的URL更新是不会去后端服务器请求的。

    Hash模式

    hash模式利用的是浏览器不会对#号后面的路径对服务端发起路由请求。
    也就是在浏览器里输入如下这两个地址:http://localhost/#/user/1http://localhost/其实到服务端都是去请求http://localhost这个页面的内容。

    而前端的router库通过捕捉#号后面的参数、地址,来告诉前端库(比如Vue)渲染对应的页面。这样,不管是我们在浏览器的地址栏输入,或者是页面里通过router的api进行的跳转,都是一样的跳转逻辑。所以这个模式是不需要后端配置其他逻辑的,只要给前端返回http://localhost对应的html,剩下具体是哪个页面,就由前端路由去判断便可。

    History模式

    不带#号的路由,也就是我们通常能见到的URL形式。router库要实现这个功能一般都是通过HTML5提供的history这个api。比如history.pushState()可以向浏览器地址栏push一个URL,而这个URL是不会向后端发起请求的!通过这个特性,便能很方便地实现漂亮的URL。不过需要注意的是,这个api对于IE9及其以下版本浏览器是不支持的,IE10开始支持,所以对于浏览器版本是有要求的。vue-router会检测浏览器版本,当无法启用history模式的时候会自动降级为hash模式。

    上面说了,你在页面里的跳转,通常是通过router的api去进行的跳转,router的api调用的通常是history.pushState()这个api,所以跟后端没什么关系。但是一旦你从浏览器地址栏里输入一个地址,比如http://localhost/user/1,这个URL是会向后端发起一个get请求的。后端路由表里如果没有配置相应的路由,那么自然就会返回一个404了!这也就是很多朋友在生产模式遇到404页面的原因。

    那么很多人会问了,那为什么我在开发模式下没问题呢?那是因为vue-cli在开发模式下帮你启动的那个express开发服务器帮你做了这方面的配置。理论上在开发模式下本来也是需要配置服务端的,只不过vue-cli都帮你配置好了,所以你就不用手动配置了。

    那么该如何配置呢?其实在生产模式下配置也很简单,参考vue-router给出的配置例子。一个原则就是,在所有后端路由规则的最后,配置一个规则,如果前面其他路由规则都不匹配的情况下,就执行这个规则——把构建好的那个index.html返回给前端。这样就解决了后端路由抛出的404的问题了,因为只要你输入了http://localhost/user/1这地址,那么由于后端其他路由都不匹配,那么就会返回给浏览器index.html

    浏览器拿到这个html之后,router库就开始工作,开始获取地址栏的URL信息,然后再告诉前端库(比如Vue)渲染对应的页面。到这一步就跟hash模式是类似的了。

    当然,由于后端无法抛出404的页面错误,404的URL规则自然是交给前端路由来决定了。你可以自己在前端路由里决定什么URL都不匹配的404页面应该显示什么。

    通俗点说,route就是你访问一个页面的地址。router就是由一群地址组成的东西。

    参考https://www.cnblogs.com/songyao666/p/11470030.html#router=1
    https://zhuanlan.zhihu.com/p/138480612

    首先我们来学习三个单词(route,routes,router):
      route:首先它是个单数,译为路由,即我们可以理解为单个路由或者某一个路由;
      routes:它是个复数,表示多个的集合才能为复数;即我们可以理解为多个路由的集合,JS中表示多种不同状态的集合的形式只有数组和对象两种,事实上官方定义routes是一个数组;所以我们记住了,routes表示多个数组的集合;
      router:译为路由器,上面都是路由,这个是路由器,我们可以理解为一个容器包含上述两个或者说它是一个管理者,负责管理上述两个;举个常见的场景的例子:当用户在页面上点击按钮的时候,这个时候router就会去routes中去查找route,就是说路由器会去路由集合中找对应的路由;

    router.js

    //引入vue
    import Vue from 'vue';
    //引入vue-router
    import VueRouter from 'vue-router';
    //第三方库需要use一下才能用
    Vue.use(VueRouter)
    //引用page1页面
    import page1  from './page1.vue';
    //引用page2页面
    import page2  from './page2.vue';
    
    //定义routes路由的集合,数组类型
    const routes=[
        //单个路由均为对象类型,path代表的是路径,component代表组件
        {path:'/page1',component:page1},
        {path:"/page2",component:page2}
    ]
    
    //实例化VueRouter并将routes添加进去
    const router=new VueRouter({
    //ES6简写,等于routes:routes
        routes
    });
    
    //抛出这个这个实例对象方便外部读取以及访问
    export default router
    

    这里我们再修改一下main.js

    import Vue from 'vue'
    import App from './App'
    //引用router.js
    import router from './router.js'
    Vue.config.productionTip = false
    
    /* eslint-disable no-new */
    new Vue({
      el: '#app',
    //一定要注入到vue的实例对象上
      router,
      components: { App },
      template: '<App/>'
    })
    

    修改App.vue

    <template>
      <div id="app">
        <img src="./assets/logo.png">
        <div>
    //router-link定义页面中点击触发部分  
          <router-link to="/page1">Page1</router-link>
          <router-link to="/page2">Page2</router-link>
        </div>
    //router-view定义页面中显示部分
        <router-view></router-view>
      </div>
    </template>
    
    <script>
    export default {
      name: 'App'
    }
    </script>
    
    <style>
    #app {
      font-family: 'Avenir', Helvetica, Arial, sans-serif;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
      text-align: center;
      color: #2c3e50;
      margin-top: 60px;
    }
    </style>
    

    参考https://www.cnblogs.com/dengyao-blogs/p/11562257.html

    相关文章

      网友评论

        本文标题:vue路由

        本文链接:https://www.haomeiwen.com/subject/glxzoktx.html