欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

面试题-1

程序员文章站 2022-06-04 18:23:41
...

一、网页从输入网址到渲染经历了哪些过程

1、输入网址

2、发送到DNS服务器,并获取域名对应的WEB服务器对应的Ip地址

3、与服务器web建立TCP连接

4、浏览器向web服务器发送http请求

5、web服务器响应请求,并返回指定url的数据(或错误信息,或重定向的新的url地址)

6、浏览器下载Web服务器返回的数据并解析html源文件

7、生成DOM树,解析css和js,渲染页面,直至显示完成。

二、Vue双向数据绑定原理

1.数据劫持结合发布者-订阅者模式来实现的。通过Object.defineProperty()来实现数据劫持。

2.实现双向数据绑定主要包含两个方面

(1)视图(view)到数据(data),通过事件监听即可完,

(2)数据(data)到视图(view)通过Object.defineProperty()对属性设置一个set函数,当数据改变就来触发这个函数

(别人的博客上看到的:vue.js 是采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty()来劫持各个属性的 setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。)

三、Vue-router有哪几种导航钩子函数

1、全局导航钩子

(1)rouer.beforeEach(to,from,next):全球前卫
(2)router.beforeResolve(to,from,next):全球解决警卫
(3)router.afterEach(to,from,next):全球后钩

2、组件内钩子
(1)beforeRouteEnter
(2)beforeRouteUpdate
(3)beforeRouteLeave

3、单独路由独享组件
beforeEnter

四、vue-router的两种模式

vue-router存在的意义:改变视图的同时不会向后端发起请求

1、hash模式:地址栏URl中的#符号

(1)原理:onhashchang事件,通过window对象来监听该事件

这里的 hash 就是指 url 尾巴后的 # 号以及后面的字符。这里的 # 和 css 里的 # 是一个意思。hash 也 称作 锚点,本身是用来做页面定位的,她可以使对应 id 的元素显示在可视区域内。

比如这个 URL:http://www.abc.com/#/hello,hash 的值为 #/hello。它的特点在于:hash 虽然出现在 URL 中,但不会被包括在 HTTP 请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面。

由于 hash 值变化不会导致浏览器向服务器发出请求,而且 hash 改变会触发 hashchange 事件,浏览器的进后退也能对其进行控制,所以人们在 html5 的 history 出现前,基本都是使用 hash 来实现前端路由的。

使用到的api:

window.location.hash = 'qq' // 设置 url 的 hash,会在当前url后加上 '#qq'

var hash = window.location.hash // '#qq' 

 window.addEventListener('hashchange', function(){

    // 监听hash变化,点击浏览器的前进后退会触发

})

2、history模式:利用了HTML5 History Interface中新增的pushState() 和 repalceState()方法

已经有 hash 模式了,而且 hash 能兼容到IE8, history 只能兼容到 IE10,为什么还要搞个 history 呢?

首先,hash 本来是拿来做页面定位的,如果拿来做路由的话,原来的锚点功能就不能用了。其次,hash 的传参是基于 url 的,如果要传递复杂的数据,会有体积的限制,而 history 模式不仅可以在url里放参数,还可以将数据存放在一个特定的对象中。

相关api:

window.history.pushState(state, title, url)

 // state:需要保存的数据,这个数据在触发popstate事件时,可以在event.state里获取

// title:标题,基本没用,一般传 null

l// url:设定新的历史记录的 url。新的 url 与当前 url 的 origin 必须是一樣的,否则会抛出错误。url可以是绝对路径,也可以是相对路径。//如 当前url是 https://www.baidu.com/a/,执行history.pushState(null, null, './qq/'),则变成 https://www.baidu.com/a/qq/,//执行history.pushState(null, null, '/qq/'),则变成 https://www.baidu.com/qq/

window.history.replaceState(state, title, url)

// 与 pushState 基本相同,但她是修改当前历史记录,而 pushState 是创建新的历史记录window.addEventListener("popstate", function(){

    // 监听浏览器前进后退事件,pushState 与 replaceState 方法不会触发             

 });

window.history.back() // 后退

