zoukankan      html  css  js  c++  java
  • 前端中高级面试题 Jim

    • 原型
    
    构造函数 ,是一种特殊的方法。主要用来在创建对象时初始化对象。每个构造函数都有prototype(原型)属性
    
    每个函数都有prototype(原型)属性,这个属性是一个指针,指向一个对象,
    
    这个对象的用途是包含特定类型的所有实例共享的属性和方法,即这个原型对象是用来给实例共享属性和方法的。
    
    而每个实例内部都有一个指向原型对象的指针。
    
    • 闭包
    
    简单来说就是函数嵌套函数,内部函数引用来外部函数的变量,从而导致来垃圾回收机制没有生效,变量被保存来下来。
    
    也就是所谓的内存泄漏,然后由于内存泄漏又会导致你项目逐渐变得卡顿等等问题。因此要避免内存泄漏。
    
    • 原型链
    
    提到原型链就不得不提原型的继承,继承的完美实现方案是借助寄生组合继承,主要实现原理
    
    PersonB.prototype = Object.create(PersonA.prototype)实现来继承PersonA的原型
    
    当我们通过new关键字实例化的对象身上就有了PersonB自身的属性和方法,也有了PersonA的原型方法
    
    当实例化对象调用某个方法时会先在自身和原型上查找,然后是在_proto_上一层层查找,这种方式就是原型链。
    
    • vuex
    
    Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态
    
    并以相应的规则保证状态以一种可预测的方式发生变化。
    
    state:Vuex 使用单一状态树——是的,用一个对象就包含了全部的应用层级状态。
    
    mutation:更改 Vuex 的 store 中的状态的唯一方法是提交 mutation
    
    action: action 提交的是 mutation,而不是直接变更状态。action 可以包含任意异步操作。
    
    getter: 相当于Vue中的computed计算属性
    
    • vue-router
    
    Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌
    
    和和
    
    • 深拷贝浅拷贝
    
    深拷贝:
    
    通过利用JSON.parse(JSON.stringify(Object))来达到深拷贝的目的
    
    但是JSON深拷贝的缺点是undefined和function还有symbol类型是无法进行深拷贝的
    
    如有需要可以自己手动封装函数来达到目的
    
    浅拷贝:
    
    通过ES6新特性Object.assign()与扩展运算符来达到浅拷贝的目的
    
    • Vue通信
    
    第一种:props和e m i t 第 二 种 : 中 央 事 件 总 线 E v e n t B u s ( 基 本 不 用 ) 第 三 种 : v u e x ( 状 态 管 理 器 ) 第 四 种 : emit 第二种:中央事件总线 EventBus(基本不用) 第三种:vuex(状态管理器) 第四种:emit第二种:中央事件总线EventBus(基本不用)第三种:vuex(状态管理器)第四种:parent 和 $children
    
    当然还有其他办法,但是基本不常用
    
    • 你在工作终于到那些问题,解决方法是什么
    
    经常遇到的问题就是Cannot read property ‘prototype’ of undefined
    
    解决办法通过浏览器报错提示代码定位问题,解决问题
    
     
    
    Vue项目中遇到视图不更新,方法不执行,埋点不触发等问题
    
    一般解决方案查看浏览器报错,查看代码运行到那个阶段未之行结束,阅读源码以及相关文档等
    
    然后举出来最近开发的项目中遇到的算是两个比较大的问题。
    
    • webpack配置入口出口
    
    module.exports={undefined
    
    //入口文件的配置项
    
    entry:{},
    
    //出口文件的配置项
    
    output:{},
    
    //模块:例如解读CSS,图片如何转换,压缩
    
    module:{},
    
    //插件,用于生产模版和各项功能
    
    plugins:[],
    
    //配置webpack开发服务功能
    
    devServer:{}
    
    }
    
    简单描述了一下这几个属性是干什么的。
    
    • webpack3和webpack4区别
    
    1.mode
    
     
    
    webpack增加了一个mode配置,只有两种值development | production。对不同的环境他会启用不同的配置。
    
     
    
    2.CommonsChunkPlugin
    
     
    
    CommonChunksPlugin已经从webpack4中移除。
    
    可使用optimization.splitChunks进行模块划分(提取公用代码)。
    
    但是需要注意一个问题,默认配置只会对异步请求的模块进行提取拆分,如果要对entry进行拆分
    
    需要设置optimization.splitChunks.chunks = ‘all’。
    
     
    
    3.webpack4使用MiniCssExtractPlugin取代ExtractTextWebpackPlugin。
    
     
    
    4.代码分割。
    
     
    
    使用动态import,而不是用system.import或者require.ensure
    
     
    
    5.vue-loader。
    
     
    
    使用vue-loader插件为.vue文件中的各部分使用相对应的loader,比如css-loader等
    
     
    
    6.UglifyJsPlugin
    
     
    
    现在也不需要使用这个plugin了,只需要使用optimization.minimize为true就行,production mode下面自动为true
    
     
    
    optimization.minimizer可以配置你自己的压缩程序
    
    二面
    
    • 陈述输入URL回车后的过程
    
    1.读取缓存:
    
    搜索自身的 DNS 缓存。(如果 DNS 缓存中找到IP 地址就跳过了接下来查找 IP 地址步骤,直接访问该 IP 地址。)
    
    2.DNS 解析:将域名解析成 IP 地址
    
    3.TCP 连接:TCP 三次握手,简易描述三次握手
    
    客户端:服务端你在么?
    
    服务端:客户端我在,你要连接我么?
    
    客户端:是的服务端,我要链接。
    
    连接打通,可以开始请求来
    
    4.发送 HTTP 请求
    
    5.服务器处理请求并返回 HTTP 报文
    
    6.浏览器解析渲染页面
    
    7.断开连接:TCP 四次挥手
    
     
    
    关于第六步浏览器解析渲染页面又可以聊聊如果返回的是html页面
    
    根据 HTML 解析出 DOM 树
    
    根据 CSS 解析生成 CSS 规则树
    
    结合 DOM 树和 CSS 规则树,生成渲染树
    
    根据渲染树计算每一个节点的信息
    
    根据计算好的信息绘制页面
    
    • 陈述http
    
    基本概念:
    
     
    
    HTTP,全称为 HyperText Transfer Protocol,即为超文本传输协议。是互联网应用最为广泛的一种网络协议
    
    所有的 www 文件都必须遵守这个标准。
    
     
    
    http特性:
    
     
    
    HTTP 是无连接无状态的
    
    HTTP 一般构建于 TCP/IP 协议之上,默认端口号是 80
    
    HTTP 可以分为两个部分,即请求和响应。
    
     
    
    http请求:
    
     
    
    HTTP 定义了在与服务器交互的不同方式,最常用的方法有 4 种
    
    分别是 GET,POST,PUT, DELETE。URL 全称为资源描述符,可以这么认为:一个 URL 地址
    
    对应着一个网络上的资源,而 HTTP 中的 GET,POST,PUT,DELETE
    
    就对应着对这个资源的查询,修改,增添,删除4个操作。
    
     
    
    HTTP 请求由 3 个部分构成,分别是:状态行,请求头(Request Header),请求正文。
    
     
    
    HTTP 响应由 3 个部分构成,分别是:状态行,响应头(Response Header),响应正文。
    
     
    
    HTTP 响应中包含一个状态码,用来表示服务器对客户端响应的结果。
    
    状态码一般由3位构成:
    
     
    
    1xx : 表示请求已经接受了,继续处理。
    
    2xx : 表示请求已经处理掉了。
    
    3xx : 重定向。
    
    4xx : 一般表示客户请求无端有错误,法实现。
    
    5xx : 一般为服务器端的错误。
    
     
    
    比如常见的状态码:
    
     
    
    200 OK 客户端请求成功。
    
    301 Moved Permanently 请求永久重定向。
    
    302 Moved Temporarily 请求临时重定向。
    
    304 Not Modified 文件未修改,可以直接使用缓存的文件。
    
    400 Bad Request 由于客户端请求有语法错误,不能被服务器所理解。
    
    401 Unauthorized 请求未经授权,无法访问。
    
    403 Forbidden 服务器收到请求,但是拒绝提供服务。服务器通常会在响应正文中给出不提供服务的原因。
    
    404 Not Found 请求的资源不存在,比如输入了错误的URL。
    
    500 Internal Server Error 服务器发生不可预期的错误,导致无法完成客户端的请求。
    
    503 Service Unavailable 服务器当前不能够处理客户端的请求,在一段时间之后,服务器可能会恢复正常。
    
     
    
    大概还有一些关于hhtp请求和响应头信息的介绍。
    
    • 说说Vue原理
    
    Vue是采用数据劫持配合发布者-订阅者模式,通过Object.defineProperty来()来劫持各个属性的getter和setter
    
    在数据发生变化的时候,发布消息给依赖收集器,去通知观察者,做出对应的回调函数去更新视图。
    
     
    
    具体就是:
    
    MVVM作为绑定的入口,整合Observe,Compil和Watcher三者,通过Observe来监听model的变化
    
    通过Compil来解析编译模版指令,最终利用Watcher搭起Observe和Compil之前的通信桥梁
    
    从而达到数据变化 => 更新视图,视图交互变化(input) => 数据model变更的双向绑定效果。
    
    • Vue路由守卫有哪些,怎么设置,使用场景等
    
    常用的两个路由守卫:router.beforeEach 和 router.afterEach
    
     
    
    每个守卫方法接收三个参数:
    
     
    
    to: Route: 即将要进入的目标 路由对象
    
     
    
    from: Route: 当前导航正要离开的路由
    
     
    
    next: Function: 一定要调用该方法来 resolve 这个钩子。
    
     
    
    在项目中,一般在beforeEach这个钩子函数中进行路由跳转的一些信息判断。
    
    判断是否登录,是否拿到对应的路由权限等等。
    
     
    
    • 数组去重
    
    第一种:通过ES6新特性Set()
    
    例如:var arr = [1, 2, 3, 1, 2]; var newArr= […new Set(arr)]
    
     
    
    第二种:封装函数利用 {} 和【】
    
    function uniqueEasy(arr) {undefined
    
    if(!arr instanceof Array) {undefined
    
    throw Error(‘当前传入的不是数组’)
    
    }
    
    let list = []
    
    let obj = {}
    
    arr.forEach(item => {undefined
    
    if(!obj[item]) {undefined
    
    list.push(item)
    
    obj[item] = true
    
    }
    
    })
    
    return list
    
    }
    
    当然还有其他的方法,但本人项目中一般使用以上两种基本满足
    
    • Set,Map解构
    
    ES6 提供了新的数据结构 Set。
    
    它类似于数组,但是成员的值都是唯一的,没有重复的值。Set 本身是一个构造函数,用来生成 Set 数据结构。
    
     
    
    ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。
    
    • 对数组排序
    
    第一种方法利用sort方法
    
    第二种利用冒泡排序
    
    • 说一说js是什么语言
    
    js是一种运行在浏览器的脚本语言,这种语言主要的功能是可以制作出动态的页面的效果
    
    我们可以通过js+css+html布局来形成我们现在可以访问展示的页面
    
     
    
    js语言是弱语言类型, 因此我们在项目开发中当我们随意更该某个变量的数据类型后
    
    有可能会导致其他引用这个变量的方法中报错等等。
    
    • 原型
    
    JavaScript中的对象都有一个特殊的 prototype 内置属性,其实就是对其他对象的引用
    
    几乎所有的对象在创建时 prototype 属性都会被赋予一个非空的值,我们可以把这个属性当作一个备用的仓库
    
    当试图引用对象的属性时会出发get操作,第一步时检查对象本身是否有这个属性,如果有就使用它,没有就去原型中查找。一层层向上直到Object.prototype顶层
    
     
    
    基于原型扩展描述一下原型链,什么是原型链,原型的继承,ES5和ES6继承与不同点。
    
    • ES6新特性
    
    1.ES6引入来严格模式
    
    变量必须声明后在使用
    
    函数的参数不能有同名属性, 否则报错
    
    不能使用with语句 (说实话我基本没用过)
    
    不能对只读属性赋值, 否则报错
    
    不能使用前缀0表示八进制数,否则报错 (说实话我基本没用过)
    
    不能删除不可删除的数据, 否则报错
    
    不能删除变量delete prop, 会报错, 只能删除属性delete global[prop]
    
    eval不会在它的外层作用域引入变量
    
    eval和arguments不能被重新赋值
    
    arguments不会自动反映函数参数的变化
    
    不能使用arguments.caller (说实话我基本没用过)
    
    不能使用arguments.callee (说实话我基本没用过)
    
    禁止this指向全局对象
    
    不能使用fn.caller和fn.arguments获取函数调用的堆栈 (说实话我基本没用过)
    
    增加了保留字(比如protected、static和interface)
    
     
    
    2.关于let和const新增的变量声明
    
     
    
    3.变量的解构赋值
    
     
    
    4.字符串的扩展
    
    includes():返回布尔值,表示是否找到了参数字符串。
    
    startsWith():返回布尔值,表示参数字符串是否在原字符串的头部。
    
    endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部。
    
    5.数值的扩展
    
    Number.isFinite()用来检查一个数值是否为有限的(finite)。
    
    Number.isNaN()用来检查一个值是否为NaN。
    
    6.函数的扩展
    
    函数参数指定默认值
    
    7.数组的扩展
    
    扩展运算符
    
    8.对象的扩展
    
    对象的解构
    
    9.新增symbol数据类型
    
     
    
    10.Set 和 Map 数据结构
    
    ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。Set 本身是一个构造函数,用来生成 Set 数据结构。
    
     
    
    Map它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。
    
    1
    
    11.Proxy
    
    Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问
    
    都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。
    
    Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,可以译为“代理器”。
    
    Vue3.0使用了proxy
    
    12.Promise
    
    Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。
    
    特点是:
    
    对象的状态不受外界影响。
    
    一旦状态改变,就不会再变,任何时候都可以得到这个结果。
    
    13.async 函数
    
    async函数对 Generator 函数的区别:
    
    (1)内置执行器。
    
    Generator 函数的执行必须靠执行器,而async函数自带执行器。也就是说,async函数的执行,与普通函数一模一样,只要一行。
    
    (2)更好的语义。
    
    async和await,比起星号和yield,语义更清楚了。async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果。
    
    (3)正常情况下,await命令后面是一个 Promise 对象。如果不是,会被转成一个立即resolve的 Promise 对象。
    
    (4)返回值是 Promise。
    
    async函数的返回值是 Promise 对象,这比 Generator 函数的返回值是 Iterator 对象方便多了。你可以用then方法指定下一步的操作。
    
    14.Class
    
    class跟let、const一样:不存在变量提升、不能重复声明…
    
    ES6 的class可以看作只是一个语法糖,它的绝大部分功能
    
    ES5 都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
    
    15.Module
    
    ES6 的模块自动采用严格模式,不管你有没有在模块头部加上"use strict";。
    
    import和export命令以及export和export default的区别
    
    • Css3新特性
    
    1.过渡 transition
    
    2.动画 animation
    
    3.形状转换 transform
    
    4.阴影 box-shadow
    
    5.滤镜 Filter
    
    6.颜色 rgba
    
    7.栅格布局 gird
    
    8.弹性布局 flex
    
    等等还多…
    
    • 说一说你用过的UI框架
    
    Element-UI Vant
    
    • 说一说什么是跨域,怎么解决
    
    因为浏览器出于安全考虑,有同源策略。也就是说,如果协议、域名或者端口有一个不同就是跨域,Ajax 请求会失败。
    
    为来防止CSRF攻击
    
    1.JSONP
    
    JSONP 的原理很简单,就是利用
    
    JSONP 使用简单且兼容性不错,但是只限于 get 请求。
    
    2.CORS
    
    CORS 需要浏览器和后端同时支持。IE 8 和 9 需要通过 XDomainRequest 来实现。
    
    3.document.domain
    
    该方式只能用于二级域名相同的情况下,比如 a.test.com 和 b.test.com 适用于该方式。
    
     
    
    只需要给页面添加 document.domain = 'test.com' 表示二级域名都相同就可以实现跨域
    
    1
    
    4.webpack配置proxyTable设置开发环境跨域
    
    5.nginx代理跨域
    
    6.iframe跨域
    
    7.postMessage
    
    这种方式通常用于获取嵌入页面中的第三方页面数据。一个页面发送消息,另一个页面判断来源并接收消息
    
    • 说一说前端性能优化方案
    
    三个方面来说明前端性能优化
    
    一:webapck优化与开启gzip压缩
    
    1.babel-loader用 include 或 exclude 来帮我们避免不必要的转译,不转译node_moudules中的js文件
    
    其次在缓存当前转译的js文件,设置loader: ‘babel-loader?cacheDirectory=true’
    
    2.文件采用按需加载等等
    
    3.具体的做法非常简单,只需要你在你的 request headers 中加上这么一句:
    
    accept-encoding:gzip
    
    4.图片优化,采用svg图片或者字体图标
    
    5.浏览器缓存机制,它又分为强缓存和协商缓存
    
    二:本地存储——从 Cookie 到 Web Storage、IndexedDB
    
    说明一下SessionStorage和localStorage还有cookie的区别和优缺点
    
    三:代码优化
    
    1.事件代理
    
    2.事件的节流和防抖
    
    3.页面的回流和重绘
    
    4.EventLoop事件循环机制
    
    5.代码优化等等
    
     
    
    • 说一说SessionStorage和localStorage还有cookie
    
    共同点:都是保存在浏览器端、且同源的
    
    不同点:
    
    1.cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递。
    
    cookie数据还有路径(path)的概念,可以限制cookie只属于某个路径下
    
    sessionStorage和localStorage不会自动把数据发送给服务器,仅在本地保存。
    
    2.存储大小限制也不同,cookie数据不能超过4K,sessionStorage和localStorage可以达到5M
    
    3.sessionStorage:仅在当前浏览器窗口关闭之前有效;
    
    localStorage:始终有效,窗口或浏览器关闭也一直保存,本地存储,因此用作持久数据;
    
    cookie:只在设置的cookie过期时间之前有效,即使窗口关闭或浏览器关闭
    
    4.作用域不同
    
    sessionStorage:不在不同的浏览器窗口中共享,即使是同一个页面;
    
    localstorage:在所有同源窗口中都是共享的;也就是说只要浏览器不关闭,数据仍然存在
    
    cookie: 也是在所有同源窗口中都是共享的.也就是说只要浏览器不关闭,数据仍然存在
    
    • 说一说你用过的css布局
    
    gird布局,layout布局,flex布局,双飞翼,圣杯布局等
    
    • Promise是什么,解决了什么,之前怎么实现的
    
    Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。
    
    解决来之前在请求中回调请求产生的回调地狱,使得现在的代码更加合理更加优雅,也更加容易定位查找问题。
    
    • 说说浏览器缓存
    
    缓存可以减少网络 IO 消耗,提高访问速度。浏览器缓存是一种操作简单、效果显著的前端性能优化手段
    
    很多时候,大家倾向于将浏览器缓存简单地理解为“HTTP 缓存”。
    
    但事实上,浏览器缓存机制有四个方面,它们按照获取资源时请求的优先级依次排列如下:
    
     
    
    Memory Cache
    
    Service Worker Cache
    
    HTTP Cache
    
    Push Cache
    
     
    
    缓存它又分为强缓存和协商缓存。优先级较高的是强缓存,在命中强缓存失败的情况下,才会走协商缓存
    
    实现强缓存,过去我们一直用 expires。
    
    当服务器返回响应时,在 Response Headers 中将过期时间写入 expires 字段,现在一般使用Cache-Control 两者同时出现使用Cache-Control
    
     
    
    协商缓存,Last-Modified 是一个时间戳,如果我们启用了协商缓存,它会在首次请求时随着 Response Headers 返回:每次请求去判断这个时间戳是否发生变化。
    
    从而去决定你是304读取缓存还是给你返回最新的数据
    
    1
    
    2
    
    使用Vuex只需执行 Vue.use(Vuex),并在Vue的配置中传入一个store对象的示例,store是如何实现注入的?state内部是如何实现支持模块配置和模块嵌套的?在执行dispatch触发action(commit同理)的时候,只需传入(type, payload),action执行函数中第一个参数store从哪里获取的?如何区分state是外部直接修改,还是通过mutation方法修改的?带着这些疑问,让我们先从什么是vuex开始——
    
    一、vuex是什么?
    
    Vuex是专门为Vue服务,用于管理页面的数据状态、提供统一数据操作的状态管理系统,相当于数据库mongoDB,MySQL等,只不过它的数据是存储在内存中,页面刷新即消失。
    
    二、vue和vuex关系
    
     
    
    看一下这个vue响应式的例子,vue中的data 、methods、computed,可以实现响应式。视图通过点击事件,触发methods中的increment方法,可以更改state中count的值,一旦count值发生变化,computed中的函数能够把getCount更新到视图。
    
     
    
    那么vuex又和vue这个响应式的例子有什么关系呢?视图通过点击事件,触发mutations中方法,可以更改state中的数据,一旦state数据发生更改,getters把数据反映到视图。那么actions,可以理解处理异步,而单纯多加的一层。既然提到了mutions actions这时候 就不得不提commit,dispatch这两个有什么作用呢?在vue例子中,通过click事件,触发methods中的方法。当存在异步时,而在vuex中需要dispatch来触发actions中的方法,actions中的commit可以触发mutations中的方法。同步,则直接在组件中commit触发vuex中mutations中的方法。
    
     
    
    三、vuex实现
    
    我们看下vuex中能像vue中实现改变状态,更新视图的功能
    
    Store/index.js
    
     
    
    App.vue
    
     
    
    四、源码分析
    
    store注入组件install方法vuex是通过vue插件机制将组件注入的
    
    首先使用vuex,需要安装插件:
    
     
    
    可见,store注入 vue的实例组件的方式,是通过vue的 mixin机制,借助vue组件的生命周期 钩子 beforeCreate 完成的。即 每个vue组件实例化过程中,会在 beforeCreate 钩子前调用 vuexInit 方法。
    
    vuex中的数据双向绑定
    
     
    
    getters实现
    
     
    
    从上面源码,我们可以看出Vuex的state状态是响应式,是借助vue的data是响应式,将state存入vue实例组件的data中;Vuex的getters则是借助vue的计算属性computed实现数据实时监听。
    
    mutations实现
    
     
    
    actions实现
    
     
    
    五、小结
    
    Vuex是通过全局注入store对象,来实现组件间的状态共享。在大型复杂的项目中(多级组件嵌套),需要实现一个组件更改某个数据,多个组件自动获取更改后的数据进行业务逻辑处理,这时候使用vuex比较合适。假如只是多个组件间传递数据,使用vuex未免有点大材小用,其实只用使用组件间常用的通信方法即可。
    
    前言
    
    最近看到一些人在问单页面和多页面应用的区别。所以也就输出这一篇短文希望可以给你一个整体的认识。
    
    这里也会大体介绍单页应用实现的核心 —— 前端路由。
    
    单页应用 VS 多页应用
    
     
    
    对比图
    
     
    
    单页应用(SinglePage Application,SPA)
    
    指只有一个主页面的应用,一开始只需加载一次 js,css 等相关资源。所有的内容都包含在主页面,对每一个功能模块组件化。单页应用跳转,就是切换相关组件,仅刷新局部资源。
    
    多页应用(MultiPage Application,MPA)
    
    指有多个独立的页面的应用,每个页面必须重复加载 js,css 等相关资源。多页应用跳转,需要整页资源刷新。
    
    两者对比表格:
    
     
    
    单页应用实现核心:前端路由
    
    前端路由的核心:改变视图的同时不会向后端发出请求。
    
    这里我讲讲 vue-router 路由的两种模式:hash&history
    
    1、hash 模式
    
    hash 模式背后的原理是 onhashchange 事件。
    
     
    
    window.addEventListener( hashchange ,function(e) {
    
     console.log(e.oldURL);
    
    1
    
     console.log(e.newURL)
    
    1
    
    },false);
    
    通过 window.location.hash 属性获取和设置 hash 值。
    
    由于 hash 发生变化的 url 都会被浏览器记录下来,所以浏览器的前进后退可以使用,尽管浏览器没有请求服务器,但是页面状态和 url 关联起来。后来人们称其为前端路由,成为单页应用标配。
    
    hash 模式的特点在于 hash 出现在 url 中,但是不会被包括在 HTTP 请求中,对后端没有影响,不会重新加载页面。
    
    2、history 模式
    
    利用了 HTML5 History Interface 中新增的 pushState() 和 replaceState(),它们提供了对历史记录进行修改的功能。
    
    相关的 API:
    
    history.pushState()
    
    history.pushState(stateObj, title, url);
    
    state:一个与指定网址相关的状态对象, popstate 事件触发时,该对象会传入回调函数。如果不需要可填 null。
    
    title:新页面的标题,但是所有浏览器目前都忽略这个值,可填 null。
    
    url:新的网址,必须与当前页面处在同一个域。浏览器的地址栏将显示这个网址。
    
    例如:history.pushState( new , new , new.html );
    
    添加上面这个新记录后,浏览器地址栏立刻显示 ~/new.html,但并不会跳转到 new.html,它只是成为 history 中的最新记录。pushState 方法不会触发页面刷新,只是 history 对象变化,地址栏会变。
    
    history.replaceState()
    
    history.replaceState(stateObj, title, url);
    
    参数同 pushState() 一样。
    
    调用该方法,会修改当前的 history 对象记录, history.length 的长度不会改变
    
    history.state
    
    当前 URL 下对应的状态信息。如果当前 URL 不是通过 pushState 或者 replaceState 产生的,那么 history.state是 null。当需要 state 和 URL 同步时可以使用 replaceState() 使之同步。
    
    popstate 事件
    
    同一个文档的 history 对象出现变化时,就会触发 popstate 事件。
    
    不同的浏览器在加载页面时处理 popstate 事件的形式存在差异。页面加载时 Chrome 和 Safari 通常会触发 popstate 事件,但 Firefox 则不会。
    
    注意:调用 history.pushState() 或者 history.replaceState() 不会触发 popstate 事件。 popstate 事件只会在浏览器某些行为下触发, 比如点击后退、前进按钮(或者调用 history.back()、history.forward()、history.go()方法)。
    
    1、什么是发布/订阅模式、观察者模式?
    
    观察者模式是观察者和被观察者之间的通讯,发布/订阅模式是“一对多”的依赖关系
    
    2、如何理解Vue2响应式原理?
    
    (1)利用Object.defineProperty重新定义一遍目标对象,完成对目标对象的劫持,在属性值变化后即触发set方法 后通知订阅者,告诉该对象的某个属性值发生了变化。
    
    (2)解析器Compile解析模板中的指令,收集指令所依赖的方法和数据,等待数据变化然后进行渲染。
    
    (3)Watcher在收到属性值发生变化后,根据解析器Compile提供的指令进行视图渲染。
    
    3、vuex的工作原理是什么?
    
    每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state)
    
    多个视图依赖于同一状态。
    
    来自不同视图的行为需要变更同一状态。
    
    vuex 类似Redux 的状态管理器, 用来管理Vue的所有组件状态
    
    采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
    
    4、谈一谈nextTick 的原理以及运行机制?
    
     
    
    vue用异步队列的方式来控制DOM更新和nextTick回调先后执行
    
    microtask因为其高优先级特性,能确保队列中的微任务在一次事件循环前被执行完毕
    
    因为浏览器和移动端兼容问题,vue不得不做了microtask向macrotask的兼容(降级)方案
    
    它可以在DOM更新完毕之后执行一个回调,一般来说,在对于MVVM框架结构的技术栈是不推荐操作DOM的,但是很多情况下可能会需要操作DOM,特别是一些charts插件等所以nextTick就出现了,确保我们所操作的DOM是更新之后的
    
    5、聊聊keep-alive 的实现原理和缓存策略
    
    包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们,是一个抽象组件:它自身不会渲染一个 DOM 元素,也不会出现在父组件链中。当组件在 内被切换,它的 activated 和 deactivated 这两个生命周期钩子函数将会被对应执行。
    
    获取 keep-alive 包裹着的第一个子组件对象及其组件名
    
    根据设定的 include/exclude(如果有)进行条件匹配,决定是否缓存。不匹配,直接返回组件实例
    
    根据组件 ID 和 tag 生成缓存 Key,并在缓存对象中查找是否已缓存过该组件实例。如果存在,直接取出缓存值并更新该 key 在 this.keys 中的位置(更新 key 的位置是实现 LRU 置换策略的关键)
    
    在 this.cache 对象中存储该组件实例并保存 key 值,之后检查缓存的实例数量是否超过 max 的设置值,超过则根据 LRU 置换策略删除最近最久未使用的实例(即是下标为 0 的那个 key)
    
    最后组件实例的 keepAlive 属性设置为 true,这个在渲染和执行被包裹组件的钩子函数会用到,
    
    6、你阅读过axios的 源码吗 ?Axios主要有哪些特性?
    
    1、在浏览器中发送 XMLHttpRequests 请求;
    
    2、在 node.js 中发送 http请求;
    
    3、基于 promise 的 HTTP 库,支持promise所有的API
    
    4、拦截请求和响应;(修改请求数据,只能用在’PUT’,'POST’和’PATCH’这几个请求方法)
    
    5、转换请求和响应数据,响应回来的内容自动转换;
    
    6、自动转换 JSON 数据;
    
    7、客户端支持保护安全免受 XSRF 攻击;
    
    7、Vuex与Redux比较,他们的相同点以及不同点?
    
    vuex的同步异步方式不一样,
    
    view——>commit——>mutations——>state变化——>view变化(同步操作)
    
    view——>dispatch——>actions——>mutations—>state变化—>view变化(异步操作)
    
    redux的同步异步方式一样。
    
    view—>dispatch—>actions—>reducer——>state变化——>view变化(同步异步一样)
    
    2.用过redux的知道redux需要增加订阅函数,也就是我们的 store.subscribe(render),但是vue是双向绑定,不需要这步操作
    
    3.vuex只能和vue配合,vuex把redux里面的reducer部分改成了mutations,但是reducer里面需要分情况,要么switch,要么if else,但是vuex里面的mutations,里面你直接写方法就完事了。
    
    4.vuex里面有个module
    
    8、在vue 中 如何 通过createElement创建虚拟dom?
    
    在Vue的底层实现上,Vue将模板编译成虚拟DOM渲染函数。结合Vue自带的响应系统,在状态改变时,Vue能够智能地计算出重新渲染组件的最小代价并应到DOM操作上。
    
    createElement 默认暴露给用户传递3个参数,{String | Object | Function} ,createElement 最终是通过调用new VNode 来创建虚拟dom,函数在调用new VNode之前处理了很多限制的情况,比如:data不能是响应式数据,tag是否为空等等
    
    9、如何通过vue, vue-router, vuex进行权限控制?
    
           https://www.cnblogs.com/zhengrunlin/p/8981017.html
    
    10、vue的数据驱动原理及如何实现?
    
      vue实现对数据的双向绑定,通过对数据劫持结合发布者-订阅者模式实现的。
    
       https://segmentfault.com/a/1190000013276124
  • 相关阅读:
    判断一个序列是否是另一个序列的前缀
    Ant-打增量包
    cas-单点登录-应用说明
    firebug离线安装方法-拖入法
    oracle-获取数据库中所有表的注释 comments
    跨浏览器的placeholder – 原生JS版
    birt IE8 IE9 兼容问题
    websphere部署--web应用-以自己的项目为例
    JSP-页面跳转大全
    Oracle中Union与Union All的区别(适用多个数据库)
  • 原文地址:https://www.cnblogs.com/huoshengmiao/p/15578361.html
Copyright © 2011-2022 走看看