【vue-cli】路由模式

1. 概念

路由模式包括 hash模式和history 模式

1.1 hash模式

单页面应用中vue-router 默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载,只加载需要显示的部分(组件)。hash模式URL带"#",代表瞄点,定位页面加载的显示组件是什么。单页面应用,一个页面显示不同内容就是靠"#",它后面的部分地址代表路由,指向某个组件。如:

http://localhost:7230/#/
http://localhost:7230/#/login

第一个“/”,代表一个路由,指向一个组件,一般是首页。“/login” 代表登录组件路由,指向登录组件。

1.2 history 模式

当你使用 history 模式时,URL 就像正常的 url,例如 http://yoursite.com/user/id
,因为我们的应用是个单页客户端应用,用户在浏览器直接访问此地址时会报404错误(F5刷新当前页面们或外部系统调用本系统页面时)。解决这个问题的方法每次请求提交到服务器,服务器找不到资源就返回首页内容index.html,前端收到内容后如果router里面没有该路径,只能匹配404路由
(1)服务器端配置无法匹配资源返回index.html内容
除了index.html资源(首次请求)外,上面地址资源/user/id在服务器是不存在的。因此要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面。nginx配置:

location / {
  try_files $uri $uri/ /index.html;
}

(2)前端处理错误路径返回的页面
虽然能解决404问题,但是你的服务器就不再返回 404 错误页面,因为对于所有路径都会返回 index.html 文件。为了避免这种情况,你应该在 Vue 应用里面覆盖所有的路由情况,然后再给出一个 404 页面。

    router.addRoutes([
      mainRoutes,
      { path: '*', redirect: { name: '404' } }
    ])

npm run dev时候没发现这类问题,因为这时候默认给返回了index.html内容。类似实现nginx功能。
如果以上正常但仍然无法访问、空白页、或部分资源404,比如我这里需要用到一个配置文件env.js,但是返回的404,内容返回了空白或者index.html的内容。这本质是由于路径不对造成的,查看是否有使用了相对路径或者错误的路径

  <!-- 生产环境 -->
  <script>
    document.write('<script src="./systemConfig.js?t=' + new Date().getTime() + '"><\/script>');
    document.write('<script src="./config/index.js?t=' + new Date().getTime() + '"><\/script>');
    // eslint-disable-next-line no-multiple-empty-lines

  </script>
  <% }else { %>
  <!-- 开发环境 -->
  <link rel="shortcut icon" type="image/x-icon" href="./static/img/favicon.ico?v=1">
  <script src="./static/config/index.js"></script>
  <!--  <script src="./static/plugins/mock-1.0.0-beta3/mock-min.js"></script>-->
  <% } %>

如以上相对路径引用改为绝对路径即可

2.history 模式改造

考虑到微信不识别#,另外公司领导看到hash模式#不爽,强烈要求去掉,没法办法只能折腾。整个过程大致这样

2.1.前端部分改造

(1) router模式进行修改

const router = new Router({
  mode: 'history',
  // mode: 'hash',
  scrollBehavior: () => ({ y: 0 }),
  isAddDynamicMenuRoutes: false, // 是否已经添加动态(菜单)路由
  routes: globalRoutes.concat(mainRoutes)
})

(2)刷新页面或者直接输入链接地址空白
发现空白的原因是因为静态资源文件使用相对路径,要改成绝对路径

  <title>ERP财务结算</title>
  <% if (process.env.NODE_ENV === 'production') { %>
  <!-- 生产环境 -->
  <script>
    document.write('<script src="/systemConfig.js?t=' + new Date().getTime() + '"><\/script>');
    document.write('<script src="/config/index.js?t=' + new Date().getTime() + '"><\/script>');
    // eslint-disable-next-line no-multiple-empty-lines
  </script>
  <% }else { %>
  <!-- 开发环境 -->
  <link rel="shortcut icon" type="image/x-icon" href="/static/img/favicon.ico?v=1">
  <script src="/static/config/index.js"></script>
  <!--  <script src="./static/plugins/mock-1.0.0-beta3/mock-min.js"></script>-->
  <% } %>
</head>

由于是引用了外部js等静态文件,不是import的,所有要用绝对路径

2.2.nginx改造

