面试题总结

179 阅读10分钟

vue 内置指令

v-bind: 响应数据并更新DOM特性

v-on: 用于监听 DOM 事件

v-model: 数据双向绑定

v-show:条件渲染指令

v-if: 条件渲染指令

v-else: 条件渲染指令,必须跟 v-if 成对使用

v-for:循环指令

v-text: 更新元素的 textComtent(文本内容)

v-html:更新元素的 innerHTML

v-pre:不需要表达式,跳过这个元素以及子元素的编译过程

v-clock:不需要表达式,这个指令保持在元素上直到关联实例结束编译

v-once:不需要表达式,只渲染元素或组件一次,随后的渲染,组件/元素以及下面的子元素都当成静态页面不在渲染

vue生命周期的八个阶段

1,beforeCreate:在 new 一个 vue 实例后,datamethods 中的数据还没有初始化。不能在这个阶段使用 data 中的数据和 methods 中的方法

2,create:datamethods 都已经被初始化好了,如果需要调用 methods 中的方法,或 data 中的数据,最早可以在这个阶段进行调用

3,beforeMount:页面还没有挂载,此时页面还是旧的

4,mounted:vue 实例化已经完成,如果想要通过插件操作页面上的 DOM 节点,最早可以在这个节点中执行, 此时虚拟 DOM 挂载完成

5,beforeUpdate:执行这个钩子时,页面中显示的数据还是旧的,data中的数据是更新后的,页面还没有和最新的数据同步

6,updated:页面显示的数据和data中的数据已经同步,都是最新的

7,beforeDestory:vue 实例从运行阶段进入到销毁阶段,这时所有的 datamethods指令过滤器 都是出于可用状态,还没有被真正销毁

8,dastroyed:这个时候所有的 datamethods指令过滤器 都是出于不可用状态,组件已经被销毁了

父子组件生命周期执行顺序

1,加载渲染过程

  • 父组件执行到 beforeMount 的时候开始执行子组件的生命周期到 mounted ,然后开始执行父组件的 mounted

2,子组件更新过程

  • 父组件 beforeUpdate 先执行,然后执行子组件的 beforeupdate , updated , 最后在执行父组件的 updated

3,父组件更新过程

  • 父组件 beforeUpdateupdated

4,销毁过程

  • 父组件 beforeDestroy 先执行,然后执行子组件的 beforeDestroydestroyed ,最后在执行父组件的 destroyed

es6常用的属性

1,let 和 count:let 定义变量,count:定义常量;两者都不能进行变量提升

2,模板字符串

3,增强函数:函数传参是,可以给定默认值

4,扩展运算符

5,解构赋值

6,set,map

7,数组,将伪数组转换为数组:

  • Array.from(arr,(ele) => {}) ,接收两个参数,一个是伪数组,一个是匿名函数,用来对数组的每一项进行处理
  • Array.of() 将传入的参数转换为一个数组
  • Array.find(()=>{}) : 返回数组中满足条件的第一个元素的值,若不满足这返回undefined

8,迭代器,生成器

9,promise

10,async await

11,模块化:export import

浅拷贝和深拷贝

1,深拷贝的方式:

  • 递归调用
  • JSON.stringify + JSON.parse
  • lodash
  • Object.assgin
  • structureClone

es6的导入导出

1,导入

  • 默认导入:import 名称 from “模块化的路径名”
  • 按需导入:import {导入的数据名称} from “模块化的路径名”

2,导出

  • 默认导出:export default{导出的全部数据}
  • 按需导出:export {导出的数据}

data中数据为什么放在一个对象中?

组件的data写成一个函数,数据一函数返回值形式定义,这样每复用一次组件,就会返回一份新的data,类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护自己的数据。而单纯的写成对象形式,就是的所有组件实例公用一份data,就会造成一个变了,所有的都会发生改变的结果

vue的异步队列和nextTick的区别

Vue的dom更新是异步的,当数据发生变化,vue并不是里面去更新DOM,而是开启一个队列

