通过Nginx,代理Vue项目,刷新页面返回404,思考VUE项目的F5刷新和路由请求。

举报
DevFeng 发表于 2021/08/20 16:02:33 2021/08/20
【摘要】 通过Nginx,代理Vue项目,刷新页面返回404。为什么会出现404原因是因为web单页面开发模式,只有一个index.html入口,其他路径是前端路由去跳转的,nginx没有对应这个路径,当然就是404了。一般nginx监听配置如下    server {        listen       8086;        server_name  localhost;        lo...

通过Nginx,代理Vue项目,刷新页面返回404。

为什么会出现404

原因是因为web单页面开发模式,只有一个index.html入口,其他路径是前端路由去跳转的,nginx没有对应这个路径,当然就是404了。
一般nginx监听配置如下

    server {
        listen       8086;
        server_name  localhost;
        location / {
            root   D:\XXX\XXX\dist;
            index  index.html index.htm;
        }
    
    }

知道是因为nginx找不到路径那么该如果去处理

处理方法

在配置中加上try_files,意思跟翻译差不多,“尝试读取文件”。

    server {
        listen       8086;
        server_name  localhost;
        location / {
            root   D:\XXX\XXX\dist;
            index  index.html index.htm;
            try_files $uri $uri/ /index.html;
        }
    
    }

当用户请求 http://localhost/example 时,这里的 $uri 就是 /example。 
try_files 会到硬盘里尝试找这个文件。如果存在名为 /$root/example(其中 $root 是项目代码安装目录)的文件,就直接把这个文件的内容发送给用户。 
显然,目录中没有叫 example 的文件。然后就看 $uri/,增加了一个 /,也就是看有没有名为 /$root/example/ 的目录。 
又找不到,就会 fall back 到 try_files 的最后一个选项 /index.php,发起一个内部 “子请求”,也就是相当于 nginx 发起一个 HTTP 请求到 http://localhost/index.php。 

 

那么为什么VUE项目会出现这个问题?

前言
基于vue-cli脚手架开发的单页应用有他特殊的特点和优势。因为是单页应用,所以在进行F5刷新的时候和之前常规的html页面还有区分。主要区别在于,vue-router接管了浏览器的前进、后退、刷新等事件,通过对相关事件的监听,动态的操作popstate,pushstate,replacestate等api来完成浏览器url的变化;但其实对于页面本身而言,并没有我们所理解的常规刷新或者后退前进操作,毕竟是单页应用,内部的核心还是动态的div切换或者dom元素的动态渲染。

本篇通过对F5刷新操作的跟踪,我们来记录和了解一下vue组件是如何对对刷新操作进行处理的,各个组件的生命周期又是如何进行操作的,又有哪些点是需要我们注意的。

问题描述
我们先来看一个具体的问题,实际项目中,登录成功之后的页面是一个左右结构的页面,假设为组件A,左侧是菜单区域,右侧是显示区域,我们的做法是在右侧区域添加一个<router-view>,通过左侧菜单的点击,动态的改变右侧router-view中的页面效果。首次登陆成功之后,要显示一个默认页面,我们在组件A的create中获取菜单树,然后判断菜单的id是否顶级,如果是则自动显示,假设默认组件是B。然后选择左侧菜单,跳转新页面,右侧区域渲染,假设我们显示了C组件,此时F5刷新,页面会自动回到组件B,也就是说,刷新操作无法刷“当前页”,只要刷新总会返回首页。

问题分析
我们在根组件A的beforeRouteEnter钩子函数中将to、from打印出来。然后我们通过左侧菜单点击,页面跳转到manager_device_list路由页面,然后点击F5刷新,打印的to 和 from如下

可以看到from的null,to就是我们当前的路由页面,但是为何会自动跳转到首页B去了呢?

这里就要说一下F5刷新时候组件的生命周期。

F5刷新的时候,会从跟组件重新走生命周期,即其实是从root.vue开始重新走声明周期,然后一级一级往下走,根据to路由最终到具体的渲染页面,问题就是出在这里,因为我们在跟组件A的create方法中循环菜单并自动跳转到首页了,所以在F5之后重新走跟组件声明周期时,在create中直接就把路由改变了,而不会再回到原来的to。

问题解决
通过再跟组件A的beforeRouteEnter钩子函数中判断from.name是否为null,来操作是否走自动到首页的逻辑。相关代码如下:

beforeRouteEnter(to, from, next) {
      console.log("to--->",to);
      console.log("from--->",from);
      if(ctool.strIsEmpty(from.name)){
        next();
      }else{
        next(vm => vm.initViews());
      }
    },
这里initViews中就是循环菜单找到首页并跳转到首页的逻辑。通过上面这种处理,完美解决该问题。

总结
(1) 不管是在浏览器中还是通过this.$router.push跳转某个页面时候,路由都是会从跟组件开始走,最终定位到具体的子组件,并在其对应的router-view中渲染,尤其是router-view嵌套router-view时候会看的更清晰,子组件始终是在父组件的生命周期走完再开始渲染。即:如果出现刷新后,页面没有留在当前页,那肯定是代码逻辑处理的有问题。

(2) F5刷新操作会清空store中的数据,所以般情况下,我们可以通过监听浏览器的刷新事件,在跟组件中对store中的数据通过localstorage进行保存和还原。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。