history模式,还需要后台配置支持。因为我们的应用是个单页客户端应用,如果后台没有正确的配置,当用户在浏览器直接访问 http://oursite.com/user/id 就会返回 404,因此服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面内容

   location /{
       #文件位置
      root /HXG/www/dist-cw;
      try_files $uri $uri/ /index.html last;
      index index.html;
  }

这么做以后,你的服务器就不再返回 404 错误页面,因为对于所有路径都会返回 index.html 文件。为了避免这种情况,你应该在 Vue 应用里面覆盖所有的路由情况,然后再给出一个 404 页面。

    router.addRoutes([
      mainRoutes,
      { path: '*', redirect: { name: '404' } }
    ])

路由对象最后添加404路由,当前面路由都匹配不到时,就执行跳转到404

2.3. 本地调试和nginx服务器执行差异

本地调试使用npm run dev,不管是本地服务器或者服务器调用,都不会访问页面。但是服务器方式,会请求
[数字].js,页面对应的js文件,所以页面对应的js路径一定不能错


image.png

2.4.发布部署问题

hash模式发布最简单省事,但是history模式发布遇到复杂一点,就问题多多,例如nginx多层代理(内外网要求),应用没有发布在域名的目录根下如http://xxx.com/wx/,又或如部署到一个子目录。现在总结如下:
(1)直接发布域名下
域名只是绑定这个系统,可以简单配置,参照

    server {
        listen 1005;
        server_name 1005;           
        location / {
            proxy_pass   http://101.150.10.23:12345/;
        }       
    }   

(2)发布域名下级目录下
有时候存在多个系统挂在同一个域名下,通过不同目录来区分。例如目录是"/cw/"

    server {
        listen 1004;
        server_name 1004;           
        #页面路径
        location /cw/ {
            proxy_pass   http://101.150.10.23:89/;
        }
        #静态文件是绝对路径,没有/cw/前缀,因此要设置匹配路由
        location ~* \.(js|css|img|png|jpg|ioc)$ { 
            proxy_pass   http://101.150.10.23:89;
        }       
    }   

因为js等静态文件是绝对路径,所以需要增加静态文件路由匹配。如果域名下有目录(系统),正则匹配还需要优化,再根据页面路径(referer)规则过滤到不同的系统。以下是存在/cw/和/wl/两个目录:
http://localhost:1006/cw/
http://localhost:1006/wl/
具体参照配置:

    server {
        listen 1006;
        server_name 1006;
        ####财务系统####
        #页面路径
        location /cw/ {
            proxy_pass   http://101.150.10.23:89/;
        }   
        ###物流系统####
        location /wl/ {
            proxy_pass    http://101.150.10.23:12345/;
        }   
        #静态文件是绝对路径,没有/cw/和/wl/前缀,因此要设置匹配路由
        location ~* \.(js|css|img|png|jpg)$ {
            if ($http_referer ~* "http://localhost:1006/cw/")
            {
                proxy_pass http://101.150.10.23:89;
                #break;
            }
            if ($http_referer ~* "http://localhost:1006/wl/")
            {
                proxy_pass http://101.150.10.23:12345;
                #break;
            }   
        }
    }

除了要做nginx配置外,代码层面也需要支持,查阅官方资料如下:

  • 如果想部署到一个子目录,你需要使用 Vue CLI 的 publicPath 选项 (opens new window)和相关的 router base property(基路径)
  • 当你在 HTML5 history 模式下使用 base 选项之后,所有的 to 属性都不需要写 (基路径) 了。

这里都提到了基路径base,所以需要用到基路径配置,基路径设置为/cw/

const router = new Router({
  mode: 'history',
  base: '/cw/',
  scrollBehavior: () => ({ y: 0 }),
  isAddDynamicMenuRoutes: false, // 是否已经添加动态(菜单)路由
  routes: globalRoutes.concat(mainRoutes)
})

基路径有个很重要的特点,请求url路径可以含有基路径,也可以不含有,效果是一样:

http://101.150.10.23:89/cw/about 和 http://101.150.10.23:89/about 访问是一样的

在导航路由中查看路由情况,其实是to不含有基路径的

router.beforeEach((to, from, next) => {
  console.log('from===' + from.path)
  console.log('to===' + to.path)
}
都是输出
to===/about
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,651评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,468评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,931评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,218评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,234评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,198评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,084评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,926评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,341评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,563评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,731评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,430评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,036评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,676评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,829评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,743评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,629评论 2 354

推荐阅读更多精彩内容