前端面试题(六)

Vue路由的实现原理

路由这个概念最初是由后端提出来的,在我们没有SPA单页面应用之前,使用的一直都是后端路由,根据不同的路由返回不同的页面,后来随着单页面应用的诞生,开始有了前端路由,实现不刷新但是更新页面的效果
vue-router是专为Vue打造的路由管理工具
vue-router提供三种路由模式
1.hash模式

  • 默认模式,通过路径中的hash值来控制路由跳转,不存在兼容问题
    2.history模式
  • H5新增的 history API,相对hash而言,不会显示#号,但是需要服务器端配置
    3.abstract模式
  • 支持javascript的所有运行环境,常指Node.js服务器环境
hash模式实现原理

在正常路径后跟一个 # 号,匹配 # 后边的路径为前端路由,通过window.onhashchange方法来操控路由改变的时候切换内容
2.onhashchange 方法的触发时机

  1. 直接更改浏览器地址,在最后面增加或改变#hash;
  2. 通过改变location.href或location.hash的值;
  3. 通过触发点击带锚点的链接;
  4. 浏览器前进后退可能导致hash的变化,前提是两个网页地址中的hash值不同。
    2.示例代码
<body>
  <ul>
    <li>
       <a href="#/home">home</a>
    </li>
    <li>
       <a href="#/list">list</a>
    </li>
    <li>
       <a href="#/detail">detail</a>
    </li>
 </ul>
</body>
<script>
window.onhashchange = function() {
    //  做页面切换渲染等
    console.log(location.href);
    console.log(location.hash);
}
</script>
  • 通过点击a标签,传递一个hash值,然后通过window.onhashchange方法来监听hash的变化,然后在这个事件触发的时候,根据location.hash来动态的修改单页面应用的内容即可
history模式实现原理

看起来与后端路由没有任何区别,在window.history这个对象中,包含浏览器的历史,而在HTML5中,新增了pushState和replaceState,通过这两个API可以改变url地址且不会发送请求,同时还有popstate事件,实现原理与hash相似,只不过因为没有了 # 号,所以刷新页面还是会向服务器发送请求,而后端没有对应的处理措施的话,会返回404,所以需要后端配合

  1. popstate方法的触发时机
  2. 仅仅调用pushState方法或replaceState方法 ,并不会触发该事件;
  3. 只有用户点击浏览器倒退按钮和前进按钮,或者使用JavaScript调用back、forward、go方法时才会触发。
  4. 另外,该事件只针对同一个文档,如果浏览历史的切换,导致加载不同的文档,该事件也不会触发。
    2.示例代码
<body>
  <ul>
    <li>
      <a href="/home">home</a>
    </li>
    <li>
      <a href="/list">list</a>
    </li>
    <li>
      <a href="/detail">detail</a>
    </li>
  </ul>
</body>
<script>
document.querySelectorAll('a').forEach(item => {
  item.onclick = function (e) {
      e.preventDefault();
      let link = item.getAttribute('href');
      window.history.pushState({link}, link, link);
   };
});
window.addEventListener('popstate', function (e) {
   console.log(e.state);
   console.log(location.href);
})
</script>
  • 当点击浏览器的后退或前进按钮,或者调用history上的go、back方法时,就会触发事件,打印出对应的数据,e.state 中就存放着pushState方法中的state对象
  • 通过在修改路由信息的同时执行切换DOM的操作,来实现了路由切换
abstract模式实现原理
  • abstract模式是不依赖于浏览器环境,所以没有使用hash或者history等浏览器才会提供的API,而是VueRouter内部使用数组进行模拟了路由管理,在node环境,或者原生App环境下,都会默认使用abstract模式,VueRouter内部会根据所处的环境自行判断,默认使用hash模式,如果检测到没有浏览器API的时候,就会使用abstract模式。

SPA 路由history模式上线后刷新404

1.出现问题:在使用history模式的时候,由于浏览器路径与后端路径类似,所以当刷新页面的时候,浏览器还是会向服务器发送请求,但是由于服务器并没有对应的路由页面,所以会导致404空白
2.解决方案:在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。同时这么做以后,服务器就不再返回 404 错误页面,因为对于所有路径都会返回 index.html 文件。为了避免这种情况,在 Vue 应用里面覆盖所有的路由情况,然后在给出一个 404 页面。或者,如果是用 Node.js 作后台,可以使用服务端的路由来匹配 URL,当没有匹配到路由的时候返回 404,从而实现后退。
1.node服务器

  • 简单粗暴的一种方法,如果没有读取到静态资源就直接返回html页面,可以用于前端调试
const http = require('http');
const fs = require('fs');

