web前端面试题(更新)

web前端面试题

1、垂直居中方式

/* 垂直居中方式 */
.aaaaa {
    /* 直接定位 */
    position: absolute; // 子绝父相
    top: 45px;
    left: 45px;
    
    margin: 0 auto; // 块级
    
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    
    text-align: center; // 文本居中
    
    vertical-align: middle; // 图片
    
    display: flex;  // 自由布局
    justify-content: center;
    align-items: center;
    
    height: 100px; // 行高等于实际高度
  	line-height: 100px;
}
(1)内减模式
/* css3盒子,不需要手动计算盒子尺寸||内减模式 */
  box-sizing: border-box;
(2)flex 布局
.grid-item {
  width: 33.3%;
  height: 200rpx;
  display: flex;
  flex-direction: column; /* 竖向排列 */
  align-items: center; /*水平居中 */
  justify-content: center; /* 垂直居中 */
  border-right: 1rpx solid #efefef;
  border-bottom: 1rpx solid #efefef;
  box-sizing: border-box; /* 内减模式 */
}


.img-box {
  display: flex;
  padding: 20rpx 10rpx;
  justify-content: space-around; /* 四周平均留空 */
}

2、清除float影响

/* 清除float影响
    1.尾部额外标签,添加块元素的css样式clear:both

    2.单伪元素清除法
    .clearfix::after{
        content:'';
        display:blok;
        clear:both;
        //低版本浏览器添加
        height:0;
        visibility:hidden;
    }

    3.双伪元素解决塌陷法
    .clearfix::before,
    .clearfix::after{
        content:'';
        display:table;
    }
    //真正清除浮动部分
     .clearfix::after{
        clear:both;
    }

    4.父元素添加overflow:hidden;
*/

3、css3超出部分省略

适用于input标签和普通标签文本内容超出部分省略号显示。

(1)哪三个属性
overflow:hidden; 
white-space:nowrap; 
text-overflow:ellipsis;
(2)具体属性用法

overflow属性的使用
特点:必须给块级容器指定高度,或者使用不换行属性让内容变宽
属性值

  • visible:默认值。
  • hidden:内容会被修剪,浏览器会显示滚动条。
  • scroll:由浏览器定夺,如果内容被修剪,会显示滚动条。
  • auto:规定从父元素继承overflow属性的值。

white-space属性的使用 :处理元素中的空白
属性值:常用

  • normal:文字换行。
  • nowrap:文字不换行。

text-overflow属性的使用

特点:该属性不会强制发生溢出,要是文本溢出其容器,必须设置overflow和white-space
属性值

  • clip:默认值,换行。
  • ellipsis:显示一个‘…’来表示剪切文本

4、css实现三角形

三角形原理:边框的均分原理

通过设置 border 的 top、left、right、bottom 属性实现,transparent 表示透明色

.box1 {
    width: 0;
    height: 0;
    border-top: 100px solid red;
    border-left: 100px solid blue;
    border-right: 100px solid green;
    border-bottom: 100px solid yellow;
}

.box2 {
    width: 0;
    height: 0;
    /* transparent 透明色 */
    border-top: 200px solid transparent;
    border-left: 0px solid blue;
    border-right: 100px solid green;
    border-bottom: 0 solid yellow;
}

.box3 {
    width: 0;
    height: 0;
    border-color: transparent green transparent transparent;
    border-style: solid;
    border-width: 200px 100px 0 0;
}

5、Session、Cookie、sessionStorage、localStorage区别

特别

cookie 数据存放在客户的浏览器上,session 数据放在服务器上;

cookie 不安全,可能被别人分析欺骗

① 传递方式不同

  1. cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递。

  2. sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。

② 数据大小不同

Cookie 4KB、sessionStorage 约 5M、localStorage 约 20M

③ 数据有效期不同

  1. sessionStorage:仅在当前浏览器窗口关闭前有效,自然也就不可能持久保持;

  2. localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;

  3. cookie只在设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭。

④ 作用域(生命周期)不同

sessionStorage不在不同的浏览器窗口中共享,即使是同一个页面;

localStorage 在所有同源窗口中都是共享的;

cookie也是在所有同源窗口中都是共享的。

6、iframe 是什么?有什么优缺点?

iframe 元素会创建包含另一个文档的内联框架。

优点

  • 解决加载缓慢的第三方内容如图标和广告等的加载问题
  • Security sandbox
  • 并行加载脚本

缺点

  • iframe会阻塞主页面的Onload事件
  • 即时内容为空,加载也需要时间
  • 没有语意
  • 搜索引擎无法解读这种页面,不利于 SEO

  • iframe 和主页面共享连接池,而浏览器对相同区域有限制所以会影响性能。

7、对 HTML 标签语义化的理解

HTML 语义化标签是指正确的标签包含了正确的内容,结构良好,便于阅读,比如 nav 表示导航条,类似的还有 article、header、footer 等等标签。

8、你对web标准以及W3C的理解?

web标准:web标准主要分为结构、表现、行为3部分,
结构:指我们平时在body里面写的标签,主要是由HTML标签组成
表现:指更加丰富HTML标签样式,主要由CSS样式组成,
行为:指页面和用户的交互,主要由JS部分组成
W3C:W3C对web标准提出了规范化的要求,即代码规范对结构的要求1、标签字母要小写2、标签要闭合3、标签不允许随意嵌套
对表现和行为的要求1、建议使用外链CSS和js脚本,实现结构与表现分离、结构与行为分离,
能提高页面的渲染效率,更快地显示网页内容

9、回流和重绘

回流:当一个元素自身的宽高,布局,显示或隐藏,或元素内部的文字结构发生变化
,导致需要重新构建页面的时候,就产生了回流复制

重绘:当一个元素自身的宽高,布局,及显示或隐藏没有改变,
而只是改变了元素的外观风格的时候,就产生了重绘

10、搭建网页都需要用到哪些布局方式

① 标准流(标签自带布局)

② 浮动(float)

③ 定位(position)

层级关系

标准流<浮动<定位(默认情况,定位的盒子,后来者居上;z-index:整数;取值越大,显示顺序越在上;默认为0,必须配合定位。)

11、防抖和节流

