面试题准备,边背边敲

79 阅读6分钟

CSS 相关

圣杯和双飞翼

都是用float实现布局的,都是两边宽度固定,中间自适应的三栏布局,中间栏始终放在最前面优先渲染。

  1. 圣杯:左中右三个盒子在同一个盒子中,中间盒子设置左右padding值留给左右两个盒子,左右两个盒子通过position:relative设置left和right属性,以便不遮挡中间的盒子。

    • 优点:少一层dom;
    • 缺点:当页面拉伸或者中间的盒子宽度小于左边盒子宽度时,会布局混乱。
  2. 双飞翼:左中右三个盒子也在同一个盒子中,但中间盒子需要再加一个子盒子,设置子盒子的左右margin值给左右两边的盒子留出位置。

    • 优点:不会因为拉伸等情况造成布局问题;
    • 缺点:多一层dom.
元素的居中方式 (问了)

/* margin 居中对齐 */

margin0 auto;

/* flex 水平垂直居中 */

display:flex;

justify-content:center;

align-item:center;

/* position 水平垂直居中 */

Position:absolute;

left:50%;

top:50%;

transform:translate(-50%,-50%);


JS 相关

数据类型 (问了)
  • 基本数据类型:string,boolean,number,null,undefined,symbol

  • 引用数据类型:object,function等

  • symbol 表示独一无二的值,最大的用法就是定义对象的唯一属性名。

es6的5种去重方式 (问了)
  • 利用set和array.from()去重

let arr = [1,1,2,3,4,2,3,5,undefined];

let newArr = Array.from(new Set(arr));

console.log(newArr);

  • 利用Set和扩展运算符去重

let arr = [1,1,2,3,4,2,3,5,undefined];

let newArr = [...new Set(arr)];

console.log(newArr);

  • 利用单层循环和indexOf去重

let arr = [1,1,2,3,4,2,3,5,undefined];

let newArr = [];

for(let i=0;i<arr.length;i++){

if(newArr.indexOf(arr[i])===-1){

newArr.push(arr[i])

}

}

console.log(newArr);

  • 利用单层循环和includes去重

let arr = [1,1,2,3,4,2,3,5,undefined];

let newArr = [];

for(let i=0;i<arr.length;i++){

if(!newArr.includes(arr[i])){

newArr.push(arr[i])

}

}

console.log(newArr);

  • 利用数组的filter去重

let arr = [1,1,2,3,4,2,3,5,undefined];

let newArr = arr.filter(item,index=>{

return arr.indexOf(item,0) === index;

})

console.log(newArr)

闭包

一个函数的返回值是一个函数,如果这个返回的函数调用了父函数内部的变量,并且被外部调用了,就形成了闭包。

一般应用在返回值,函数赋值,自执行函数等。

promise,promise.all,promise.race (问了)

promise 是es6的特性,通常是异步的一种解决方案。

promise 有三种状态:

  • pending:初始化状态

  • fulfilled:已完成状态

  • rejected:已拒绝状态

promise 有两个过程:

  • pending => resolved (已完成)

  • pending => rejected (已拒绝)

只要promise一旦开始,无论怎么样,状态都无法被改变。

优点:

  • promise 将异步操作已同步的方式展示出来,避免的层层嵌套,更清晰,代码更优雅;

  • promise 对象提供统一的接口,使控制异步操作更容易。

缺点:

  • 无法取消promise,一旦开始立即执行,中途无法取消;

  • 如果不设置回调函数,结果无法被抛出;

  • 当处于pending阶段时,无法知道目前正处于哪一个阶段,直到结束。

promise.all 将多个promise实例组合成一个新的实例,成功的时候返回一个成功的数组,失败的时候返回最先被返回的rejected的值。

promise.race 有点赛跑的意思,也就是哪一个最先完成就返回哪一个,不管是成功,还是失败。


Vue 相关

为什么data是一个函数

组件中的data写成一个函数,以返回值的形式定义,这样每复用一次组件,就行形成一个新的data,而写成一个对象的话,那就共用同一个data,就会造成一个变了所有的都会变的结果。

vue 生命周期 (问了)
  • create阶段:beforeCreate:vue实例创建之前,create:vue实例创建完成,data中有值,未挂载,可以将数据请求放在这个阶段;

  • mount阶段:beforeMount:dom 挂载之前,mounted:dom 挂载完成,可以操作dom;

  • update阶段:当data数据变化时,会出发beforeUpdate和updated;

  • destroy阶段:当vue实例被销毁的时候发生,beforeDestroy,销毁之前,可以清除定时器或者一些需要手动销毁的方法,destroyed:vue实例已经被销毁了。

组件之间的传值 (问了)
  • 父传子:父组件给子组件传的值,子组件通过props接收;

  • 子传父:子组件用on或者on或者emit给父组件传值,父组件用@方法名来接收;

  • 亲兄弟传值:通过公共的父组件,用父子,子父的方式进行传值;

  • 非亲兄弟:创建一个中间组件,用emitemit,on,进行传值和接受;

  • 祖孙传值:provide/inject

v-if 和 v-show (问了)

v-if 通过控制dom实现显示和隐藏,所以会不停的销毁和创建,v-show 通过控制css中的display完成显示和隐藏的效果,只编译一次。通常日常判断显示和隐藏用v-show,一般带权限的判断用v-if多一些。