http.createServer((req,res) => {
    fs.readFile(__dirname + req.url, (err, data) => {
      if(!err) {
          res.end(data);
      }else {
          fs.readFile('index.html', (e, html) => {
              if(!e) {
                  res.end(html);
              }
          })
      }
  })
}).listen(8080, err => {
  !err&&(console.log('http://localhost:8080')
})

2.nginx静态服务器

  • 常用方式,直接使用80端口
server {
      listen       80;
      server_name  localhost;

      location / {
          root   html;
          index  index.html;
          try_files $uri $uri/ /index.html;
      }
   }
  • 在nginx安装目录下,将打包后的文件放置在安装目录下的 html 目录中,接着打开conf目录中的nginx.conf文件,修改server部分如上,然后在nginx根目录使用nginx -t测试配置文件修改后的语法是否正确(如果有问题会报错),如果没有错误的话,使用命令nginx -s reload命令重启让配置文件生效,打开浏览器,输入localhost即可看到项目部署完成
  • 常用方式,同时运行多个程序时,80端口被占用时
server {
    listen       8000;
    server_name  localhost;

    location / {
        root   html/project;
        index  index.html;
        try_files $uri $uri/ /index.html;
    }
}
  • 在html目录下新建文件夹,例如project,将打包后的文件放置在project文件夹下,在conf/nginx.conf文件中,原80端口的下方新加入上述代码,接着重复nginx -t与nginx -s reload再次打开浏览器,输入localhost:8000就可以看到项目部署完成

$$route和$router的区别

1.route是路由信息对象,包括 path、params、hash、query、fullPath、meta、name 等路由信息参数,可以通过route来获取当前路由的各种参数
1.path String 保存当前绝对路径信息

2.params Object 保存当前的params参数对象

3.hash String 保存当前的hash信息,不带#号,如果没有hash为空字符串

4.query Object 保存当前的query参数对象

5.meta Object 保存当前路由的源信息

6.fullPath String 保存完成解析后的路径信息,包含hash、query等参数

7.name String 保存路由name值

2.$router是路由实例对象,包含的是VueRouter实例上的方法以及配置属性,常用于编程式导航;

1.push Function(Object|String)

  • this.$router.push('/home?tab=all')
  • this.$router.push({path: '/home', query:{tab:'all'}})

2.replace Function(Object|String)

  • this.$router.replace('/home?tab=all')
  • this.$router.replace({path: '/home', query:{tab:'all'}})

3.go Function(Number)

  • this.$router.go(-1) 操作history的API进行后退

  • this.$router.go(1) 操作history的API进行前进

自定义过滤器详解

1.在Vue1.x的版本中,是有内置过滤器的,而到了2.0以后,废除了内置过滤器,允许我们自定义过滤器
2.自定义过滤器的使用方法

  • 在插值表达式{{}}以及v-bind:指令绑定的属性的冒号内,可以使用自定义过滤器
  • 使用时,在js表达式的结尾使用管道符来指示过滤器
  • 示例: {{date| formatDate}} 或者 <input v-bind:value="date | formatDate" />
    3.自定义过滤器的使用场景
  • 在我们前端拿到后台的数据时,经常有些数据是不能直接展示出来的,需要经过处理之后再展示,在Vue中,我们可以通过methods来做,也可以通过computed计算属性来做,但是最好还是通过过滤器filters来做,因为它是在原数据基础上进行过滤,不会修改原有数据,使用computed以及methods属于大材小用了
    4.过滤器的定义
  • 在Vue中分为全局过滤器局部过滤器
// 全局过滤器
  Vue.filter(过滤器名称, function(value) {
      return value;  // 处理value,vlaue就是需要过滤的数据
  })
  // 局部过滤器
  new Vue({
      el: '#app',
      filters: {
            '过滤器名称'(value) {
                 return value;  // 处理value,vlaue就是需要过滤的数据
            }
      }
  })

5.实现自定义过滤器
1.无参数过滤器

Vue.filter('formatDate', function(value) {
      if(!value) return;
      return new Date(value).toLocaleString();
}) 
// html
<div>{{ 1562731217574 | formatDate }}</div>

2.有参数过滤器

Vue.filter('formatPrice', function(value, num) {
      if(!value) return;
      return value.toFixed(num);
}) 
// html
<div>{{ 15.6264 | formatPrice(2)}}</div>

3.多个参数的过滤器

Vue.filter('formatText', function(value, start, end) {
      if(!value) return;
      return start + '-' + value + '-' + end;
}) 
// html
<div>{{ '中间' | formatText('开始','结束')}}</div>

4.过滤器串联,可以多个串联

 <div>{{ '中间' | formatText('开始','结束') | formatText('串联start','串联end') }}</div> 

assets和static/public的区别

在vue-cli工具中,有两个存放静态资源的目录,一个是src目录下的assets,另一个在vue-cli2下是static目录,在vue-cli3下是public目录,那这两个目录的区别是什么呢?
首先需要知道:在.vue组件中,所有的templates和css都会被vue-html-loader 和 css-loader解析,寻找资源的URL。
例如: <img src="./assets/logo.png">或者 background: url('./assets/logo.png'),这两个url路径都会被webpack解析成资源模块依赖,而由于这些静态文件大都不是js文件,而vue-cli工具利用各种loader帮助我们解析了这些资源

资源处理规则
1.相对路径, ./assets/logo.png 将会被解析成一个模块依赖。
2.没有前缀的路径, assets/logo.png 将会被看成./assets/logo.png进行解析模块依赖
3.前缀带~的URL 会被当成模块请求, 例如:<img src="~assets/logo.png">
4.相对根目录的URL/assets/logo.png 是不会被处理的

javascript中使用静态资源

  • 例如:imgUrl: require('./assets/logo.png')

assets和static/public的区别

  • 在assets目录下的静态资源会被webpack解析成资源模块依赖,在项目打包的时候会随着项目一起打包
  • 而在static/public目录下的静态资源不会被解析,是真正的静态资源

本文CSDN地址:前端面试题(六)

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