window.history.forward() // 前进

window.history.go(1) // 前进一步,-2为后退两步,

window.history.length可以查看当前历史堆栈中页面的数量

history 模式改变 url 的方式会导致浏览器向服务器发送请求,这不是我们想看到的,我们需要在服务器端做处理:如果匹配不到任何静态资源,则应该始终返回同一个 html 页面。

hash 模式下,仅 hash 符号之前的内容会被包含在请求中,如 http://www.abc.com,因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回 404 错误。

history 模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致,如 http://www.abc.com/book/id。如果后端缺少对 /book/id 的路由处理,将返回 404 错误。vue-router官网里如此描述:“不过这种模式要玩好,还需要后台配置支持……所以呢,你要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。”

可以说,hash 模式和 history 模式都属于浏览器自身的特性,Vue-Router 只是利用了这两个特性(通过调用浏览器提供的接口)来实现前端路由。

五、computed和watch的区别

1、computed的是计算属性,依赖其他计算属性,它是有缓存的,当计算值发生变化时会发生改变

2、watch监听到值的变化就会执行

六、Vue组件之间的传值

1、父子组件间的传值

(1)父向子传值:子组件通过props方法接收数据

(2)子向父传值:$emit方法传递参数

2、非父子组件间的数据传递,兄弟组件传值

eventBus创建一个事件中心,相当于中转站,可以接受事件也可以传递事件,项目比较小时,建议使用。

七、Vuex是什么?怎么使用?那种情况使用?

1.Vuex:状态管理模式+库,只用来读取的状态store中,改变状态的方式是mutations,这是个同步的事物,异步逻辑封封装在action中

2、怎样使用:在main.js中引入store,注入。新建了一个目录store,...export。

3、什么情况使用:单页面应用中,组件之间的状态、音乐播放、登录状态、加入购物车。

八、keep-alive

1、keep-alive是vue提供的一个抽象组件,用来对组件进行缓存,从而节省性能,由于是抽象组件,所以在v页面渲染完毕后不会被渲染成另一个DOM元素。

<keep-alive>
  <loading></loading>
</keep-alive>

当组件在keep-alive内部切换时,组件的activated和deactivated这两个生命周期钩子函数会被执行,被包裹在keep-alive内的组件的状态将被保留

被keep-alive包裹的动态组件或者router-view会缓存不活动的实例,再次调用这些被缓存的实例会被再次复用,对于我们不是需要实时更新的页面来说,大大减少了性能上的消耗,不需要再次发送HTTP请求,但是存在一个问题,被keep-alive包裹的组件我们请求的数据不会再重新渲染页面,这就出现了例如我们在使用动态路由做匹配的话,页面只会保持第一次请求数据的渲染结果,所以需要我们在特定的情况下,强制刷新某些组件

(1)利用include、exclude属性

<keep-alive include="bookLists,bookLists">
    <router-view></router-view>
</keep-alive>
<keep-alive exlude="indexLists">
    <router-view></router-view>
</keep-alive>

include表明只有name名字为bookLists,bookLists的组件才会被缓存(注意是组件名称,不是路由的名字),其他组件不会被缓存,exclude除了name名为indexLists的组件不会被缓存,其他组件都会被缓存。

(2)利用meta属性

<keep-alive>
  <router-view if="this.$route.meta.keepAlive"></router-view>
  <!--这里是会被缓存的组件-->
</keep-alive>
<keep-alive>
  <router-view if="!this.$route.meta.keepAlive"></router-view>
    <!--这里是不会被缓存的组件-->
</keep-alive>
expoer default[
  {
    path: '/',
    name: 'home',
    components: Home,
    meta: {
      keepAlive: true //需要被缓存的组件
    }
  },
  {
    path: '/book',
    name: 'book',
    components: Book,
    meta: {
      keepAlive: false //不需要被缓存的组件
    }
  }
]

3、官方提出的解决方案响应路由参数的变化

4、利用beforeRouteEnter实现前进刷新,后退,缓存资料

5、第三方插件实现前进刷新,后退不缓存

九、跨域