1. 防抖(debounce):
防抖触发高频率事件时n秒后只会执行一次,如果n秒内再次触发,则会重新计算。
简单概括:每次触发时都会取消之前的延时调用。(将多次执行变为最后一次执行
2. 节流(thorttle):
高频事件触发,每次触发事件时设置一个延迟调用方法,并且取消之前延时
调用的方法。
简单概括:每次触发事件时都会判断是否等待执行的延时函数。(将多次连续的执行变成每隔一段时间执行

区别:

降低回调执行频率,节省计算资源。

防抖和节流本质是不一样的。防抖是将多次执行变为最后一次执行,节流是将
多次执行变成每隔一段事件执行

函数防抖一定连续触发的事件,只在最后执行一次,而函数节流一段时间内只执行
一次。

12、判断js的数据类型

通过 typeofinstanceof

typeof 可以用来区分除了 Null 类型(可以用全等===判断)以外的原始数据类型

instanceof 不能用于判断原始数据类型的数据

13、 var、let和const的区别

var、let 区别

1.使用var声明的变量,其作用域为该语句所在的函数内,且存在变量提升现象;
2.使用let声明的变量,其作用域为该语句所在的代码块内,不存在变量提升;
3.let不允许在相同作用域内,重复声明同一个变量

const

(1) const是设置常量,也就是不能改变。const定义的数值字符串的时候值不能改变。
(2) const 定义的对象的时候,对象不能改变,但是对象的属性值可以改变。

varletconst
只有全局作用域和函数作用域有块级作用域有块级作用域
存在变量提升不存在变量提升不存在变量提升
可以重复声明不能重复声明不能重复声明
没有死区存在暂时性死区存在暂时性死区
可以先声明后赋值可以先声明 后赋值声明即赋值

14、函数提升与变量提升

变量提升
简单说就是在 JavaScript 代码执行前引擎会先进行预编译,预编译期间会将变量声明与函数声明提 升至其对应作用域的最顶端,函数内声明的变量只会提升至该函数作用域最顶层。当函数内部定义的一个变量与外部相同时,那么函数体内的这个变量就会被升到最顶端
函数提升
函数提升只会提升函数声明式写法,函数表达式的写法不存在函数提升
函数提升的优先级大于变量提升的优先级,即函数提升在变量提升之上

15、什么是作用域?全局作用域和局部作用域?

概念:代码(变量)可以使用的范围就是作用域。主要是为了提高程序的可靠性,也是为了减少命名冲突

全局作用域和局部作用域
全局作用域:指的是整个js文件,定义在全局中的全局变量,可以在局部作用域中使用,函数内部没有声明直接赋值的变量也叫全局变量
局部作用域:主要指的是函数作用域,函数内部也就是局部作用域
在函数内部var定义的变量-,叫做局部变量,局部变量无法被外部获取

16、什么是事件冒泡?怎么阻止事件冒泡?

概念:当我们点击子元素触发父元素的事件,这种现象,我们叫做事件冒泡,即由子元素向祖先元素传播,就像气泡从水底上浮
event.stopPropagation();阻止事件冒泡

17、什么是事件委托?

通俗的讲,子代有事,让父级执行,当我们点击li时,子元素会通过事件的冒泡来触发父元素的事件,主要是通过事件冒泡
原理: 不要给每个子节点单独设置事件监听器,而是事件监听设置在其父节点上,然后利用冒泡原理影响设置每个子节点

18、闭包

闭包就是能够读取其他函数内部变量的函数
闭包基本上就是一个函数内部返回一个函数

特点

  1. 函数嵌套函数

  2. 内部函数可以访问外部变量

  3. 参数和变量不会被回收(回收牵扯出全局变量和局部变量,因为全局变量在页面关闭后销毁,比较占内存资源。局部变量在函数执行完毕后销毁,闭包保护局部变量不会在函数执行完被回收也就是销毁)

19、深拷贝与浅拷贝

浅拷贝:基本数据类型拷贝的是值,引用数据类型拷贝的是地址
深拷贝:引用数据类型拷贝的是开辟新地址中的值

JS 中可以使用 node.cloneNode() 复制;参数为空或者false,浅拷贝,只复制标签不复制内容;可以添加true,深复制

JQuery 中可以使用 $.extend([deep], target, object, [objectN]) ,把 deep 参数设为 true

json暴力转化

对象和字符串的相转化

var a = JSON.stringify(one);//先转字符串再转对象
var b = JSON.parse(a);

封装开辟新地址的函数

function deepCopy(obj){
    var objs = JSON.stringify(obj);
    var newObj = JSON.parse(objs);
    return newObj;
}

这种简单粗暴的方式有局限性,当值为undefined、function、symbol会在转换过程中被忽略。

ES6 新语法扩展运算符

var obj = {name:'123',age:13};
var obj2 = {...obj}

只能深度拷贝对象的第一层,如果对象中的属性也是对象的话,没有办法进行深度拷贝的。

for in 循环遍历对象

var obj = {
    name: "小明",
    age: 20
}
var obj1 = {}
for (var key in obj) {
    //遍历属性值,深拷贝
    obj1[key] = obj[key]
}
console.log(obj1);

同样的,只能深度拷贝对象的第一层,如果对象中的属性也是对象的话,没有办法进行深度拷贝的。

Object.assign() 对象的合并
利用Object.assign(), 第一个参数必须是空对象

var obj = {name:'123',age:13};
var obj2 = Object.assign({},obj1);

只能深度拷贝对象的第一层,如果对象中的属性也是对象的话,没有办法进行深度拷贝的。

⑦ 利用循环和递归的方式

function deepClone(obj, newObj) {
    var newObj = newObj || {};
    for (let key in obj) {
        if (typeof obj[key] == 'object') {
            newObj[key] = (obj[key].constructor === Array) ? [] : {}
            deepClone(obj[key], newObj[key]);
        } else {
            newObj[key] = obj[key]
        }
    }
    return newObj;
}

在循环递归中需要注意设置临界值(typeof obj[key] == ‘object’),否则会造成死循环。
循环递归可以处理对象中嵌套数组或对象的问题。相当于第三种方法的优化。

20、javascript 的内存(垃圾)回收机制?

含义:垃圾回收器会每隔一段时间找出那些不再使用的内存,然后为其释放内存

一般使用标记清除方法(mark and sweep), 当变量进入环境标记为进入环境,离开环境标记为离开环境
垃圾回收器会在运行的时候给存储在内存中的所有变量加上标记,然后去掉环境中的变量以及被环境中变量所引用的变量(闭包),在这些完成之后仍存在标记的就是要删除的变量了

还有引用计数方法(reference counting), 在低版本IE中经常会出现内存泄露,很多时候就是因为其采用引用计数方式进行垃圾回收。引用计数的策略是跟踪记录每个值被使用的次数,当声明了一个 变量并将一个引用类型赋值给该变量的时候这个值的引用次数就加1,如果该变量的值变成了另外一个,则这个值得引用次数减1,当这个值的引用次数变为0的时 候,说明没有变量在使用,这个值没法被访问了,因此可以将其占用的空间回收,这样垃圾回收器会在运行的时候清理掉引用次数为0的值占用的空间。

在IE中虽然JavaScript对象通过标记清除的方式进行垃圾回收,但BOM与DOM对象却是通过引用计数回收垃圾的, 也就是说只要涉及BOM及DOM就会出现循环引用问题。

21、JavaScript 的同源策略

概念: 同源策略是客户端脚本(尤其是Netscape Navigator2.0,其目的是防止某个文档或脚本从多个不同源装载。
这里的同源策略指的是:协议,域名,端口相同,同源策略是一种安全协议。
指一段脚本只能读取来自同一来源的窗口和文档的属性。

22、解决跨域?

  1. jsonp跨域
  2. document.domain + iframe 跨域
  3. nodejs中间件代理跨域
  4. vue 的 proxy 代理

23、内存泄漏

定义:程序中己动态分配的堆内存由于某种原因程序未释放或无法释放引发的各种问题。
js中可能出现的内存泄漏情况:结果:变慢,崩溃,延迟大等
js中可能出现的内存泄漏原因

  • 全局变量
  • dom 清空时,还存在引用
  • 定时器未清除
  • 子元素存在引起的内存泄露

24、JavaScript 的执行策略

1. EventLoop

JavaScript 单线程语言

问题:前一个任务耗时,程序假死

(1) 同步任务和异步任务

① 同步任务(synchronous)

  • 非耗时任务,主线程上排队执行
  • 前一个执行完,才执行后一个

② 异步任务 (asynchronous)

  • 好耗时任务,js 委托给宿主环境执行
  • 异步任务执行完成后,会通知 js主线程执行异步任务的回调函数
(2) 同步任务和异步任务的执行过程

在这里插入图片描述

在这里插入图片描述

2. 宏任务和微任务

① 宏任务(macrotask)

  • 异步 Ajax 请求
  • setTimeout、setinterval
  • 文件操作
  • 其它宏任务

② 微任务 (microtask)

  • Promise.then、.catch 和 .finally
  • process.nextTick
  • 其它微任务

在这里插入图片描述

(1) 宏任务和微任务的执行顺序

在这里插入图片描述

(2) 经典面试题

在这里插入图片描述

25、get与post的区别

  • get 通过地址栏拼接参数,但是因为地址栏长度有限,所以get传输数据也有限
  • post 没有数据传输大小的限制
  • get不需要设置请求头post需要设置请求头
  • get请求数据可能被缓存post不会
  • get只能URL编码,post支持的编码格式众多

26、web性能优化

  • 降低请求量:合并资源,减少 HTTP 请求数,minify / gzip 压缩,webP,lazyLoad。

  • 加快请求速度:预解析 DNS,减少域名数,并行加载,CDN 分发。

  • 缓存:HTTP 协议缓存请求,离线缓存 manifest,离线数据缓存 localStorage。

  • 渲染:JS/CSS 优化,加载顺序,服务端渲染,pipeline。

27、为什么vue组件中的data是一个函数

确保组件间数据相互不被影响,防止变量污染

28、computed和watch的区别

1、含义

computed:计算属性,并且有缓存,只有她所依赖的属性值发生变化computed才会重新计算,并且支持同步

watch:监听器,不支持缓存(可以在data中直接使用),监听的数据发生变化才会触发,watch支持异步,监听的函数可以接收两个参数,一个是最新的值,另一个是改变之前的值

2、特点

计算属性 computed :
支持缓存,只有依赖数据发生改变,才会重新进行计算
不支持异步,当computed内有异步操作时无效,无法监听数据的变化

侦听属性watch

  1. 不支持缓存,数据变,直接会触发相应的操作;
  2. watch支持异步;
  3. 监听的函数接收两个参数,第一个参数是最新的值;第二个参数是输入之前的值;

3、使用场景

  • computed

    • 当一个属性受多个属性影响的时候就需要用到computed
    • 最典型的例子: 购物车商品结算的时候
  • watch

    • 当一条数据影响多条数据的时候就需要用watch,搜索数据
    • 深度监听:handle() deep:true; immediate:true

29、v-if和v-show的区别

v-if:是真正的条件渲染,同时他也是惰性的,如果在初始渲染时条件为假,则什么也不做,直到第一次变为真时,才会开始渲染,条件切换过程会发生销毁和重建,动态创建和删除元素

具有更高的切换开销,如果在运行是条件很少改变,使用v-if比较好

v-show:不管初始条件是什么,元素总是会被选二胺,并且知识简单的基于css(display:none/block)进行切换
具有更高的初始开销,如果切换非常频繁,则使用v-show比较好

30、vue的生命周期

概念:vue实例从创建到销毁的过程就是生命周期,也就是从开始创建,出啊石化数据,编译模板,挂载dom->渲染,更新->渲染,卸载等一系列过程

beforeCreate():vue实例创建之前调用

created():vue实例创建完成

beforeMount():视图编译之前

mounted():视图编译完成,vuedom加载之后

beforeUpdate():数据改变之前

updated():数据改变之后

beforeDestory():vue2销毁之前 || beforeUnmount():vue3销毁之前

destory():vue2销毁之后 || Unmounted():vue3销毁之后

特别的:

keep-alive 对应的生命周期函数

被缓存:deactivated

被激活:activated

31、vue组件如何进行传值的

  1. 父组件向子组件传递数据

    • 父组件内设置要传的数据,在父组件中引用的子组件上绑定:(v-bind)一个自定义属性并把数据绑定在自定义属性上,在子组件添加props接收即可(自定义属性
  2. 子组件向父组件传递数据

    • 子组件通过vue实例方法$emit进行触发并且可以携带参数,父组件监听使用@(v-on)绑定的事件进行监听,然后方法处理(自定义方法)
  3. 兄弟组件之间传递数据

    • 引入第三方 new vue 定义为 eventBus

    • 在组件中 created 中订阅方法 eventBus.$on(“自定义事件名”,methods 中的方法名)

    • 在另一个兄弟组件中的 methods 中写函数,在函数中发布 eventBus 订阅的方法

    • eventBus.$emit("自定义事件名”)

    • 在组件的 template 中绑定事件(比如 click)

  4. 祖孙之间的传值

    • provide 定义的对象会加载到子组件或者孙子组件中

    • inject 接收祖先组件中provide函数return出的内容

  5. 父子之间的双向数组同步

在这里插入图片描述

<button @click="count++">+1</button>
	APP-----count: {{count}}
<MyCounter v-model:number="count"></MyCounter>

----------------------------------------------

<template>
  <div>
    <p>count 值:{{ number }}</p>
    <button @click="add">+1</button>
  </div>
</template>

<script>
export default {
  name: 'MyCounter',
  props: ['number'],
  emits: ['update:number'],
  methods: {
    add() {
      this.$emit('update:number', this.number + 1)
    }
  },
}
</script>
  1. 可以通过 vuex 传值

  2. 可以使用本地存储进行传值(cookie、localstorge、sessionStorage)

32、常见的修饰符及其作用

修饰符作用
.stop等同于js中event.stopPropagation(),防止事件冒泡
.prevent等同于js中event.preventDefault(),阻止默认行为
.capture当元素发生冒泡时,先触发带有修饰符的元素,若有多个修饰符,则由内而外触发。如 div1中嵌套div2中嵌套div3.capture中嵌套div4,那么执行顺序为:div3=》div4=》div2=》div1
.slef只触发自己范围内的事件,不包含子元素
.once只触发一次
.lazy延迟执行,一般用于表单输入框
.trim自动去除首位空格
.number自动转化为数值类型

33、vue-router路由模式有几种?

  • hash: 使用 URL hash 值来作路由。支持所有浏览器,包括不支持 HTML5 History Api 的浏览器;
  • history : 依赖 HTML5 History API 和服务器配置。具体可以查看 HTML5 History 模式;
  • abstract : 支持所有 JavaScript 运行环境,如 Node.js 服务器端。如果发现没有浏览器的 API,路由会自动强制进入这个模式.

34、对 nextTick 的理解

  1. 当你修改了data的值然后马上获取这个dom元素的值,是不能获取到更新后的值,你需要使用$nextTick这个回调,让修改后的data值渲染更新到dom元素之后在获取,才能成功。

  2. 在使用某个第三方插件时,希望在vue生成的某些DOM动态发生变化时重新应用该插件,也会用到该方法,这时候就需要$nextTick的回调函数中执行重新应用插件的方法,例如:应用滚动插件better-scroll

35、vuex

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。每一个 Vuex 应用的核心就是 store(仓库)。“store” 基本上就是一个容器,它包含着你的应用中大部分的状态 ( state )。

(1)Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
(2)改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化。
主要包括以下几个模块:

  • State => 基本数据,定义了应用状态的数据结构,可以在这里设置默认的初始状态。
  • Getter => 从基本数据派生的数据,允许组件从 Store 中获取数据,mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性。
  • Mutation => 是唯一更改 store 中状态的方法,且必须是同步函数。
  • Action => 像一个装饰器,包裹mutations,使之可以异步。用于提交 mutation,而不是直接变更状态,可以包含任意异步操作。
  • Module => 模块化Vuex,允许将单一的 Store 拆分为多个 store 且同时保存在单一的状态树中。
import { mapGetters } from 'vuex' // 导入

computed: { // 计算属性
    ...mapGetters([
        '属性名'
    ])
 }

this.$store.commit('set属性名', 属性值) // 设置

// 直接调用

36、对keep-alive的理解

keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,避免重新渲染 ,其有以下特性:

  • 一般结合路由和动态组件一起使用,用于缓存组件;
  • 提供 include 和 exclude 属性,两者都支持字符串或正则表达式, include 表示只有名称匹配的组件会被缓存,exclude 表示任何名称匹配的组件都不会被缓存 ,其中 exclude 的优先级比 include 高;
  • 对应两个钩子函数 activated 和 deactivated ,当组件被激活时,触发钩子函数 activated,当组件被移除时,触发钩子函数 deactivated。

37、请说出 vue-cli 工程中每个文件夹和文件的用处?

  • build 文件夹是保存一些 webpack 的初始化配置。
  • config 文件夹保存一些项目初始化的配置
  • node_modules 是 npm 加载的项目依赖的模块
  • src 目录是我们要开发的目录:
  • assets 用来放置图片
  • components 用来放组件文件
  • app.vue 是项目入口文件
  • main.js 项目的核心文件

38、Vuex 页面刷新数据丢失怎么解决?

需要做 vuex 数据持久化,一般使用本地储存的方案来保存数据,可以自己设计存储方案,也可以使用第三方插件。

推荐使用 vuex-persist 插件,它是为 Vuex 持久化储存而生的一个插件。不需要你手动存取 storage,
而是直接将状态保存至 cookie 或者 localStorage中。

39、vue 中使用了哪些设计模式?

1、工厂模式 - 传入参数即可创建实例
虚拟 DOM 根据参数的不同返回基础标签的 Vnode 和组件 Vnode。
2、单例模式 - 整个程序有且仅有一个实例
vuex 和 vue-router 的插件注册方法 install 判断如果系统存在实例就直接返回掉。
3、发布-订阅模式。(vue 事件机制)
4、观察者模式。(响应式数据原理)
5、装饰器模式(@装饰器的用法)
6、策略模式,策略模式指对象有某个行为,但是在不同的场景中,
该行为有不同的实现方案 - 比如选项的合并策略。

40、你都做过哪些 Vue 的性能优化?

  • 这里只列举针对 Vue 的性能优化,整个项目的性能优化是一个大工程。
    • 对象层级不要过深,否则性能就会差。
    • 不需要响应式的数据不要放在 data 中(可以使用 Object.freeze() 冻结数据)
    • v-if 和 v-show 区分使用场景
    • computed 和 watch 区分场景使用
    • v-for 遍历必须加 key,key最好是id值,且避免同时使用 v-if
    • 大数据列表和表格性能优化 - 虚拟列表 / 虚拟表格
    • 防止内部泄露,组件销毁后把全局变量和时间销毁
    • 图片懒加载
    • 路由懒加载
    • 异步路由
    • 第三方插件的按需加载
    • 适当采用 keep-alive 缓存组件防抖、节流的运用
    • 服务端渲染 SSR or 预渲染

41、Vue路由懒加载

1、vue异步组件实现路由懒加载

component:resolve=>(['需要加载的路由的地址',resolve])

2、es提出的import(推荐使用这种方式)

const HelloWorld = ()=>import('需要加载的模块地址')

42、其他内容

1、性能优化的几个方面?
  • 资源压缩合并,减少HTTP请求
  • 非核心代码异步加载
  • 利用浏览器缓存
  • 使用CDN
  • 预解析DNS
2、异步加载?
  • 动态脚本加载
  • defer
  • async
3、加载方式
  • defer是在html解析完毕才执行,如果有多个则按加载顺序执行
  • async是加载完毕后立即执行,如果是多个,执行顺序与加载顺序无关
4、预加载

在开发中,可能会遇到这样的情况。有些资源不需要马上用到,但是希望尽早获取,这时候就可以使用预加载。
预加载其实是声明式的 fetch ,强制浏览器请求资源,并且不会阻塞 onload 事件,可以使用以下代码开启预加载
link rel=“preload” href=“http://example.com”预加载可以一定程度上降低首屏的加载时间,因为可以将一些不影响首屏但重要的文件延后加载,唯一缺点就是兼容性不好。

5、DNS预解析

DNS 解析也是需要时间的,可以通过预解析的方式来预先获得域名所对应的 IP。

在https协议中默认a标签不会开启预解析,因此需要手动设置meta
6、懒执行

懒执行就是将某些逻辑延迟到使用时再计算。
该技术可以用于首屏优化,对于某些耗时逻辑并不需要在首屏就使用的,
就可以使用懒执行。懒执行需要唤醒,一般可以通过定时器或者事件的调用来唤醒。

7、懒加载

懒加载就是将不关键的资源延后加载。懒加载的原理就是只加载自定义区域(通常是可视区域,
但也可以是即将进入可视区域)内需要加载的东西。对于图片来说,
先设置图片标签的 src 属性为一张占位图,
将真实的图片资源放入一个自定义属性中,当进入自定义区域时,
就将自定义属性替换为 src 属性,这样图片就会去下载资源,实现了图片懒加载。懒加载不仅可以用于图片

43、案例数组去重

//数组去重['x', 's', 'a', 's', 'g', 'a', 'h', 'm', 'd', 'l']
//1、目标:把旧数组中里面不重复的元素取出来放到新数组里,重复元素只保留一个,放到新数组里去重
//2、核心算法:遍历旧数组,拿旧数组元素去查新数组,如果该元素在新数组里没有出现过就添加,否则不添加
//3、利用 新数组.indexOf(数组元素)  如果返回是-1就说明新数组没有该元素,那就添加上

//封装一个 去重函数 unique
function unique(arr) {
    var newArr = [];
    for (var i = 0; i < arr.length; i++) {
        if (newArr.indexOf(arr[i]) === -1) {
            newArr.push(arr[i])
        }
    }
    return newArr;
}
console.log(['x', 's', 'a', 's', 'g', 'a', 'h', 'm', 'd', 'l']);
console.log(unique(['x', 's', 'a', 's', 'g', 'a', 'h', 'm', 'd', 'l']));

44、查询字符串所有特定元素出现位置及次数

// 查找字符串'ascascasdsacsfea'中所有a出现的位置以及次数
// 核心算法:先查找第一个a出现的位置
// 然后,只要indexOf返回的结果不是-1,就继续往后查找
// 因为indexOf只能查找到第一个元素,所以后边的查找,一定是当前索引加1,从而继续查找
var str = 'ascascasdsacsfea';
var index = str.indexOf('a');
var num = 0;
while (index !== -1) {
    num++;
    addr = index + 1;
    console.log('第' + num + '个的位置是:' + addr);
    index = str.indexOf('a', index + 1);
}
console.log('a出现的次数是:' + num);

45、常用的 JS 库

  • tocbot.js(目录生成)

  • waypoints.js(平滑滚动)

  • swiper.js(轮播图)

  • qrcode.js(生成二维码)

  • Day.js(时间日期处理)

  • lodash.js(鲁大师,高效处理array、number、objects、string等对象,降低JS操作难度)

  • zplayer.js(音乐)

  • gallery.js(画廊,图片管理)

  • distance.js(实现计算两点经纬度之间的距离)

  • Dropzone.js(文件拖拽上传)

  • zy.media.js (视频管理)

46、特别的:forEach和map的区别

1、相同点

​ (1) 都是循环遍历数组中的每一项。

​ (2) 每次执行匿名函数都支持三个参数,参数分别为item(当前每一项),index(索引值),arr(原数组)。

​ (3) 匿名函数中的this都是指向window。

​ (4) 只能遍历数组。

2、不同点

​ (1) map()会分配内存空间存储新数组并返回,forEach()不会返回数据。

​ (2) forEach()允许callback更改原始数组的元素。map()返回新的数组

47、vue2 和 vue3 的区别

  1. 双向数据绑定原理不同;

  2. 是否支持碎片;

  3. API类型不同;

  4. 定义数据变量和方法不同;

  5. 生命周期钩子函数不同;

  6. 父子传参不同;

  7. 指令与插槽不同;

  8. main.js文件不同。

可参考:vue2和vue3区别 • Worktile社区

48、把树转化数组

// 树状结构数据
const data = [
    {
      id: 1,
      pid: null,
      title: '研发部',
      children: [
        { id: 5, title: '前端研发部', pid: 1 },
        { id: 6, title: '后端研发部', pid: 1 },
        { id: 7, title: '算法研发部', pid: 1 },
      ],
    },
    {
      id: 2,
      pid: null,
      title: '开发部',
      children: [
        { id: 8, title: '前端开发部', pid: 2 },
        { id: 9, title: '后端开发部', pid: 2 },
        { id: 10, title: '算法开发部', pid: 2 },
      ],
    },
    { id: 3, title: '市场部', pid: null },
    { id: 4, title: '销售部', pid: null },
];

// 方法一
function treeToArray1(array) {
    const result = [];
    array.forEach((item) => {
      if (item.children) {
        // 得到push进去最后一位成员的位置 从1开始,同时直接返回数组长度index
        let index = result.push(item, ...item.children);
        // 删除children属性
        delete result[index - item.children.length - 1].children;
      } else {
        result.push(item);
      }
    });
    return result;
}

// 方法二
function treeToArray2(array) {
    return array.reduce((prev, cur) => {
      if (cur.children) {
        // 删除chidren项 因为push得到的是push进去的成员在第几个位置 从1开始 因此要减1
        delete prev[prev.push(cur, ...cur.children) - cur.children.length - 1].children;
      } else {
        prev.push(cur);
      }
      return prev;
    }, []);
}

// 数组结果数据
  const data = [
	{
	  id: 1,
	  title: '研发部',
	  pid: null,
	},
	{
	  id: 2,
	  title: '开发部',
	  pid: null,
	},
	{
	  id: 3,
	  title: '市场部',
	  pid: null,
	},
	{
	  id: 4,
	  title: '销售部',
	  pid: null,
	},
	{
	  id: 5,
	  title: '前端研发部',
	  pid: 1,
	},
	{
	  id: 6,
	  title: '后端研发部',
	  pid: 1,
	},
	{
	  id: 7,
	  title: '算法研发部',
	  pid: 1,
	},
	{
	  id: 8,
	  title: '前端开发部',
	  pid: 2,
	},
	{
	  id: 9,
	  title: '后端开发部',
	  pid: 2,
	},
	{
	  id: 10,
	  title: '算法开发部',
	  pid: 2,
	},
];

49、用 js 实现将一个二维数组转换成树结构。

比如,将以下二维数组:

const arr = [
    ["a", "aa", "aaa", "aaaa"],
    ["b", "bb", "bbb"],
    ["a", "ab", "aba"],
    ["a", "aa", "aab"]
]

转为树结构的对象数组:

[{
    "name" : "a",
    "child" : [
        {
            "name" : "aa",
            "child" : [
                {
                    "name" : "aaa",
                    "child" : [
                        {
                            "name" : "aaaa",
                            "child" : []
                        }
                    ]
                },
                {
                    "name" : "aab",
                    "child" : []
                }
            ]
        },
        {
            "name" : "ab",
            "child" : [
                {
                    "name": "aba",
                    "child" : []
                }
            ]
        }
    ]
},
{
    "name": "b",
    "child" : [
        {
            "name" : "bb",
            "child" : [
                {
                    "name" : "bbb",
                    "child" : []
                }
            ]
        }
    ]
}]

实现思路基本是将一维数组转为链表,再进行合并去重。算法如下:

// 实现思路基本是将一维数组转为链表,再进行合并去重。算法如下:
function arr2List(arr) {
  const list = [];
  const head = {
    name: arr[0],
    child: [],
  };
  let prev = head;
  list.push(prev);
  for (let i = 1; i < arr.length; i++) {
    const current = {
      name: arr[i],
      child: [],
    };
    // 将当前节点挂载到链表尾节点上
    prev.child.push(current);
    prev = current;
  }
  // 返回链表头节点, 已经挂载了所有节点
  return list;
}

function mergeList(tree, list) {
  // 递归终止条件,因为可能有多个链表头节点挂载到树上
  if (!tree) {
    return;
  }
  // 遍历树,查找是否有共同的父节点
  const hasCommonParent = tree.some(treeItem => {
    // 有共同的父节点
    if (treeItem.name === list[0].name) {
      // 将链表头节点挂载到树上
      mergeList(treeItem.child, list[0].child); // 确保链表头节点的子节点不会丢失
      // 递归终止条件
      return true;
    }
    // 递归继续
    return false;
  })

  // 没有共同的父节点,将链表头节点挂载到树上
  if (!tree.length || !hasCommonParent) {
    tree.push(list[0]);
  }
}

function arr2Tree(arr) {
  const tree = [];
  // 遍历二维数组,将每个一维数组转为链表,再将链表合并到树中
  arr.forEach((item) => {
    const list = arr2List(item);
    mergeList(tree, list);
  });
  return tree;
}
const arr = [
  ['a', 'aa', 'aaa', 'aaaa'],
  ['b', 'bb', 'bbb'],
  ['a', 'ab', 'aba'],
  ['a', 'aa', 'aab'],
  ['b', 'ba', 'aabb'],
  ['b', 'ba', 'aabbaa'],
];

arr2Tree(arr);

50、Date对象

Date() : Date()日期对象 是一个构造函数,必须用new来调用;

​ 无参数时 为当前时间;

​ 字符串格式 ‘2023-4-9 12:48:12’;

​ 数字格式 2023, 4, 9 返回的是5月;

//Date()日期对象 是一个构造函数,必须用new来调用
var date1 = new Date();
var date2 = new Date('2023-4-9 12:48:12');
var date3 = new Date(2023, 4, 9);
console.log(date1); //返回当前时间
console.log(date2);  //正常
console.log(date3); //返回的是5月,不是4月

var date4 = new Date();
console.log(date4.getFullYear()); //返回当前年份
console.log(date4.getMonth() + 1); //返回当前月份,返回月份默认从0开始,记得加1
console.log(date4.getDate()); //返回当前几号
console.log(date4.getDay()); //返回当前星期,从 星期日到星期六 依次是 0,1,2,3,4,5,6
console.log(date4.getHours());  //时
console.log(date4.getMinutes()); //分
console.log(date4.getSeconds()); //秒

var year = date4.getFullYear();
var month = date4.getMonth() + 1; //加1
var dates = date4.getDate();
var arr = ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'];
var day = date4.getDay();
console.log('当前日期是:' + year + '年' + month + '月' + dates + '日 ' + arr[day]);

function getTime() {
    var time = new Date();
    var h = time.getHours();  //时
    h = h < 10 ? '0' + h : h; //小于10,前边补0
    var m = time.getMinutes(); //分
    m = m < 10 ? '0' + m : m; //小于10,前边补0
    var s = time.getSeconds(); //秒
    s = s < 10 ? '0' + s : s; //小于10,前边补0
    return h + '时' + m + '分' + s + '秒';
}
console.log(getTime()); //00时00分00秒

时间戳(总的毫秒数)

//获取总的毫秒数(时间戳),距离1970年1月1日过了多少毫秒
//1、通过valueOf() 或者 getTime() 获取
var date5 = new Date();
console.log(date5.valueOf());
console.log(date5.getTime());

//2、简单写法(常用)
var date6 = +new Date();
console.log(date6);

//3、H5新增的方法
console.log(Date.now());

倒计时

//1、核心算法:输入的时间减去现在的时间就是剩余时间,即倒计时,但是不能拿着时分秒直接相减
//2、用时间戳来做,用户输入的时间的总毫秒数减去现在时间的总毫秒数,得到剩余时间的总毫秒数
//3、把剩余时间总毫秒数转化为天、时、分、秒(时间戳转化为时分秒)
//转化公式如下:
//   d = parseInt(总秒数/ 60/60 /24); //计算天数
//   h = parseInt(总秒数/ 60/60 %24); //计算小时
//   m = parseInt(总秒数/ 60 % 60); //计算分数
//   s = parseInt(总秒数 %60); //计算当前秒数
function countDown(time) {
    var nowTime = +new Date(); //当前时间的总毫秒数
    var inputTime = +new Date(time); //用户输入时间的总毫秒数
    var times = (inputTime - nowTime) / 1000; //剩余时间总秒数
    var d = parseInt(times / 60 / 60 / 24); //计算天数
    d = d < 10 ? '0' + d : d;
    var h = parseInt(times/ 60 / 60 % 24); //计算小时
    h = h < 10 ? '0' + h : h;
    var m = parseInt(times/ 60 % 60); //计算分数
    m = m < 10 ? '0' + m : m;
    var s = parseInt(times % 60); //计算当前秒数
    s = s < 10 ? '0' + s : s;
    return d + '天' + h + '时' + m +'分' + s + '秒';
}
console.log(countDown('2023-4-11 18:00:00'));
var date = new Date();
console.log(date);

51、数组去重

//数组去重['x', 's', 'a', 's', 'g', 'a', 'h', 'm', 'd', 'l']
//1、目标:把旧数组中里面不重复的元素取出来放到新数组里,重复元素只保留一个,放到新数组里去重
//2、核心算法:遍历旧数组,拿旧数组元素去查新数组,如果该元素在新数组里没有出现过就添加,否则不添加
//3、利用 新数组.indexOf(数组元素)  如果返回是-1就说明新数组没有该元素,那就添加上

//封装一个 去重函数 unique
function unique(arr) {
    var newArr = [];
    for (var i = 0; i < arr.length; i++) {
        if (newArr.indexOf(arr[i]) === -1) {
            newArr.push(arr[i])
        }
    }
    return newArr;
}
console.log(['x', 's', 'a', 's', 'g', 'a', 'h', 'm', 'd', 'l']);
console.log(unique(['x', 's', 'a', 's', 'g', 'a', 'h', 'm', 'd', 'l']));

52、什么是盒子模型

css 盒模型(Box Model),在html中任何一个元素都可以看作盒子,这里说的盒子与现实不太一样,css中盒子是二维的,盒子由内到外分四个部分:margin(外边距)、border(边框)、padding(内边距)、content(内容)。css通过margin、border、padding三个属性来控制盒子,content是html元素的内容。

53、css 的 @import 和 link 的区别

1、link属于html标签,而@import是css提供的,只能加载CSS
2、加载顺序,link在页面加载时被加载,@import在页面加载完之后再加载
3、link是html标签,因此没有兼容性,而@import只有IE5以上才能识别
4、link是可以通过 JS 操作 DOM ,插入link标签来改变样式;由于 DOM 方法是基于文档的,无法使用@import

54、git 常用命令

创建仓库:1.创建一个仓库,git init 2.git clone一个远程仓库

git日常工作流程:1.git pull拉取最新的代码 2.git add将修改的代码文件提交到暂存区 3.git commit -m 将暂存区的代码提交到本地仓 4.git push将代码推送到远程仓

分支相关的命令:git branch 查看分支,git checkout分支名 切换分支,git checkout -b分支名 新建并切换到新的分支,git merge合并分支,其实合并分支还有另一种,是git rebase,但是很少去用,这两个的区别就是merge保留了完整的历史记录,它是将当前的commit和公共分支合并在一起,形成一个新的commit,rebase不会保留完整的历史记录 ,它是将当前分支的commit放到公共分支的最后面,形成一条新的分支

55、web前端常见兼容性问题

在 Web 前端开发中,浏览器兼容性问题是一个常见的挑战。由于不同的浏览器实现了不同的标准和规范,因此相同的代码在不同的浏览器上可能会有不同的表现,或者甚至无法正常工作。

(1)常见前端兼容性问题

常见的浏览器兼容性问题包括以下几点:

CSS 盒模型问题:不同浏览器对盒模型的解释可能不一致,导致页面布局不同。解决方法是在 CSS 中明确指定盒模型的属性。(内减模式)

CSS 属性兼容性问题:某些 CSS 属性在不同浏览器中表现不一致,如某些浏览器不支持某些属性或值,解决方法是使用 CSS hack 或兼容性前缀。

JavaScript 兼容性问题:不同浏览器对 JavaScript 的解释也可能不一致,如一些浏览器不支持某些 DOM 方法或事件。解决方法是使用浏览器检测和兼容性处理。

HTML 兼容性问题:不同浏览器对 HTML 标签和属性的解释也可能不一致,如一些浏览器对一些 HTML5 标签和属性支持不完全。解决方法是使用 polyfill 或兼容性库。

图片加载问题:不同浏览器对图片加载的处理也可能不同,如某些浏览器在加载图片时可能会阻塞其他资源的加载。解决方法是使用图片懒加载或使用适当的图片格式。

响应式布局问题:不同浏览器在解释媒体查询时可能存在差异,导致响应式布局不同。解决方法是在编写媒体查询时尽可能明确和具体,避免使用模糊的描述词汇。

跨域访问问题:由于安全限制,浏览器禁止从一个域名的网页中直接访问另一个域名的资源。解决方法是使用 CORS(跨域资源共享)或 JSONP(JSON with Padding)等技术。

表单元素的兼容性问题:不同浏览器对表单元素的默认样式和行为可能存在差异,如某些浏览器对某些表单元素的样式可能不支持修改。解决方法是使用自定义的样式或 JavaScript 代码对表单元素进行处理。

CSS 动画效果兼容性问题:某些浏览器对 CSS3 动画效果的支持不完全或不一致,解决方法是使用 JavaScript 实现动画效果,或使用 CSS hack 或兼容性前缀。

字体兼容性问题:不同浏览器在对字体的解释和渲染上也可能存在差异,解决方法是使用 Web 字体或使用适当的字体格式。

针对以上兼容性问题,前端开发者需要在开发过程中注意不同浏览器的差异性,并采用相应的解决方法来保证页面在各种浏览器中能够正确地展示和运行,例如使用 polyfill 库、CSS hack、媒体查询、特定的前缀等。同时,可以使用一些兼容性检测工具来帮助开发者发现和解决兼容性问题。

(2)常用前端兼容性问题检测工具

Can I Use: https://caniuse.com/ 是一个免费的 Web 工具,提供了各种前端技术在各种浏览器和平台中的支持情况,包括 HTML5、CSS3、JavaScript 等。

BrowserStack: https://www.browserstack.com/ 是一个基于云端的跨浏览器测试工具,可以模拟各种浏览器和操作系统,帮助开发者发现和解决兼容性问题。

CrossBrowserTesting: https://crossbrowsertesting.com/ 是另一个基于云端的跨浏览器测试工具,可以模拟各种浏览器和操作系统,并提供自动化测试和调试工具。

Modernizr: https://modernizr.com/ 是一个 JavaScript 库,用于检测浏览器对 HTML5 和 CSS3 特性的支持情况,开发者可以根据检测结果进行相应的兼容性处理。

HTML5 Boilerplate: https://html5boilerplate.com/ 是一个针对 HTML5 开发的模板和工具集合,包括一些兼容性处理和优化技术。

W3C 标准测试工具: https://validator.w3.org/ 和 https://jigsaw.w3.org/css-validator/ 是 W3C 提供的 HTML 和 CSS 标准测试工具,开发者可以使用这些工具来检测代码的规范性和兼容性。

LambdaTest: https://www.lambdatest.com/ 是一个跨浏览器测试工具,提供云端虚拟机和实时测试功能,可以模拟各种浏览器和操作系统,并支持自动化测试和调试工具。

Browsershots: https://browsershots.org/ 是一个免费的在线截图工具,可以在不同的浏览器和操作系统上生成网站截图,用于检测网站在不同浏览器上的表现。

IE NetRenderer: http://www.netrenderer.com/ 是一个免费的在线工具,可以在不同的 IE 版本中预览网站的效果,用于检测和调试网站在 IE 浏览器上的兼容性问题。

Sauce Labs: https://saucelabs.com/ 是一个基于云端的测试平台,提供跨浏览器和跨平台测试功能,支持各种桌面和移动浏览器,并提供自动化测试和调试工具。

Browserling: https://www.browserling.com/ 是一个在线测试工具,可以在各种浏览器和操作系统上测试网站的兼容性,支持自动化测试和调试工具。

这些工具都可以帮助开发者检测和解决网站在不同浏览器和操作系统上的兼容性问题,从而提高网站的可访问性和用户体验。开发者可以根据自己的需求选择合适的工具来进行兼容性测试和调试。

56、react里面:state和prop的区别?setState为什么是异步的?组件传值有几种方式?

答:

  1. prop用于定义外部接口,state用于记录内部状态。

  2. prop的赋值在外部使用组件时,state的赋值在组建内部。

  3. 组件不应该改变prop的值,但是state的存在目的是让组件来改变。

57、setState异步更新状态使得并发更新组件成为可能。

资料:https://segmentfault.com/a/1190000013040438?utm_source=tag-newest

58、组件传值的方式:

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

子传父(回调函数)

跨级组件传值

没有嵌套关系的组件通信

参考:https://www.cnblogs.com/dhcn/p/11125448.html

59、vuex里面存储的数据,怎么处理页面刷新丢失的问题?

可以直接改为本地存储,sessionstorage等。

资料:https://www.cnblogs.com/goloving/p/9074574.html

60、amd规范和cmd规范的区别?

cmd规范推崇依赖就近,amd规范推崇依赖前置。

对依赖模块amd是提前执行,cmd是延迟执行。

61、spa应用怎么做seo?

服务器端渲染ssr,预渲染。

预渲染指的是在服务器端生成静态 HTML。在用户访问 SPA 应用之前,服务器可使用 headless 浏览器进行渲染,并生成 HTML 网页,该网页将包含静态的内容和必要的元数据。搜索引擎可以抓取和索引这些预渲染的网页,而用户在访问 SPA 应用时,JavaScript 代码会接管交互过程。

62、百度权重的优化方法?

友情链接,关键字,网站功能多时可以设置网站导航地图。

63、简单描述一下ajax的过程?

  1. 先创建一个xmlhttprequest对象。
  2. open()
  3. send()
  4. 判断服务器响应的状态。

64、怎么中断ajax的发送?

一种是设置超时时间让ajax自动断开,

另一种为手动去停止ajax请求,其核心是调用XMLHttpRequest对象上的abort方法

65、vue-router是基于什么来实现的?

  1. hash ----------(#hash)
  2. 浏览器的history

资料:https://blog.csdn.net/qq_27674439/article/details/99821474

66、创建对象有几种方式?

  1. 字面量方式

  2. 构造函数

资料:https://www.cnblogs.com/topsyuan/p/11260399.html

用原生的方法监听对象的变化?如对象有个name属性,如果改变为张三就alert张三,如果改变为李四就alert李四?

67、什么情况下会引起重绘和回流?

重绘:当更新render tree中某个元素属性时,而这些属性只是影响元素外观风格,不影响布局,称为重绘。

回流:当render tree的一部分因为元素规模尺寸,布局,隐藏等改变需要重新构建时,称为回流。当页面第一次加载时一定会发生回流。

区别:回流必将引起重绘,重绘不一定会引起回流。

68、怎么实现一个div(正方形)高度随宽度变化而变化?

使用js监听div.style.height,在赋值给div的宽。

69、call和apply的区别?

  1. call的语法:函数名.call(obj,参数1,参数2,参数3……);

  2. apply的语法:函数名.apply(obj,[参数1,参数2,参数3……]);

这两个东西功能相同,就是把一个函数里面的this设置为某个对象,区别就是后面的参数的语法。call需要使用逗号分隔列出所有参数,但是apply是把所有参数写在数组里面。需要注意的是即使只有一个参数,也必须写在数组里面。

70、移动端开发中遇到过哪些问题?

例如:插件安装问题,请求跨域问题等。

71、vue为什么对这个数组和对象进行监听?

watch:{} 对象,可监听数据,数据发生变化, 处理函数

目的: watch虽可监听,但只是浅监听,只监听数据第一层或者第二层,watch监听不到。可以设置deep:true做深度监听。

对vue的数据双向绑定。

72、常见的状态码有哪一些?403代表什么?

403服务器拒绝访问。

73、一个radio标签能在安卓上面添加一个click事件吗?

能。

具体实现参考:


方法(@click.native.prevent):

<el-radio-group v-model="radio2">
  <el-radio @click.native.prevent="clickitem(3)" :label="3"> 备选项</el-radio>
  <el-radio @click.native.prevent="clickitem(6)" :label="6"> 备选项</el-radio>
  <el-radio @click.native.prevent="clickitem(9)" :label="9"> 备选项</el-radio>
</el-radio-group>
           
clickitem (e) { 
     e === this.radio2 ? this.radio2 = '' : this.radio2 = e
 },

74、动画的优化方式有哪些?

图形图像优化,声音文件优化,文件及库的优化,代码的优化。

75、vue中keep-alive的作用?

keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。

76、跨域的几种解决方案?

四种:1.jsonp 2.cros 3.domain.xml配置 4.正向代理。

77、get和post请求的区别?

post安全性比get好,get的参数在url上,post请求文件中,get用于获取数据,post主要用于提交数据。

78、什么是内存泄露?什么操作会引发内存泄露?

内存泄露是指程序中已动态分配的堆内存由于某种原因程序未释放或者无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。

闭包使用不当引发

79、ie盒模型和w3c盒模型有什么区别?

ie盒模型content部分包含了padding和border

w3c盒模型content不包含。

80、讲讲你前端性能优化会做的一些工作?

雪碧图技术,压缩代码,合并复用的js和css文件,懒加载技术,css放在head中,设置浏览器缓存等。

81、webpack的fileload跟urlload的区别?

答: url-loader封装了file-loader。url-loader不依赖于file-loader,例如:我们需要background样式用url引入一张背景图,我们都知道webpack会将各模块进行打包,因此用url的路径是html页面入口,而不是原始的css文件,会导致图片引入失败。而使用file-load,可以解析项目中的url引入,根据我们的配置,将图片拷贝到相应的路径,根据我们的配置,修改打包后文件引用路径,指向正确文件。

82、css3怎么实现一条线围绕这个中心点做一个旋转的动画?

答:使用css3的transform属性。

​ @keyframes

83、jquery里面on和bind的区别?

都是事件绑定,

区别:事件委托。

84、ES5 和 ES6 新特性以及API对比

1、es6新增了箭头函数,es5没有;

2、ES6中新增了块级作用域,es5没有;

3、ES6引入Class概念,不再像ES5一样使用原型链实现继承;

​ ES6引入了class关键字,提供了更易读和理解的面向对象编程方式。另外,ES6还引入了模块化的概念,使用importexport关键字实现模块的导入和导出。

4、ES6中可以设置默认函数参数,es5不行;

5、ES6中新增了promise特性。

6、ES6中新增模版字符串

7、ES6中新增结构赋值

85、MySQL的索引类型有哪些

B+tree索引、Hash索引、Full-text索引

86、javascript原始类型有哪些

javascript原始类型有6种,分别为:

1、number(数字类型);

2、string(字符串类型);

3、null;

4、undefined(未定义);

5、boolean(布尔类型);

6、symbol,表示独一无二的值。

87、前端刷新页面的五种方法(含原生js、vue和react)

原生JS

1、window.history.go(0)方法

window.history.go(0)

2、location.reload()方法

location.reload()

3、location.href=location.href方法

location.href=location.href

4、vue-router方法

const router = useRouter()

router.go(0)

5、react-router方法

import { createBrowserHistory, createHashHistory } from 'history';

const history = createBrowserHistory() // history模式
const history = createHashHistory() // hash模式

history.go(0)

88、发布订阅者模式和观察者模式的区别

发布订阅者模式又叫观察者模式发布订阅者模式一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得将得到通知;观察者模式则是一种一对一的依赖关系。

89、浏览器输入 URL 后回车发生了什么?

在这里插入图片描述

面试题:浏览器输入 URL 后回车发生了什么? (baidu.com)

90、vue2/3响应式的区别以及proxy的优点

个人对“vue2与vue3响应式原理的区别”的理解 - 知乎 (zhihu.com)

在响应式原理方面 Vue3 与 Vue2 有什么不同? (zhihu.com)

91、原型链的三个对象

原型链:原型链主要有三部分构成:原型、构造函数、实例,实例可以通过new构造函数获取,构造函数可以通过实例的constructor或者原型的constructor获取,原型可以通过实例的__proto__或者构造函数的prototype获取。原型也可以通过__proto__获取父级元素的原型,直到最终拿到null。

【四】原型链 - 哔哩哔哩 (bilibili.com)

92、React和Vue的区别有什么

1、学习曲线的区别

React:React的学习曲线相对较陡,尤其是当引入Redux等数据流管理工具时,开发者需要花费更多时间掌握。React更注重JavaScript的本质,强调函数式编程,对于具有较强JS基础的开发者来说,更容易上手。

Vue:相比之下,Vue的学习曲线相对较缓。Vue集成了许多React和Angular的优点,同时其API设计更为直观,使得初学者可以更快地上手并进行开发。同时,Vue的文档也非常友好,对初学者更有帮助。

2、数据流管理的区别

React:React使用Redux进行状态管理,Redux是一个高度严谨和可预测的状态管理器,但也因此变得相对复杂。初学者可能会对其有一些困惑。

Vue:Vue使用Vuex进行状态管理,Vuex的设计原则和Redux相似,但在实际使用中,Vuex的API更简单,学习成本更低。

3、社区支持的区别

React:React由Facebook维护,拥有庞大的社区支持。同时,由于其长时间的历史,React有更多的库可供选择,且生态系统更为成熟。

Vue:Vue虽然社区相对较小,但发展非常快速,国内的支持也非常热烈。

4、基础结构的区别

React:React是由Facebook开发的一个JavaScript库,它只关注视图层。这种设计理念使得React可以与其他库无缝协作。另一方面,React使用虚拟DOM,并引入了一种叫做JSX的语法糖,可以在JavaScript中写HTML。

Vue:Vue也是一个专注于视图层的JavaScript框架,同时也易于学习。Vue使用了一种类似于HTML的模板语法,让开发者可以将HTML元素绑定到Vue实例的数据上。另外,Vue也使用了虚拟DOM。

5、数据绑定的区别

React:React实现了单向数据流,这种设计使得应用的状态预测更为准确。当视图需要变化时,必须通过Dispatch Action,然后通过Reducer函数来改变State状态。

Vue:Vue实现了双向数据绑定,通过v-model指令可以很容易地实现。这种设计使得开发者在编写业务代码时,可以更快速地响应用户输入,而不需要手动监听和更新DOM。

6、性能的区别

React:React通过引入虚拟DOM,降低了直接操作DOM带来的性能损耗。在每次状态更新时,React会创建一个新的虚拟DOM树,并与上一次的树进行比较,然后高效地更新实际DOM。

Vue:Vue也使用了虚拟DOM,但它进一步优化了虚拟DOM的性能。在初始化应用时,Vue会预先计算出模板中的依赖关系,因此在重新渲染时,只需要更新依赖的部分,从而提高渲染效率。

93、CSS3新特性

  1. 选择器
  2. 边框圆角 radius
  3. 盒阴影 shadow
  4. 渐变 tranform
  5. 过渡 transition
  6. 动画 animation

94、移动端适配问题

1、rem

  • rem单位是相对于html元素的font-size来设置的,那么如果我们需要在不同的屏幕下有不同的尺寸,可以动态的修改html的font-size尺寸。
  • 需要设置根节点的font-size,以便根据它计算

2、media

  • @media screen and开头的语句就是媒体查询语句。@media后面是一个或者多个表达式,如果表达式为真,则应用样式。@media screen and (min-width:320px) 这句话的意思就是:设备宽度小于320就选中这个样式。

  • 也可以利用第三方库lib-flexible动态font-size

    下载地址:GitHub - amfe/lib-flexible: 可伸缩布局方案

3、viewport

  • vw单位是相对于视口的。比如375px的屏幕就是1vw==3.752px。

/* width: 100px / 3.75px = 26.6667vw */

4、media+viewport

5、media+rem

特比地:vw和rem的对比

  • rem事实上是作为一种过渡的方案,它利用的也是vw的思想

    1. 前面不管是我们自己编写的js,还是flexible的源码
    2. 都是将1rem等同于设计稿的1/10,在利用1rem计算相对于整个屏幕的尺寸大小
    3. 思考一下,1vw不是刚好等于屏幕的1/100
    4. 而且相对于rem还更加有优势;
  • vw相比于rem的优势:

    1. 优势一: 不用去计算html的font-size大小,也不需要给html设置这样一个font-size
    2. 优势二:不会因为设置html的font-size大小,而必须给body再设置一个font-size,防止继承
    3. 优势三:因为不依赖font-size的尺寸,所以不用担心某些原因html的font-size尺寸被篡改,页面尺寸混乱
    4. 优势四:vw相比于rem更加语义化,1vw刚好是1/100的viewport的大小
    5. 优势五: 可以具备rem之前所有的优点

95、移动端实现 0.5px 的细线

  1. viewport
  2. calc()计算函数
  3. transform: scale() 方法缩放

96、深拷贝、扁平化(多层数组嵌套)

JSON、循环、递归、reduce函数迭代、es6扩展运算符

97、css3动画:从左到右 2秒

@keyframe move {
    from {left: 0;} 
	to {left: 100%;} 
}
/*
@keyframe move {
    0 {tranform: translateX(0);} 
	100% {tranform: translateX(100%);} 
}
*/
element {
    animation: move 2s
}

98、ESM(ESModule) 和 CJS(CommonJS) 的区别

  1. 导入导出方式不同:

    • CJS 是通过 require 导入,module.exports 和 exports 导出的

    • ESM 是通过 import 导入,export 导出的

  2. 输出值方式不同

    • CJS 输出的是一个值的拷贝
    • ESM 输出的是值的引用,并且只读
  3. 加载机制不同

    • CJS 是运行时加载
    • ESM 是编译时输出接口
    • CJS 的 require() 是同步加载模块
    • ESM 的 import 是异步加载,有一个独立的模块依赖的解析阶段
  4. ESM 模块会自动使用严格模式,不管你有没有在模块头部添加 “use strict”

  • 15
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Pluto_ssy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值