nextTick:当dom发生变化,更新后执行的回调

vue绑定事件的时候如何阻止冒泡

@click.stop="事件名"

methods,watch,computed的执行顺序

  • computed:在dom加载后马上执行
  • methods:需要有一定的触发条件,比如点击事件
  • watch:用于观察Vue实例上数据变动,数据发生变动时执行

es5和es6的继承的区别

1,es5是新建子类的实例对象this,再将父类的属性添加到子类上面

  • 由于父类的内部属性无法获取,导致无法继承原生的构造函数

2,es6是新建父类的实例对象this,然后再用子类的构造函数修饰this,使得父类的所有行为都可以进行

  • es6允许继承原生构造函数定义子类

promise的构造函数是同步还是异步的

promise的构造函数是同步执行的,then是异步执行的

setTimeout,promise,async await的区别

setTimeout是宏任务,promise,async await是微任务,async await是promise的同步写法(语法糖),微任务是在宏任务之前执行的

async await如何把异步的操作变成同步的操作

async函数返回的是一个promise对象,在调用这个函数时,如果函数执行成功,内部会调用promise.solve() 方法返回一个promise对象,如果函数执行出现异常,就会调用reject方法返回一个promise对象。async与await配合使用才能是异步操作同步化,await就是等待的意思,等待摸一个函数执行完后,后面的代码才能开始执行

盒模型有几种

1,标准盒模型

-宽高不包含border,padding

2,怪异盒模型(ie)

  • 宽高包含了border,padding

v-model实现原理

在内部为不同的输入元素使用不同的属性并抛出不同的事件

  • text 和 textarea 元素使用 value 属性和 input 事件
  • CheckBox 和 redio 使用 checked 属性和 change 事件
  • select 字段将 value 作为 prop 并将 change 作为事件

实现原理:

  • v-bind:绑定响应式数据
  • 触发 v-on: input 事件并传递数据

组件间的通信方式

1,props / $emit

父组件向子组件传值(props)

子组件向父组件传值($emit)

2,ref / $refs

实现父子组件通信

3,eventBus事件总线(emit/emit / on)

适用于父子组件、非父子组件等之间的通信

4,依赖注入(provide / inject)------ 了解

父子,祖孙之间通信

【注】:依赖注入所提供的属性时 非响应式的

5,parent/parent / children

使用 $parent 可以访问 父组件 的实例(访问的是上一级父组件的属性和方法)

使用 children可以让组件访问子组件的实例,但是,children 可以让组件访问 **子组件** 的实例,但是,children 并不能保证顺序,并且访问的数据也不是 响应式

6,attrs/attrs / listeners 跨代通信

$attrs:继承所有父组件属性(除了 props 传递的属性、class、style),一般用在子组件的子元素上

listeners:该属性是一个对象,里面包含了作用在这个组件上的所有的监听器,可以配合von="listeners:该属性是一个对象,里面包含了作用在这个组件上的所有的监听器,可以配合 **v-on="listeners"** 将所有的事件监听器指向这个组件的某个特定的子元素。(相当于子组件继承父组件的事件)

hash路由和history路由的区别

1,原理不同:

hash模式的实现通过 监听 hashChange 事件来实现的

history模式是通过 pushState + popstate 事件来实现的

2,表现不同:

hash 模式会在地址栏中有 # 号,而history 模式没有。history 对浏览器的兼容性有要求(IE>=10)

v-for 中使用 key 的原因

key是给内个 vnode 的唯一id,也是 diff 的一种优化策略,可以根据key,跟准确,更快的找到对应的 vnode 节点

vue 相较于原生 js 的优点

1,数据的自动绑定

2,页面参数传递和页面状态管理

3,模块化开发、无刷新保留场景参数更新

4,代码的可阅读性

5,基于强大的 node.js ,拥有 npm 包管理器,可以很好地管理包的版本

6,各组件样式不冲突

7,视图,数据,结构分离

8,虚拟 DOM

9,拥有各种内置指令