v-if 和 v-for 为什么不建议一起用 (问了)

v-for 的优先级高于v-if,如果一起用的话,每一次遍历都会执行一次v-if,比较消耗性能,可以在v-for的外层加一层template,在template上使用v-if,也可以在computed中完成v-if的判断,将其替换掉。

v-for中key的作用 (问了)

key的作用是在diff算法执行时能够更快的找到对应的节点,提高diff的效率,更高效的更新虚拟dom。

key 应该是唯一的,如果不设置key,则值就是undefined,或者key设置成相同的,vue会认为两个节点是同一个,会频繁的更新元素,影响性能。

通常情况下,用唯一的id设置key,不建议使用index下标,如果使用index,当删除或者新增了元素,那所有的key值都会发生变化。

怎样理解Vue的数据单向流

在Vue中,数据总是从父组件传到子组件的,子组件没有权利修改父组件传过来的值,只能通过调用父组件的方法来修改原始数据,这样可以防止因为子组件误操作改变父组件的状态,从而使数据流向难以理解,如果一定要修改父组件传过来的props的值,可以在data中重新定义一个变量,将props的值作为初始值,再用$emit通知父组件对原数据进行修改。

watch和computed的区别
  • watch:属性监听,第一个参数是最新的值,第二个参数是改变之前的值,watch不支持缓存,当监听的属性值发生改变时,它就会触发相应的操作,watch支持异步操作。

  • computed:计算属性,支持缓存,当依赖发生改变的时候,才会重新计算,仅支持同步操作。当返回值是函数的时候,默认进行的是get方法,还有一个set,当数据变化的时候,调用set方法。

  • 当一个属性受多个属性影响时,一般写在computed中,比如购物车结算,当一个数据影响多个数据的时候,一般用watch,比如搜索


Vue 的双向绑定原理 (问了)

整体思路:数据劫持+观察者模式

使用 Object.defineProperty() 的方法对已存在的属性劫持。当页面使用对应的属性时,每个属性都会有属于自己的dep属性,存放在它所依赖的watcher中,当属性变化时就会通知对应的watcher去更新。

Vuex (问了)

Vuex 是专为vue设计的状态管理模式+库,每一个vuex的核心就是store(仓库);

Vuex 是响应式的,当组件从store中读取状态的时候,如果状态更新了,那相应的组件也会得到更新;

Vuex 的几大状态:

  • state:定义应用中的状态数据;

  • getter:store 中的 getter,相当于store中的计算属性,getter的返回值会根据它的依赖被储存起来,只有当发生改变的时候才会更新;

  • mutation:是store中唯一可以更改状态的属性,mutation中的操作必须是同步的。

  • action:相当于mutation,但只能用来提交mutation,不能直接更改的状态,可以进行所有的异步操作。

  • module:可以将一个store分割成多个store,每个store都可以有自己的一套state、getter、mutation、action。

虚拟DOM

在浏览器中频繁的操作dom,会造成一定的性能问题,这也是虚拟dom出现的原因,虚拟dom的本质就是用原生js对象去描述真实dom节点,是对真实domd的抽象。

优点:保证了性能下限,不用手动操作dom,更方便跨平台操作。

缺点:无法进行极致优化。

v-model 的原理

v-model只是一个语法糖而已,它的本质就是为不同的输入元素用不同的property并抛出不同的事件。

  • text和textarea 使用 value property 和 input 事件;

  • checkbox和radio 使用 checked property 和 change 事件;

  • select 使用value作为prop ,change 作为事件;

Vue 事件绑定原理

原生事件绑定通过addeventlistenter绑定给真实元素的,组件是通过自定义$on实现的。

说出至少vue 3个常用事件修饰符
  • :stop 阻止点击事件冒泡

  • :prevent 阻止默认事件

  • :once 只执行一次

  • :self 只在元素本身触发

父子组件生命周期顺序

父beforeCreate => 父created => 父beforeMount => 子beforeCreate => 子created => 子beforeMount => 子mounted => 父mounted

更新:父beforeUpdate => 子beforeUpdate => 子updated => 父updated

路由的两种模式 (问了)
  • hash模式
  • history模式
vue项目性能优化 (问了)
  1. 编码阶段
    • 尽量减少data中的数据,data中的数据都会增加getter和setter,会收集对应的watcher
    • v-if和v-for不能连用
    • 如果需要使用v-for给每项元素绑定事件时使用事件代理
    • SPA 页面采用keep-alive缓存组件
    • 在更多的情况下,使用v-if替代v-show
    • key保证唯一
    • 使用路由懒加载、异步组件
    • 防抖、节流
    • 第三方模块按需导入
    • 长列表滚动到可视区域动态加载
    • 图片懒加载
  2. SEO优化
    • 预渲染
    • 服务端渲染SSR
  3. 打包优化
    • 压缩代码
    • Tree Shaking/Scope Hoisting
    • 使用cdn加载第三方模块
    • 多线程打包happypack
    • splitChunks抽离公共文件
    • sourceMap优化
  4. 用户体验
    • 骨架屏
    • PWA
    • 还可以使用缓存(客户端缓存、服务端缓存)优化、服务端开启gzip压缩等。