面试题

vue-router实现原理

1: 有两种方式:
1. 在地址中加入#以欺骗浏览器,地址的改变是由于正在进行页内导航
2. 使用H5的window.history功能,使用URL的Hash来模拟一个完整的URL。

1: hash —— 即地址栏 URL 中的 # 符号(此 hash 不是密码学里的散列运算)。比如这个 URL:http://www.abc.com/#/hello hash 的值为 #/hello。它的特点在于:hash 虽然出现在 URL 中,但不会被包括在 HTTP 请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面。

2: history —— 利用了 HTML5 History Interface 中新增的 pushState() 和 replaceState() 方法。(需要特定浏览器支持)这两个方法应用于浏览器的历史记录栈,在当前已有的 back、forward、go 的基础之上,它们提供了对历史记录进行修改的功能。只是当它们执行修改时,虽然改变了当前的 URL,但浏览器不会立即向后端发送请求。

history模式的问题

对于单页应用来说,理想的使用场景是仅在进入应用时加载index.html,后续在的网络操作通过ajax完成,不会根据url重新请求页面,但是如果用户直接在地址栏中输入并回车,浏览器重启重新加载等特殊情况。

hash模式仅改变hash部分的内容,而hash部分是不会包含在http请求中的(hash带#):

官方推荐的解决办法是在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。同时这么做以后,服务器就不再返回 404 错误页面,因为对于所有路径都会返回 index.html 文件。为了避免这种情况,在 Vue 应用里面覆盖所有的路由情况,然后在给出一个 404 页面。或者,如果是用 Node.js 作后台,可以使用服务端的路由来匹配 URL,当没有匹配到路由的时候返回 404,从而实现 fallback。

Vue响应式原理

当一个Vue实例创建时,vue会遍历data选项的属性,用 Object.defineProperty 将它们转为 getter/setter并且在内部追踪相关依赖,在属性被访问和修改时通知变化。

每个组件实例都有相应的 watcher 程序实例,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的 setter 被调用时,会通知 watcher 重新计算,从而致使它关联的组件得以更新。
https://i.loli.net/2019/04/03/5ca406c4a679a.png

SPA 路由History模式 刷新404问题

原因
    刷新404,为什么,因为本地路径中没有这个真实资源存在,这些访问资源都是在js里渲染的。我们只需要在服务器配置如果URL匹配不到任何静态资源,就跳转到默认的index.html。
解决方案

nginx服务器下

server {
        listen       8089; // 端口
        server_name  localhost; // 访问地址,默认是本机
       location / {
            try_files $uri $uri/ @router; // 需要指向下面的@router否则会出现vue的路由在nginx中刷新出现404
            index  index.html index.htm;
        }
        // 对应上面的@router,主要原因是路由的路径资源并不是一个真实的路径,所以无法找到具体的文件
        #因此需要rewrite到index.html中,然后交给路由在处理请求资源
        location @router {
            rewrite ^.*$ /index.html last;
        }

记住修改配置后一定要重启Nginx服务器,否则无效,Nginx相关命令, 自行百度
nginx 代理知识充电:
proxy_pass 的路径,如果不带uri的话,就是直接原路径代理匹配,带有uri的话,就去掉匹配项再匹配,
实例如下:

(1)
访问 http://www.wyunfei.com/testa/aaa
后端的request_uri为: /testa/aaa
location ^~ /testa/ {
    proxy_pass http://127.0.0.1:8801;
}
(2)
访问 http://www.wyunfei.com/testa/bbb
后端的request_uri为: /testa/bbb
location ^~ /testb/ {
    proxy_pass http://127.0.0.1:8801/;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Vue八个生命周期 beforeCreate【创建前】created【创建后】 beforeMount【载入前】 ...
    艾萨克菊花阅读 1,357评论 0 12
  • 1.Vue的数据双向绑定如何实现?Vue的数据双向绑定如何实现? v-model指令或者.sync修饰 2.Vue...
    骑着蜗牛逛妓院阅读 3,857评论 1 11
  • Vue路由的实现原理 路由这个概念最初是由后端提出来的,在我们没有SPA单页面应用之前,使用的一直都是后端路由,根...
    郝晨光阅读 1,943评论 0 19
  • Vue路由的实现原理 路由这个概念最初是由后端提出来的,在我们没有SPA单页面应用之前,使用的一直都是后端路由,根...
    b491fe9a99d7阅读 427评论 0 1
  • 今日,奔波途中,接到一朋友电话,跟我探讨她正碰到的一个困扰,管理到底是“人治”还是“法治”好。 故事是这样的: 公...
    陈玛莎Maria阅读 3,709评论 0 6