web前端面试题必备

1、vue数据双向绑定原理

vue.js 是采用数据劫持结合发布者-订阅者的模式的方法,通过Object.defineProperty()来劫持各个属性的Getter、setter,在数据变动时发送消息给订阅者。它实现的整个流程是先为每个vue属性用Object.defineProperty()实现数据劫持,为每个属性分配一个订阅者集合的管理数组dep;然后在编译的时候在该属性的数组dep添加订阅者v-model就会添加一个订阅者,接着用input举例,为input添加监听事件,修改值就会为这个属性赋值,触发这个属性的set方法,在set方法内通知订阅者数组dep订阅者数组循环调用各个订阅者update方法更新视图。然后就实现了数据的双向绑定。

2、图片懒加载原理

先将img标签的src链接设为同一张图片(比如空白图片),然后给img标签设置自定义属性(比如 data-src),然后将真正的图片地址存储在data-src中,当JS监听到该图片元素进入可视窗口时,将自定义属性中的地址存储到src属性中。达到懒加载的效果。
这样做能防止页面一次性向服务器发送大量请求,导致服务器响应慢,页面卡顿崩溃等。

2.1判断元素是否在可视区域内

  • [ 当元素距离顶部的高度大于等于DOM文档滚动的高度并且元素距离顶部的高度小于DOM滚动高度+可视高度,那么这个元素就进入了可视区域 ]

