面试题-1

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

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

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

(1)利用include、exclude属性


    


    

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

(2)利用meta属性


  
  


  
    
expoer default[
  {
    path: '/',
    name: 'home',
    components: Home,
    meta: {
      keepAlive: true //需要被缓存的组件
    }
  },
  {
    path: '/book',
    name: 'book',
    components: Book,
    meta: {
      keepAlive: false //不需要被缓存的组件
    }
  }
]

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

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

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

九、跨域

1、what:浏览器不能执行其他网站的脚本,它是浏览器的同源策略造成的,是浏览器施加的安全限制。

同源策略:域名,协议,端口均相同。

2、解决跨域

(1)JSONP

原理:利用script标签没有跨域限制的漏洞,网页可以得到从其他来源动态产生的JSON数据,JSONP请求一定要对方的服务器做支持才可以

优点:简单兼容性好,用于解决浏览器的跨域跨域数据访问的问题

确定:只支持GET请求,不支持其他POST请求,不安全可能会造成XXS攻击。

(2)代理:

例如:www.123.com/index.html需要调用www.456.com/server.php,可以写一个接口www.123.com/server.php,找个接口在后端去调用www.456.com/server.php并拿到返回值,然后在返回给index.html,这就是一个代理的模式,相当于绕过了浏览器端,自然就不存在跨域问题了。

(3)php端修改header

在php接口脚本中加入以下两句即可:

header('Access-Control-Allow-Origin:*');//允许所有来源访问

header('Access-Control-Allow-Method:POST,GET');//允许访问的方式

十、防止重复提交表单的方法

1、通过javascript屏蔽提交按钮(不推荐)

通过js代码,当用户点击提交按钮后,屏蔽提交按钮使用户无法点击提交按钮或者点击无效,从而实现防止表单重复提交。

缺点:js代码很容易被绕过,比如重新刷新页面,或使用postman等工具绕过前段页面仍然能够重复提交代码,因此不推荐使用。

2、给数据库增加唯一约束键(简单粗暴)

在用户建表的时候在ID字段添加主键约束,用户名、电话、邮箱等增加唯一性约束,确保数据库只可以增加一条数据。

优点:有效避免数据库插入相同数据

缺点:无法避免恶意用户重复提交表单(攻击网站),服务器大量执行sql插入语句,增加服务器和数据库负荷。

3、利用session防止表单重复提交(推荐)

实现原理:服务器返回表单页面时,会生成一个subToken存于session中,并把subToken传递给表单页面。当提交表单时会带上subToken,服务器拦截器Interceptor会拦截该请求,拦截器判断session中保存的subToken与表单提交的subToken是否一致,如果不一致或session的subToken为空或表单未携带subToken则不通过。

首次提交时,seecion的subToken与表单携带的subToken一致走正常流程,然后拦截器会删除session中保存的subToken。再次提交表单时,由于session的subToken为空则不通过。从而防止了表单的重复提交。

4、利用APO自定义切入实现

你可能感兴趣的:(面试题-1)