对 MVVM 的理解

由 Model, View,ViewModel 三部分组成,Model 层代表数据模型,也可以在 Model 中定义和修改业务逻辑,View 代表 UI 组件,它负责将数据模型转化成 UI 展现出来,ViewModel 是一个同步 View 和 Model 的对象

在MVVM中,数据和视图是不能直接通信的,视图模型相当于一个观察者,监控双方的动作,并及时通知进行相应的动作。当Model发生变化的时候,viewModel能够监听到这种变化,并及时通知view做出相应的修改,反之,当view发生变化是,viewmodel监听到变化后,通知model进行修改,实现视图与模型的互相解耦

Vue数据双向绑定原理

是采用 数据劫持 结合 发布者-订阅者模式 的方式,通过 object.definePoperty() 来个各个属性添加 settergetter 并劫持监听,在数据变动时发布消息给订阅者,触发响应的监听回调

Vue性能优化

1,尽量减少data中的数据,data中的数据都会增加getter和setter,会收集对应的watcher

2,v-if和v-for不能连用(vue2中v-for的优先级高,vue3 中v-if的优先级高)

3,如果需要使用 v-for 给每项元素绑定事件时,使用事件代理

4,spa页面采用keep-alive缓存组件

5,在更多情况下,使用v-if代替v-show

js 防抖和节流

1,防抖:有些操作是高频触发的,但其实触发一次就好了。等用户高频事件完了,在进行事件操作

事件触发 ---- 开启一个定时器 ---- 如果再次触发,则清楚上一次的,重写一下 ---- 定时到,触发操作

2,节流:节流就是减少流量,将频繁触发的事件减少,并每隔一段时间实行,控制事件触发的频率

事件触发 ---- 执行操作 ---- 关闭阀门 ---- 阀门关闭,后续触发无效 ---- 一定时间后,阀门打开 ---- 操作课再次进行

设计原理

七大设计原理:

1,工厂模式:封装实例的创建过程,解放new class()

2,单例模式:全局只允许有一个实例,多则出错

3,观察者模式:前端常用的设计模式,工作必备,面试必考 ------- 当一个对象的状态或动作取决于另一个对象的状态或动作时,当更改一个对象是,需要更改未知数量的其他对象,当一个对象应该能够通知其他变化而不知道这些其他对象

4,迭代器模式:遍历数据不仅仅是 for 或 forEach,还要更高级的iterator

5,装饰器模式:decorator现已是js标准语法

6,原型模式:原型和原型链式js的必备知识

7,代理模式

vue数据驱动

vue的核心概念就是数据驱动:视图是由数据驱动生成的,我们对视图的修改不会直接操作Dom,而是通过修改数据进行视图更新。相较于传统的Dom进行开发,大大简化了代码量,只关心数据的修改让代码的逻辑变得非常清楚,DOM变成了数据的映射,所有的逻辑都是对数据的操作

解耦与耦合

1,耦合:对象之间的依赖性。对象之间的耦合度越高,维护成本越高

2,解耦:将耦合度降低

3,低耦合:在任何复杂的场景下都可以即拿即用

4,高耦合:组件使用场景少

组件化开发

将复杂的业务逻辑拆分成多个组件,每个组件依赖的css,js,模板,图片等资源放在一起开发和维护。可以简化代码量,对后期的需求变更和维护也更加友好

如何判断对象是否是空对象

1、将对象转换成字符串,再判断是否等于“{}”

let obj = {} JSON.stringify{obj} = {}

2、for in循环

let result=function(obj){ for(let key in obj){ return false;//若不为空,可遍历,返回false } return true; } console.log(result(obj));//返回true

3、Object.keys()方法,返回对象的属性名组成的一个数组,若长度为0,则为空对象(ES6的写法)

console.log(Object.keys(obj).length==0);//返回true

4、Object.getOwnPropertyNames方法获取对象的属性名,存到数组中,若长度为0,则为空对象

console.log(Object.getOwnPropertyNames(obj).length==0);//返回true