元素距离顶部高度(elOffsetTop) >= dom滚动高度(docScrollTop
并且元素距离顶部高度(elOffsetTop) < (dom滚动高度 + 视窗高度)

3、虚拟 Dom 和 Diff算法原理

虚拟 DOM就是一个JavaScript的一个对象。对复杂的文档DOM结构,提供一种方便的工具,进行最小化的DOM操作。

其实就是用js来模拟DOM中的节点,就是传说中的虚拟DOM。

diff的过程就是调用名为patch的函数,比较新旧节点,一边比较一边给真实的DOM打补丁

4、vue2与vue3的区别

首先第一点就是vue2和vue3双向数据绑定原理发生了改变

vue2 的双向数据绑定是利用ES5 的一个 API Object.definePropert()对数据进行劫持 结合 发布订阅模式的方式来实现的。
vue3 中使用了 es6ProxyAPI对数据代理。

第二就是vue2默认进行懒观察(lazy observation)。

2.x 版本里,不管数据多大,都会在一开始就为其创建观察者。当数据很大时,这可能会在页面载入时造成明显的性能压力。3.x 版本,只会对「被用于渲染初始可见部分的数据」创建观察者,而且 3.x的观察者更高效。

三就是重写了虚拟 DOM

随着虚拟 DOM 重写,减少 运行时(runtime)开销。重写将包括更有效的代码来创建虚拟节点

四是他们的项目目录结构

vue-cli2.03.0在目录结构方面,有明显的不同

vue-cli3.0移除了配置文件目录configbuild 文件夹 同时移除了 static静态文件夹,新增了 public文件夹,打开层级目录还会发现, index.html移动到 public

五就是vue3性能的提升

更小巧,更快速;支持摇树优化;支持 分段 (Fragments) 和跨组件渲染;支持自定义渲染器

5、vue 组件通信

我最常用的有三种,

第一种是父传子:主要通过 props 来实现的

父传子是通过import引入子组件,在components中注册 在父 组件标签上用v-bind绑定要传递的数据,子组件通过props接收 并明确传递属性的数据类型

第二种:子传父:主要通过$emit 来实现

子传父通过提交一个$emit方法,这个方法接收两个参数,第一个是要派发的事件,第二个参数是要传递的参数,然后在组件标签上自定义事件接收这个提交的方法,然后在methods中定义

第三种:兄弟传值

兄弟传值有两种方法:

首先创建一个空的vue实例BUS

第一种方法通过BUS.$emit(‘事件名’)传到空的vue实例中

第二种方法通过BUS.$on(‘事件名’,(参数)=>{挂载从子1传来的数据})来接收

第四种:vuex

6、 vuex

6.1 vuex的流程

Vuex怎么请求异步数据

1.首先在state中创建变量
2.然后在action中调用封装好的axios请求,异步接收数据,commit提交给mutations
Mutations中改变state中的状态,将从action中获取到的值赋值给state

页面通过mapAction异步提交事件到actionaction通过commit把对应参数同步提交到mutationmutation会修改state中对应的值。最后通过getter把对应值跑出去,在页面的计算属性中,通过mapGetter来动态获取state中的值

6.2 vuex有五种状态和属性

第一种是State

State就是存放数据的地方,类似一个仓库 , 特性就是当mutation修改了state的数据的时候,他会动态的去修改所有的调用这个变量的所有组件里面的值( 若是store中的数据发生改变,依赖这个数据的组件也会发生更新 )

第二种是Getters

getters用来获取数据,mapgetter经常在计算属性中被使用

第三种就是mutations

他是 唯一更改store 中状态的方法,且必须是同步函数。

第四种是action

他 用于提交 mutation,而不是直接变更状态,可以包含任意异步操作。

最后一种是moduled

他是store的子模块,为了开发大型项目,方便状态管理而使用的。

他可以将单一的 Store 拆分为多个 store 并同时保存在单一的状态树中。
vuex的优势

优点:解决了非父子组件的通信,减少了ajax请求次数,有些可以直接从state中获取

缺点:刷新浏览器,vuex中的state会重新变为初始状态,解决办法是vuex-along,得配合计算属性和sessionstorage来实现

7、vuekey 的作用

需要使⽤key来给每个节点做⼀个唯⼀标识,Diff算法就可以正确的识别此节 点。 作⽤主要是为了⾼效的更新虚拟DOM

8、vue 中的组件中的 data 为什么是 data函数

因为一个组件是可以共享的,但他们的data是私有的,所以每个组件都要return一个新的data对象,返回一个唯一的对象。
Data是一个函数时,每个组件实例都有自己的作用域,每个实例相互独立,不会相互影响

9、vuenextTick作用

nextTick 是在下次DOM更新循环结束之后执行延迟回调,

在修改数据之后使用nextTick,就可以在回调中获取更新后的 DOM.

10、vue组件封装

我用vue开发的所有项目,都是采用组件化的思想开发的。一般我在搭建项目的时候,会创建一个views目录和一个commen目录和一个feature目录,views目录中放页面级的组件,commen中放公共组件(如:head(公共头组件),foot(公共底部组件)等),feature目录内放功能组件(如:swiper(轮播功能组件),tabbar(切换功能组件)、list(上拉加载更多功能组件))

首先,组件可以提升整个项目的开发效率。能够把页面抽象成多个相对独立的模块,解决了我们传统项目开发:效率低、难维护、复用性低等问题。

使用Vue.extend方法创建一个组件,然后使用Vue.component方法注册组件。但是我们一般用脚手架开发项目,每个 .vue单文件就是一个组件。在另一组件import导入,并在components中注册,子组件需要数据,可以在props中接受定义。而子组件修改好数据后,想把数据传递给父组件。可以采用emit方法。

什么是vue生命周期?

Vue实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模板、挂载Dom、渲染→更新→渲染、销毁等一系列过程,我们称这是Vue的生命周期。通俗说就是Vue实例从创建到销毁的过程,就是生命周期。

vue生命周期钩子函数都有哪些?分别是什么意思?

总共分为8个阶段创建前/后,载入前/后,更新前/后,销毁前/后。

创建前/后: 在beforeCreated阶段,vue实例的挂载元素el还没有。在created阶段,vue实例的数据对象data有了,el还没有.

载入前/后:在beforeMount阶段,vue实例的$el和data都初始化了,但还是挂载之前为虚拟的dom节点,data.message还未替换。在mounted阶段,vue实例挂载完成,data.message成功渲染。

更新前/后:当data变化时,会触发beforeUpdate和updated方法。

销毁前/后:在执行destroy方法后,对data的改变不会再触发周期函数,说明此时vue实例已经解除了事件监听以及和dom的绑定,但是dom结构依然存在

vue生命周期的作用是什么?

生命周期中有多个事件钩子,让我们在控制整个 vue 实例的过程时更容易形成好的逻辑

第一次页面加载会触发哪几个钩子?

页面第一次加载会触发 beforeCreate、created、beforeMount、mounted
DOM渲染在mounted周期中就已经完成

11、闭包

闭包是用来解决全局变量私有化的,也可以说成局部变量全局化。
闭包是一种保护私有变量的机制,在函数执行时形成私有的作用域,保护里面的私有变量不受外界干扰。

就是当一个函数的返回值是另外一个函数,而返回的那个函数如果调用了其父函数的内部变量,且返回的那个函数在外部被执行,就产生了闭包 。

他的特点就是

函数嵌套函数

内部函数可以直接访问外部函数的内部变量或参数

变量或参数不会被垃圾回收机制回收( GC 项目使用的闭包越多占用的内存越大,要滞空)

闭包的优点是

变量常驻内存 避免全局变量的污染 他有私有成员存在

闭包的缺点就是

常驻内存 增加内存的使用量 使用不当会造成内存泄漏

他可以通过闭包制作计数器 封装私有属性方法 还可以作为一个回调函数 还可以用作函数节流防抖

12、介绍一下盒模型

CSS盒模型本质上是一个盒子,封装周围的HTML元素,它包括:边距,边框,填充,和实际内容。 他分为两种类型 IE盒子模型标准W3C盒子模型,两种盒模型的主要区别就是标准盒模型的宽高是值内容的宽高,而IE盒模型的宽高是值内容的宽高+填充+边框;在css中通过box-sizing设置盒模型; box-sizing:content-box就是用来设置标准盒模型box-sizing:border-box 则用来设置IE盒模型

13、原型和原型链

js的所有对象中都包含了一个[proto]内部属性,这个属性所对应的就是自身的原型JavaScript的函数对象,除了原型[proto]之外,还有prototype属性,当函数对象作为构造函数创建实例时,该prototype属性值将被作为实例对象的原型[proto];原型链 就是当一个对象调用自身不存在的属性或方法时,就会去自己 [proto] 关联的前辈 prototype 对象上去找,如果没找到,就会去该 prototype 原型 [proto] 关联的前辈 prototype 去找。依次类推,直到找到属性方法或 undefined 为止。从而形成了所谓的“原型链”。

14、 promise

Promise对象是CommonJS工作组提出的一种规范,目的是为异步编程提供统一接口。每一个异步任务返回一个Promise对象,该对象有一个then方法,允许指定回调函数。

一个promise可能有三种状态:等待(pending)已完成(resolved,又称fulfilled)已拒绝(rejected)

promise必须实现then方法(可以说,then就是promise的核心),而且then必须返回一个promise,同一个promisethen可以调用多次,并且回调的执行顺序跟它们被定义时的顺序一致。

then方法接受两个参数,第一个参数是成功时的回调,在promise由“等待”态转换到“完成”态时调用,另一个是失败时的回调,在promise由“等待”态转换到“拒绝”态时调用。同时,then可以接受另一个promise传入,也接受类then的对象或方法

(总的来说,Promise是一个让开发者更合理、更规范地用于处理异步操作的对象。它有三种状态:初始化(pending),操作成功(fulfilled),操作异常(rejected)。使用实例方法:then()和catch()用于绑定处理程序,还有all()和race()方法。)

15、async/await

async/await其实是Promise的语法糖,它能实现的效果都能用then链来实现,它是为优化then链而开发出来的。从字面上来看,async是“异步”的简写,await译为等待,所以我们很好理解async声明function是异步的,await等待某个操作完成。当然语法上强制规定await只能出现在asnyc函数中

array中some()与forEach()的区别

forEach()用来遍历数组,没有返回值。
some()大多使用场景是找到符合条件的元素,迭代效率高,返回值是布尔。

为什么要使用CSS预处理器?

CSS有具体以下几个缺点:

  1. 语法不够强大,比如无法嵌套书写,导致模块化开发中需要书写很多重复的选择器;

  2. 没有变量和合理的样式复用机制,使得逻辑上相关的属性值必须以字面量的形式重复输出,导致难以维护。

这就导致了我们在工作中无端增加了许多工作量。而使用CSS预处理器,提供 CSS 缺失的样式层复用机制、减少冗余代码,提高样式代码的可维护性。大大提高了我们的开发效率。
但是,CSS预处理器也不是万金油,CSS的好处在于简便、随时随地被使用和调试。预编译CSS步骤的加入&

你可能感兴趣的:(vue,js,css3,vue,面试,js)