面试题
1. 块级元素与行内元素的区别 80%
块级元素独占一行 行内元素与其他元素共享一行
块级元素宽高由子元素或其内容决定 可以直接设置宽高(可以通过css来指定宽高) 行内元素宽高由自身决定 行内元素不可以直接设置宽高 需要通过display改变元素属性来设置 块级元素默认宽度为100%
块级元素可以包含行内元素 行内元素只包含行内元素 //行内元素中不可以嵌套块级元素
2. 单选框互斥:
在每一个单选框中设置一name属性,给name属性设置一个相同的值
3. get与post请求的区别
- get 传输数据量小 参数携带在URL后面 没有请求体 没有数据保密性/index.php?id=100&slec=yes
- post 数据传输量大 数据携带在请求体里 数据保密性强(swagger-login /register)
4.img标签中的alt属性的作用是
alt:可以用来设置在图片不能显示的时,对图片的描述
并不是所有的属性都可以继承, 只有以color/font-/text-/line-开头的属性才可以继承
display:inline 使元素成为行内元素
display:block 使元素成为块级元素
display:inline-block 使元素保留行内元素布局,同时拥有块级元素的css属性(如width,height)
5.根据以下代码,两个div元素垂直间距为()
答案:200px
css盒模型,块之间共享垂直外边距margin,margin取其大。
6.6.input 元素的哪个类型属性将元素的值设置为表示一定范围内的数字
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DzF8OJbS-1635141950338)(C:/Users/yang/Pictures/typora图片/image-20210805192350825.png)]
答案为range
7.两列布局,实现左边定宽,右边自适应
右边自适应
左边定宽
8.三列布局,实现左边定宽,中间自适应
Document
左边定宽右边定宽中间自适应
两侧浮动 + 中间自动撑开 中间宽度用 calc 计算,设置两侧对应宽的 margin
左侧右侧中间.left {
float: left;
background: red;
width: 100px;
}
.right {
float:right;
background: blue;
width: 100px;
}
.center {
background: yellow;
width: calc(100% - 200px);
margin: 0 100px;
}
div有顺序要求 布局原则:
1.框架搭建:自上而下,由外向内
2.通配符选择器重置全局样式:
*{
margin:0,
padding:0
}
3.由外向内布局,每一块元素依然遵循自上而下的原则
9.W3C盒子
内容区的宽
width
内容区的高
height
盒子的宽
width+paddingLeft+paddingRight+borderLeft+borderRight
盒子的高
height+paddingTop+paddingBottom+borderTop+borderBottom
所占屏幕空间的宽
width+paddingLeft+paddingRight+borderLeft+borderRight +marginLeft+marginRigh
所占屏幕空间的高
height+paddingTop+paddingBottom+borderTop+borderBottom+marginTop+marginBottom
内容盒子也称为普通盒子,其特点为:当我们为一个盒子指定width属性的时候,实际上width仅为内容的宽度,当padding和border变大的时候,内容宽度不变,盒子所占的总体宽度要变大。
10. 边框盒子(IE盒子模型)
IE盒子使用box-sizing属性可以改变盒子模型,取值“border-box”的盒子为边框盒子模型。
IE盒子
内容区的宽
width-paddingLeft-paddingRight-borderLeft-borderRight
内容区的高
height-paddingTop-paddingBottom-borderTop-borderBottom
盒子的宽
width
盒子的高
height
所占屏幕空间的宽
width+marginLeft+marginRight
所占屏幕空间的高
height+marginTop+marginBottom
边框盒子也称为怪异盒子,其特点为:当我们为一个盒子指定width属性的时候,实际上width包含了border和padding的宽度,如果border不变,padding变大,这时候内容会变小。
11.水平垂直居中的三种方式
12.
for (var i = 0; i < 6; i++) {
console.log(i);//0,1,2,3,4,5
function output() {
console.log(i); // 为什么输出的是6,而不是0,1,2,3,4,5
// 因为输出的 i 是全局作用域的,当循环结束后 i 的值是 6,所以输出的 i 就是6。
}
}output()
//使用IIFE来处理
for (var i = 0; i < 6; i++) {
(function (j) {
console.log(j); //0,1,2,3,4,5
})(i)
// 因为 JS 中调用函数传递参数都是值传递 ,所以当立即执行函数执行时,首先会把参数 i 的值复制一份,然后再创建函数作用域来执行函数,循环5次就会创建5个作用域,所以每个输出访问的都是不同作用域的 i 的值 。
}
13.
var a = 10
//嵌套函数
function fn() {
var b = 20
function bar() {
console.log(a + b) //30
}
//将函数当做了返回值
return bar
}
var x = fn(), // 执行fn() 返回的是bar
b = 200 //用于迷惑人的
x() //执行x,就是执行bar函数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5nsoTOGi-1635141950341)(C:/Users/yang/Pictures/typora图片/image-20210909204949345.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NUbD0MCV-1635141950343)(C:/Users/yang/Pictures/typora图片/image-20210909205036116.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QTK89o5e-1635141950344)(C:/Users/yang/Pictures/typora图片/image-20210909205121598.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aCDaou9n-1635141950345)(C:/Users/yang/Pictures/typora图片/image-20210914163408827.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-27rkN0ep-1635141950347)(C:/Users/yang/Pictures/typora图片/image-20210915214504860.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PrH4Ua18-1635141950349)(C:/Users/yang/Pictures/typora图片/508750714_1581931863826_023A2181E333F8B14324D952C196DD58.png)]
14. 阻止默认事件, 阻止冒泡
-
阻止默认事件:
e.preventDefault()
e.returnValue = false (IE)
-
阻止冒泡:
e.stopPropagation()
e.cancelBubble = true (IE)
15. 模块化机制
-
CommonJs模块化规范(针对服务器端)
-
AMD模块化规范(针对客户端的–>浏览器)
-
ES6模块化规范
- ES6
导入模块 import ‘babel-polyfill’
默认导出
一个模块只能有一个默认导出,不能使用 var、let 或 const 用于导出默认值 export default。
export default{}
export default function foo(){}//ES6导出
let firstName = ‘zhang’
let lastName = ‘san’
export { firstName, lastName }//列表导出
export var a = 1;//单个属性导出
export function() { };//单个属性导出
export { firstName as first, lastName as last }//重命名导出
//默认导出 default
export default {}
//ES6导入
// import {firstName,lastName} form ‘./module.js’
// commomJs导出
module.exports = {
firstName,
lastName,
}
//commonJS导入
let { firstName, lastName } = require(’./module.js’)
16. CommonJS与ES6模块的区别
commonJS模块输出的是值的拷贝 ES6模块输出的是值的引用
commonJS模块运行时加载 ES6模块编译时输出接口
HTTP的几种请求方法用途?
1.1.什么是HTTP 协议?
HTTP : Hyper Text Transfer Protocol 超文本传输协议
1.2.HTTP 协议的作用HTTP 最大的作用就是确定了请求和响应数据的格式,浏览器发送给服务器的数据:请求报文;服务器返回给浏览器的数据:响应报文。
1.3 HTTP 协议的组成HTTP 协议由请求和响应两部分构成,请求是由客户端往服务器传输数据,相应是由服务器往客户端传输数据.
**1、Get方法:**发送一个请求来取得服务器上的某一资源
特征:没有请求体
请求参数附着在URL 地址后面。
请求参数在浏览器地址栏能够直接被看到,存在安全隐患。
在URL 地址后面携带请求参数,数据容量非常有限。如果数据量大,那么超出容量的数据会丢失。
从报文角度分析,请求参数是在请求行中携带的,因为访问地址在请求行。**2、Post方法:**向URL指定的资源提交数据或附加新的数据
特征:有请求体
请求参数放在请求体中
请求体发送数据的大小没有限制
可以发送各种不同类型的数据
从报文角度分析,请求参数是在请求体中携带
由于请求体参数是放在请求体中,所以浏览器地址栏看不到**3、Put方法:**跟Post方法很像,也是向服务器提交数据,但是,Put指向了资源在服务器上的位置,而Post没有
4、Head方法:只请求页面的首部
**5、Delete方法:**删除服务器上的某资源
**6、Options方法:**它用于获取当前URL所支持的方法。如果请求成功,会有一个Allow的头包含类似“Get,Post”这样的信息
**7、Trace方法:**Trace方法被用于激发一个远程的,应用层的请求消息回路
8、Connect方法:把请求连接转换到透明的TCP/IP通道
HTTP状态码及其含义?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cqunYVhv-1635141950350)(C:/Users/yang/Pictures/typora图片/image-20211020193605852.png)]
HTML语义化的理解?
<基本上都是围绕着几个主要的标签,像标题(H1~H6)、列表(li)、强调(strong em)等等>
根据内容的结构化(内容语义化),选择合适的标签(代码语义化)便于开发者阅读和写出更优雅的代码的同时让浏览器的爬虫和机器很好地解析。
- 用正确的标签做正确的事情!
- html语义化就是让页面的内容结构化,便于对浏览器、搜索引擎解析;
- 在没有样式CCS情况下也以一种文档格式显示,并且是容易阅读的。
- 搜索引擎的爬虫依赖于标记来确定上下文和各个关键字的权重,利于 SEO。
- 使阅读源代码的人对网站更容易将网站分块,便于阅读维护理解。
display: none;与visibility: hidden;的区别?
很多前端的同学认为visibility: hidden和display: none的区别仅仅在于display: none隐藏后的元素不占据任何空间,而visibility: hidden隐藏后的元素空间依旧保留 ,实际上没那么简单,visibility是一个非常有故事性的属性
1、visibility具有继承性,给父元素设置visibility:hidden;子元素也会继承这个属性。但是如果重新给子元素设置visibility: visible,则子元素又会显示出来。这个和display: none有着质的区别
2、visibility: hidden不会影响计数器的计数,如图所示,visibility: hidden虽然让一个元素不见了,但是其计数器仍在运行。这和display: none完全不一样
3、CSS3的transition支持visibility属性,但是并不支持display,由于transition可以延迟执行,因此可以配合visibility使用纯css实现hover延时显示效果。提高用户体验。
为什么要初始化CSS样式?
因为浏览器的兼容性,每个浏览器设计时都有自己的特性,因此在解析标签的时候就产生一些差异,因此显示页面的时候就会出现微小的差异。
display 有哪些值?说明他们的作用?
block 此元素将显示为块级元素,此元素前后会带有换行符。
none 此元素不会被显示。
inline-block 行内块元素。
list-item 此元素会作为列表显示。
table 此元素会作为块级表格来显示
inherit 规定应该从父元素继承 display 属性的值
介绍下flex。
Flex 布局,可以简便、完整、响应式地实现各种页面布局
任何一个容器都可以指定为 Flex 布局。
容器默认存在两根轴:水平的主轴(main axis)和垂直的交叉轴(cross axis)
伸缩盒布局用于解决块元素在x轴以及y轴上排列的问题
核心概念:主轴,交叉轴,伸缩盒容器,伸缩盒元素
伸缩盒容器规则:
display、flex-direction、flex-wrap、flex-flow、justify-content、align-items
伸缩盒元素规则:
flex-grow、flex-shrink、flex-basis、flex
介绍js的基本数据类型?
介绍js有哪些内置对象?
1.数据封装类对象: Object、Array、Boolean、Number和String
2.其他对象:Function、Arguments、Math、Date、RegExp、ErrorJavaScript
原型,原型链?有什么特点?
1.JS中每个函数都存在有一个原型对象属性prototype。并且所有函数的默认原型都是Object的实例。
2.每个继承父函数的子函数的对象都包含一个内部属性____proto____。该属性包含一个指针,指向父函数的prototype。若父函数的原型对象的_proto_属性为再上一层函数。在此过程中就形成了原型链。
3.原型链实现了继承。原型链存在两个问题:a 包含引用类型值的原型属性会被所有实例共享。b 在创建子类型时,无法向超类型的构造函数中传递参数。
每个构造函数都有一个原型对象,原型有一个属性指回构造函数,而实例有一个内部指针指向原型。如果原型是另一个类型的实例呢?那就意味着这个原型本身有一个内部指针指向另一个原型,相应地另一个原型也有一个指针指向另一个构造函数。这样就在实例和原型之间构造了一条原型链。这就是原型链的基本构想。原型中包含的引用值会在所有实例间共享
请解释什么是事件代理?
事件代理,俗地来讲,就是把一个元素响应事件(click、keydown…)的函数委托到另一个元素 事件流的都会经过三个阶段:捕获阶段 -> 目标阶段 -> 冒泡阶段,而事件委托就是在冒泡阶段完成事件委托,会把一个或者一组元素的事件委托到它的父层或者更外层元素上,真正绑定事件的是外层元素,而不是目标元素 当事件响应到目标元素上时,会通过事件冒泡机制从而触发它的外层元素的绑定事件上,然后在外层元素上去执行函数
状态机的属性有几种
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MuPQsiFJ-1635141950350)(C:/Users/yang/Pictures/typora图片/image-20211020102513415.png)]
2.vue中的data为什么是函数而不是对象//
每次使用组件时都会对组件进行实例化操作,并且调用data函数返回一个对象作为组件的数据源。这样可以保证多个组件间数据互不影响。
如果data是对象的话,对象属于引用类型,会影响到所有的实例。所以为了保证组件不同的实例之间data不冲突,data必须是一个函数。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EN1uM7eW-1635141950351)(C:/Users/yang/Pictures/typora图片/image-20211013195318374.png)]
3.vue是怎么实现的数据双向绑定
vue 双向数据绑定是通过 数据劫持 结合 发布订阅模式的方式来实现的, 也就是说数据和视图同步,数据发生变化,视图跟着变化,视图变化,数据也随之发生改变;那么什么是数据劫持?vue是如何进行数据劫持的?说白了就是通过Object.defineProperty()来劫持对象属性的setter和getter操作
核心:关于VUE双向数据绑定,其核心是 Object.defineProperty()方法。
4.vue组件的通信方式
vue父组件向子组件传递数据?
通过props
3.子组件像父组件传递事件?
$emit方法
Vue 组件间通信有哪几种方式?
核心答案:
Vue 组件间通信只要指以下 3 类通信:父子组件通信、隔代组件通信、兄弟组件通信
下面我们分别介绍每种通信方式且会说明此种方法可适用于哪类组件间通信。
1、props / $emit 适用 父子组件通信
这种方法是 Vue 组件的基础,相信大部分同学耳闻能详,所以此处就不举例展开介绍。
2、ref 与 $parent / $children 适用 父子组件通信
1)ref:如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例
2)$parent / $children:访问父 / 子实例
3、EventBus ($emit / $on) 适用于 父子、隔代、兄弟组件通信
这种方法通过一个空的 Vue 实例作为中央事件总线(事件中心),用它来触发事件和监听事件,从而实现任何组件间的通信,包括父子、隔代、兄弟组件。
4、 a t t r s / attrs/ attrs/listeners 适用于 隔代组件通信
1) a t t r s : 包 含 了 父 作 用 域 中 不 被 p r o p 所 识 别 ( 且 获 取 ) 的 特 性 绑 定 ( c l a s s 和 s t y l e 除 外 ) 。 当 一 个 组 件 没 有 声 明 任 何 p r o p 时 , 这 里 会 包 含 所 有 父 作 用 域 的 绑 定 ( c l a s s 和 s t y l e 除 外 ) , 并 且 可 以 通 过 v − b i n d = " attrs:包含了父作用域中不被 prop 所识别 (且获取) 的特性绑定 ( class 和 style 除外 )。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 ( class 和 style 除外 ),并且可以通过 v-bind=" attrs:包含了父作用域中不被prop所识别(且获取)的特性绑定(class和style除外)。当一个组件没有声明任何prop时,这里会包含所有父作用域的绑定(class和style除外),并且可以通过v−bind="attrs" 传入内部组件。通常配合 inheritAttrs 选项一起使用。
2) l i s t e n e r s : 包 含 了 父 作 用 域 中 的 ( 不 含 . n a t i v e 修 饰 器 的 ) v − o n 事 件 监 听 器 。 它 可 以 通 过 v − o n = " listeners:包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on=" listeners:包含了父作用域中的(不含.native修饰器的)v−on事件监听器。它可以通过v−on="listeners" 传入内部组件
5、provide / inject 适用于 隔代组件通信
祖先组件中通过 provider 来提供变量,然后在子孙组件中通过 inject 来注入变量。provide / inject API 主要解决了跨级组件间的通信问题,不过它的使用场景,主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入的关系。
6、Vuex 适用于 父子、隔代、兄弟组件通信
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。每一个 Vuex 应用的核心就是 store(仓库)。“store” 基本上就是一个容器,它包含着你的应用中大部分的状态 ( state )。
5.事件循环机制 --宏任务 --微任务
异步执行机制【事件循环机制 EventLoop】
- 所有同步任务都在主线程上执行,形成一个执行栈。
- 主线程之外,还存在一个"任务队列"。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
- 一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
- 主线程不断重复上面的第三步。
简单总结事件循环机制:
同步代码执行 -> 查找异步队列,推入执行栈,执行Vue.nextTick[事件循环1] -> 查找异步队列,推入执行栈,执行Vue.nextTick[事件循环2]…任务队列中的任务会被分为两种:微任务(microtask)和宏任务(macrotask)。
· 宏任务包括 script脚本, setTimeout ,setInterval
· 微任务包括 Promise
- 首先执行同步代码,即script脚本,这属于宏任务
- 当执行完所有同步代码后,执行栈清空
- 从微任务队列中逐个取出回调任务,放入执行栈中执行,直至所有微任务执行完成。注意:如果在执行微任务的过程中,产生了新的微任务,那么这个微任务会加入到队列的末尾,同样会在这个周期内被执行。
- 当执行完所有微任务后,如果有必要会开始渲染页面
- 开始下一轮 Event Loop,执行宏任务中的异步代码,也就是 setTimeout 中的回调函数。
6.Ajax和fetch的区别 –
(1)、ajax是理用XMLHttpRequest对象来请求数据的,而fetch是window的一个方法
(2)、ajax基于原生的XHR开发,XHR本身的架构不清晰,已经有了fetch的替代方案
(3)、fetch比较与ajax有着更好更方便的写法
(4)、fetch只对网络请求报错,对400,500都当做成功的请求,需要封装去处理
(5)、fetch没有办法原生监测请求的进度,而XHR可以
7.怎么绘制一个带有背景颜色的矩形 --fillRect fillStyle
1.实例 --绘制填充矩形
//通过fillRect
window.onload=function(){
//1.获取画布
var canvas=document.querySelector('canvas');
// 2.获取画布上下文对象
var context=canvas.getContext('2d');
// 3.绘制填充样式
context.fillStyle='red'
// 4.绘制填充矩形//x, y, 宽,高
context.fillRect(10,10,100,100)
}
<body>
<canvas width="600px" height="600px"></canvas>
</body>
8.cookie和session的区别
1、存储位置不同
cookie的数据信息存放在客户端浏览器上。
session的数据信息存放在服务器上。
2、存储容量不同
单个cookie保存的数据<=4KB,一个站点最多保存20个Cookie。
对于session来说并没有上限,但出于对服务器端的性能考虑,session内不要存放过多的东西,并且设置session删除机制。
3、存储方式不同
cookie中只能保管ASCII字符串,并需要通过编码方式存储为Unicode字符或者二进制数据。
session中能够存储任何类型的数据,包括且不限于string,integer,list,map等。
4、隐私策略不同
cookie对客户端是可见的,别有用心的人可以分析存放在本地的cookie并进行cookie欺骗,所以它是不安全的。
session存储在服务器上,对客户端是透明对,不存在敏感信息泄漏的风险。
5、有效期上不同
开发可以通过设置cookie的属性,达到使cookie长期有效的效果。
session依赖于名为JSESSIONID的cookie,而cookie JSESSIONID的过期时间默认为-1,只需关闭窗口该session就会失效,因而session不能达到长期有效的效果。
6、服务器压力不同
cookie保管在客户端,不占用服务器资源。对于并发用户十分多的网站,cookie是很好的选择。
session是保管在服务器端的,每个用户都会产生一个session。假如并发访问的用户十分多,会产生十分多的session,耗费大量的内存。
7、浏览器支持不同
假如客户端浏览器不支持cookie:
cookie是需要客户端浏览器支持的,假如客户端禁用了cookie,或者不支持cookie,则会话跟踪会失效。关于WAP上的应用,常规的cookie就派不上用场了。
运用session需要使用URL地址重写的方式。一切用到session程序的URL都要进行URL地址重写,否则session会话跟踪还会失效。
假如客户端支持cookie:
cookie既能够设为本浏览器窗口以及子窗口内有效,也能够设为一切窗口内有效。
session只能在本窗口以及子窗口内有效。
8、跨域支持上不同
cookie支持跨域名访问。
session不支持跨域名访问。
9.普通函数和箭头函数的区别 –
1,语法更加清晰.简洁.
- 普通函数: 不管是声明式函数还是表达式函数,亦或者匿名函数.都必须要关键字
function
.- 箭头函数: 采用箭头=>来定义函数。函数的参数放在=>前面的括号中,函数体跟在=>后的花括号中;
2,箭头函数不会创建自己的this,所以它没有自己的this,它只会从自己的作用域链的上一层继承this。
3, 箭头函数继承而来的this指向永远不变.是继承的它定义时所处的全局执行环境, 之后不再改变
4, 箭头函数继承而来的this指向永远不变.
5, 所以, call(),apply(),bind()无法改变箭头函数中this的指向
6, 箭头函数不能作为构造函数使用.
7, 箭头函数没有自己的arguments.
8, 箭头函数没有原型prototype.
9, 箭头函数不能用作Generator函数,不能使用yeild关键字.
10.怎么实现一个百度搜索框 –
11.vue-router路由的两种模式 --hash history
vue-router 两种模式的区别?
核心答案:
vue-router 有 3 种路由模式:hash、history、abstract。
\1) hash模式:hash + hashChange
特点:
hash虽然在URL中,但不被包括在HTTP请求中用来指导浏览器动作,对服务端安全无用,hash不会重加载页面
通过监听 hash(#)的变化来执行js代码 从而实现 页面的改变
核心代码:
window.addEventListener(‘hashchange‘,function(){
self.urlChange()
})
\2) history模式:historyApi + popState
HTML5推出的history API,由pushState()记录操作历史,监听popstate事件来监听到状态变更;
因为 只要刷新 这个url(www.ff.ff/jjkj/fdfd/fdf/fd)就会请求服务器,然而服务器上根本没有这个资源,所以就会报404,解决方案就 配置一下服务器端。
说明:
1)hash: 使用 URL hash 值来作路由。支持所有浏览器,包括不支持 HTML5 History Api 的浏览器;
2)history : 依赖 HTML5 History API 和服务器配置。具体可以查看 HTML5 History 模式;
3)abstract : 支持所有 JavaScript 运行环境,如 Node.js 服务器端。如果发现没有浏览器的 API,路由会自动强制进入这个模式.
12.内存泄露
闭包长期占用内存,内存消耗很大,可能导致内存泄露
把变量设置为null i=null; //释放内存
14.同步和异步
所有任务可以分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)。
同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;
异步任务指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有等主线程任务执行完毕,"任务队列"开始通知主线程,请求执行任务,该任务才会进入主线程执行。
具体来说,异步运行机制如下:
(1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
(4)主线程不断重复上面的第三步。
16.屏幕分辨率
17.echats
18.用vue进行性能优化
19.如何优化前端页面加载速度 --减少http请求
20.git的常用命令,优势
24.css样式,如何让高永远等于宽的一半(宽可设置,也可不设置)
25.前端性能优化 *****
26.前端的缓存怎么用,关键词是什么
27.jQuery和vue解析方法,交互的封装方法
28.页面的必填校验
29.vue 的生命周期
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gRgClYy6-1635141950354)(C:/Users/yang/Pictures/typora图片/生命周期-16339405116741.png)]
30.vue 的实现原理
32.深拷贝和浅拷贝
主要针对于引用数据类型参数说的,浅拷贝表示仅拷贝引用地址,深拷贝表示对于对象的克隆。
1. 浅拷贝:浅拷贝是只拷贝这个对象的指针,而不是对象本身,新旧对象共用同一个内存地址,修改新对象会影响旧对象。
2. 深拷贝:深拷贝就是新建一个一模一样的对象,新旧对象用的不是同一个内存地址,修改新对象不会影响到旧对象。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8HbHfTyy-1635141950355)(C:/Users/yang/Pictures/typora图片/image-20210927110420617.png)]
如何实现深拷贝?
- 用 JSON.stringify 把对象转换成字符串,再用 JSON.parse 把字符串转换成新的对象
但是需要注意的是
可以转成 JSON 格式的对象才能使用这种方法,如果对象中包含 function 或 RegExp 这些就不能用这种方法了。
- Object.assign()拷贝
当对象中只有一级属性,没有二级属性的时候,此方法为深拷贝,但是对象中有对象的时候,此方法,在二级属性以后就是浅拷贝。
使用递归的方式实现深拷贝
此外,通过jQuery的extend方法实现深拷贝,lodash.cloneDeep()实现深拷贝。
Object.assign()深拷贝还是浅拷贝?
Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
Object.assign()拷贝的是属性值。假如源对象的属性值是一个对象的引用,那么它也只指向那个引用。也就是说,如果对象的属性值为简单类型(如string, number),通过Object.assign({},srcObj);得到的新对象为深拷贝;如果属性值为对象或其它引用类型,那对于这个对象而言其实是浅拷贝的。
34.网页构成三要素// html css javascript
35.http与https的区别
1、HTTPS 协议需要到 CA (Certificate Authority,证书颁发机构)申请证书,一般免费证书较少,因而需要一定费用。(以前的网易官网是http,而网易邮箱是 https 。)
2、HTTP 是超文本传输协议,信息是明文传输,HTTPS 则是具有安全性的 SSL 加密传输协议。
3、HTTP 和 HTTPS 使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
4、HTTP 的连接很简单,是无状态的。HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议,比 HTTP 协议安全。(无状态的意思是其数据包的发送、传输和接收都是相互独立的。无连接的意思是指通信双方都不长久的维持对方的任何信息。)
36.ES6有哪些新特性
1. const 和 let
let
: 声明在代码块内有效的变量。特点:
- 在存在变理提升(不能在变量声明之前使用)
- let的暂时性死区: 其实与1差不多,只要在块作用域有声明,就不能在本作用域声明前用主个变量。
- 不允许重复声明。
const
: 声明一个只读的常量特点:
- 一但声明,这个值不能被改变(对于引用类型,是引用的地址不能被改变)
- 声明时必须赋值
面试中常会问到var let const 三都的区别,回答的时候注重各自的特点,其实const let就是弥补var 的各种缺点,两都的特点就是var 的缺点。
工作中声明变量多用const 和 let
其中当声明的变量为引用类型如Array,如果没有直接更改引用的地址,可以使用const
2. 解构赋值
3. 模板字符串
4. 函头函数
特点:
- 函数体内的this = 定义时所在的对像
- 不可以当作构造函数(不能用new)
- 不可以用arguments对像,可以用rest
- 不可以用yield命令(不能用作Generator函数)
5. 扩展运算符。
- 用于替代数组的
apply
。call apply bind的区别:
用于改变this的指向, 第一个参数为this指向的对像,后面的参数是作为函数的参数。
区加在于:call apply 会即调用,而bind是生成一个等调用的函数。call bind参数是一个个用逗号罗列,而apply 是传入一个数组。6.Promise
是异步编程的一种解决方案它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。
所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。 Promise对象,可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。 Promise对象提供统一的接口,使得控制异步操作更加容易。 1)创建Promise实例 // 实例化 Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject,它们是两个函数 Promise对象代表一个异步操作有三种状态: pending(进行中)、fulfilled(已成功)和rejected(已失败)。 状态发生改变之后就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。
特点:
- 状态不受外界影响(有三种状态:pending, fulfilled,redected)
- 一旦状态改变就不会再变。
用法:
7. Iterator和for…of
Iterator的3个作用:
- 为各种数据提供统一的,简便的访问接口
- 使数据结构的成员能按某种次序排列
- 主要供for…of用
原生有iterator的数据结构:
Array`, `Map`, `Set`, `String`, `TypeArray`, `arguments`, `NodeList
(object是没有的)
for…of与其他循环的比较
- for循环写法比较麻烦
- 数组的forEach: 无法用break;return跳出循环。
- For…in
- 数组的键名是数字,而for…in以字符串作为键名(也就是用for…in循环数组,其键名是字符串,笔者被坑过)
- 不仅可以遍历键名,还可以遍历手动添加的其他键,包括原型链上的
- 某些情况下,会心任意次序遍历
- ( for…in主要为对象而设计的)
8. Generator与async await
generator是ES6提供的一种异步编程解决方案。使异步写法更像同步。
Async await是ES2017的标准,是generator的一个语法糖。
9.Class
产生的原因: 原ES5语法的没有成型的类的概念。而面向对象编程又离不开类的概念。
38.跨域的产生与解决方法 //33.跨域问题。浏览器同源策略,为什么需要同源策略,解决跨域的方法//13.跨域 不同url 不同协议 不同ip 不同端口 jsonp proxy nigx反向代理
一、跨域的形成
跨域 是指浏览器不能执行其他网站的脚本。它是由浏览器的 同源策略 造成的,是浏览器对javascript施加的安全措施。
同源策略 是指:URL的协议,域名、端口都相同。只要其中有一个不同,便会产生跨域。
1.跨域资源共享(CORS)
需要被请求方的服务端设置: Access-Control-Allow-Origin。兼容性不够好,在IE10以下的浏览器不支持。
2.服务器代理
A客户端访问A服务器,并在A服务器上做代理访问B服务器把请求结果返回A客户端,即实现了A客户端请求B服务器的跨域需求。
3.JSONP
原理:所有具有src属性的HTML标签都是可以跨域的,包括
<script><img><iframe>
,所以我们通常会把一些图片资源放到第三方服务器上,然后可以通过标签的src属性引用。
- 首先在客户端注册一个callback, 然后把callback的名字传给服务器。
- 服务器先生成 json 数据。将 json 数据直接以入参的方式,放置到 callback中,这样就生成了一段 js 语法的文档,返回给客户端。
- 客户端浏览器,解析script标签,并执行返回的 javascript 代码,此时数据作为参数,传入到了客户端预先定义好的 callback 函数里.(动态执行回调函数)
39.js判断对象是否为空对象
1.将json对象转化为json字符串,再判断该字符串是否为"{}"
var data = {};
var b = (JSON.stringify(data) == “{}”);
alert(b);//true
2.for in 循环判断
var obj = {};
var b = function() {
for(var key in obj) {
return false;
}
return true;}
alert(b());//true
3.jquery的isEmptyObject方法
此方法是jquery将2方法(for in)进行封装,使用时需要依赖jquery
var data = {};
var b = $.isEmptyObject(data);
alert(b);//true
4.Object.getOwnPropertyNames()方法
此方法是使用Object对象的getOwnPropertyNames方法,获取到对象中的属性名,存到一个数组中,返回数组对象,我们可以通过判断数组的length来判断此对象是否为空
注意:此方法不兼容ie8,其余浏览器没有测试
var data = {};
var arr = Object.getOwnPropertyNames(data);
alert(arr.length == 0);//true
5.使用ES6的Object.keys()方法
与4方法类似,是ES6的新方法, 返回值也是对象中属性名组成的数组
var data = {};
var arr = Object.keys(data);
alert(arr.length == 0);//true
40.防抖和节流
防抖:
高频率触发的事件,在指定的单位时间内,只响应最后一次,如果在指定的时间在触发,则重新计算时间(后面触发的事件执行,替代了前面的事件)
<div id="container"></div> <script> // 演示事件是如何频繁发生的 // 1.获取dom节点 let container = document.querySelector('#container'); let count = 1; function doSomeThing(e) { console.log(this); console.log(e); container.innerHTML = count++ } // container.onmousemove = _.debounce(doSomeThing, 1000); container.onmousemove = debounce(doSomeThing, 1000); // 封装防抖函数 function debounce(fun, wait) { let timeout; return function () { // console.log(this); // console.log(arguments); let context = this; let argus = arguments clearTimeout(timeout) timeout = setTimeout(function () { fun.apply(context, argus) }, wait) } } </script>
节流:
高频率触发的事件,在指定的单位时间内,只响应第一次(前面触发的执行前,忽略后面的事件)
防抖和节流的使用场景
<div id="container"></div> <script> // 演示事件是如何频繁发生的 // 1.获取dom节点 let container = document.querySelector('#container'); let count = 1; function doSomeThing(e) { console.log(this); console.log(e); container.innerHTML = count++ } // container.onmousemove = _.throttle(doSomeThing, 1000); container.onmousemove = throttle(doSomeThing, 1000); // 封装节流函数 使用时间戳封装节流 function throttle(fun, wait) { let old = 0; return function () { // 立即执行 // 获取当前的时间戳 let now = new Date().valueOf(); console.log(now); let context = this; let argus = arguments if (now - old > wait) { // 立即执行 fun.apply(context, argus) // 不满足条件不执行 old = now; } } } </script>
防抖(debounce)
1.search搜索联想,用户在不断输入值时,用防抖来节约请求资源。
2.window触发resize的时候,不断的调整浏览器窗口大小会不断的触发这个事件,用防抖来让其只触发一次节流(throttle)
1.鼠标不断点击触发,mousedown(单位时间内只触发一次)
2.监听滚动事件,比如是否滑到底部自动加载更多,用throttle来判断
41.js怎么使用prototype实现继承
42.es6的promise
43.vue的mixin
3.混入
混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。
第一步定义混合:
{
data(){…},
methods:{…}
…
}第二步使用混入:
全局混入:
Vue.mixin(xxx)
局部混入:mixins:['xxx']
1.全局混入
Tip: 不建议使用全局注册混入对象,一旦使用全局混入,它将会影响以后创建的每一个vue实例。
混入规则
当组件和混入对象有同名选项时,这些选项会以恰当的方式合并
数据 data
数据对象在混入时,会进行合并,发生冲突是,保留组件的数据值为对象 methods computed等
在混入时,同名的methods会合并成为一个对象,如果对象的键名发生冲突,则保留组件对象的键值对生命周期钩子函数
同名的钩子函数会被合并为一个数组,依次都会被调用,但是混入对象的钩子函数先被调用
44.vue怎么监听数据的变化 深度监听
使用watch来响应数据的变化
一般用于异步或者开销较大的操作
watch 中的属性 一定是data 中 已经存在的数据
当需要监听一个对象的改变时,普通的watch方法无法监听到对象内部属性的改变,只有data中的数据才能够监听到变化,此时就需要deep属性对对象进行深度监听watch: {
queryData: {
handler: function() {
//do something
},
deep: true
}
}
请说一下响应式数据的理解?
核心答案:
根据数据类型来做不同处理,数组和对象类型当值变化时如何劫持。
1)对象内部通过defineReactive方法,使用Object.defineProperty() 监听数据属性的 get 来进行数据依赖收集,再通过 set 来完成数据更新的派发;
\2) 数组则通过重写数组方法来实现的。扩展它的 7 个变更⽅法,通过监听这些方法可以做到依赖收集和派发更新;( push/pop/shift/unshift/splice/reverse/sort )
这里在回答时可以带出一些相关知识点 (比如多层对象是通过递归来实现劫持,顺带提出vue3中是使用 proxy来实现响应式数据)
补充回答:
内部依赖收集是怎么做到的,每个属性都拥有自己的dep属性,存放他所依赖的 watcher,当属性变化后会通知自己对应的 watcher去更新。
响应式流程:
1、defineReactive 把数据定义成响应式的;
2、给属性增加一个 dep,用来收集对应的那些watcher;
3、等数据变化进行更新
dep.depend() // get 取值:进行依赖收集
dep.notify() // set 设置时:通知视图更新
这里可以引出性能优化相关的内容:
1)对象层级过深,性能就会差。
2)不需要响应数据的内容不要放在data中。
3)object.freeze() 可以冻结数据。
computed 和 watch 的区别和运用的场景?
核心答案:
computed: 计算属性。依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值;
watch: 监听数据的变化。更多的是「观察」的作用,类似于某些数据的监听回调 ,每当监听的数据变化时都会执行回调进行后续操作;
运用场景:
1)当我们需要进行数值计算,并且依赖于其它数据时,应该使用 computed,因为可以利用 computed 的缓存特性,避免每次获取值时,都要重新计算;
2)当我们需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,使用 watch 选项允许我们执行异步操作 ( 访问一个 API ),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。
47.动态路由
48.vue常用指令
- 属性渲染 v-bind
- 列表渲染 v-for
- 事件渲染 v-on
- 条件渲染 v-show v-if v-else
- v-html
- v-once
50.用flex实现圣杯布局,会压缩左右盒子怎么解决
<style>
* {
margin: 0;
padding: 0;
}
.header,
.footer {
width: 100%;
height: 50px;
background-color: cadetblue;
text-align: center;
line-height: 50px;
}
.content {
display: flex;
text-align: center;
line-height: 200px;
}
.left {
width: 200px;
height: 500px;
background: rosybrown;
}
.center {
height: 500px;
background: salmon;
flex: 1;
}
.right {
width: 200px;
height: 500px;
background: rosybrown;
}
</style>
</head>
<body>
<div class="header">header</div>
<div class="content">
<div class="left">left</div>
<div class="center">center</div>
<div class="right">right</div>
</div>
<div class="footer">footer</div>
</body>
</html>
52.cookie sessionStroge localStorage 区别
共同点:都是保存在浏览器端
区别:
1、cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递,而sessionStorage和localStorage不会自动把数据发送给服务器,仅在本地保存。
2、存储大小限制不同,cookie数据不能超过4K,同时因为每次http请求都会携带cookie、所以cookie只适合保存很小的数据,如会话标识。sessionStorage和localStorage虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大
3、数据有效期不同,sessionStorage:仅在当前浏览器窗口关闭之前有效;localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;cookie:只在设置的cookie过期时间之前有效,即使窗口关闭或浏览器关闭
4、作用域不同,sessionStorage不在不同的浏览器窗口中共享,即使是同一个页面;localstorage在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的
54.webpack模块
五大模块
入口(entry)
入口起点(entry point)指示 webpack 应该使用哪个模块,来作为构建其内部 依赖图(dependency graph) 的开始。进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。
默认值是 ./src/index.js,但你可以通过在 webpack configuration 中配置 entry 属性,来指定一个(或多个)不同的入口起点。输出(output)
output 属性告诉 webpack 在哪里输出它所创建的 bundle,以及如何命名这些文件。主要输出文件的默认值是 ./dist/main.js,其他生成文件默认放置在 ./dist 文件夹中。
Output用于配置打包输出的文件,包括输出文件的文件名、输出路径、静态资源地址,
(1).filename: 配置输出文件名,可添加路径配置(例子中js/)
(2).path: 文件的输出路径,必须是绝对地址
(3).publicPath: 用于设置打包过程中产生的静态文件的最终引用地址,loader加载器 (module)
webpack 只能理解 JavaScript 和 JSON 文件,这是 webpack 开箱可用的自带能力。loader 让 webpack 能够去处理其他类型的文件,并将它们转换为有效 模块,以供应用程序使用,以及被添加到依赖图中。
在更高层面,在 webpack 的配置中,loader 有两个属性:
test 属性,识别出哪些文件会被转换。
use 属性,定义出在进行转换时,应该使用哪个 loader。插件(plugin)
loader 用于转换某些类型的模块,而插件则可以用于执行范围更广的任务。包括:打包优化,资源管理,注入环境变量。
想要使用一个插件,你只需要 require() 它,然后把它添加到 plugins 数组中。多数插件可以通过选项(option)自定义。你也可以在一个配置文件中因为不同目的而多次使用同一个插件,这时需要通过使用 new 操作符来创建一个插件实例。模式(mode)
通过选择 development(生产模式), production(开发模式) 或 none 之中的一个,来设置 mode 参数,你可以启用 webpack 内置在相应环境下的优化。其默认值为 production。
55.vue两大核心
vue.js的两大核心
1.数据驱动
2.组件系统
数据驱动,也就是数据的双向绑定
Vue 响应式核心就是,getter 的时候会收集依赖,setter 的时候会触发依赖更新
vue将遍历data中对象的所有property,并使用 Object.defineProperty 把这些 property 全部转为
getter/setter。这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在 property
被访问和修改时通知变更。每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。
getter的时候我们会收集依赖,依赖收集就是订阅数据变化watcher的收集,依赖收集的目的是当响应式数据发生变化时,能够通知相应的订阅者去处理相关的逻辑。
setter 的时候会触发依赖更新,之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。
组件系统
组件的核心选项
模板(template):模板声明了数据和最终展现给用户的DOM之间的映射关系。
初始数据(data):一个组件的初始数据状态。对于可复用的组件来说,这通常是私有的状态。
接受的外部参数(props):组件之间通过参数来进行数据的传递和共享。
方法(methods):对数据的改动操作一般都在组件的方法内进行。
生命周期钩子函数(lifecycle hooks):一个组件会触发多个生命周期钩子函数,最新2.0版本对于生命周期函数名称改动很大。
私有资源(assets):Vue.js当中将用户自定义的指令、过滤器、组件等统称为资源。一个组件可以声明自己的私有资源。私有资源只有该组件和它的子组件可以调用。
57.路由传参
1、 this.$router.push进行编程式路由跳转
2、 router-link 进行页面按钮式路由跳转
3、 this.$route.params获取路由传递参数
4、this.$route.query获取路由传递参数
5、 params 和 query 都是传递参数的,params不会在url上面出现,并且params参数是路由的一部分,是一定要存在的 query则是我们通常看到的url后面的跟在?后面的显示参数
一、router-link路由导航
父组件: 使用
<router-link to = "/跳转路径/传入的参数"></router-link>
例如:
<router-link to="/a/123">routerlink传参</router-link>
子组件: this.$route.params.num接收父组件传递过来的参数
mounted () { this.num = this.$route.params.num }
路由配置::
{path: '/a/:num', name: A, component: A}
地址栏中的显示::
http://localhost:8080/#/a/123
二、调用$router.push实现路由传参
父组件: 绑定点击事件,编写跳转代码
<button @click="deliverParams(123)">push传参</button> methods: { deliverParams (id) { this.$router.push({ path: `/d/${id}` }) } }
子组件: this.$route.params.id接收父组件传递过来的参数
mounted () { this.id = this.$route.params.id }
路由配置::
{path: '/d/:id', name: D, component: D}
地址栏中的显示::
http://localhost:8080/#/d/123
三、通过路由属性中的name匹配路由,再根据params传递参数
父组件: 匹配路由配置好的属性名
<button @click="deliverByName()">params传参</button> deliverByName () { this.$router.push({ name: 'B', params: { sometext: '一只羊出没' } }) }
子组件:
<template> <div id="b"> This is page B! <p>传入参数:{{this.$route.params.sometext}}</p> </div> </template>
路由配置: 路径后面不需要再加传入的参数,但是name必须和父组件中的name一致
{path: '/b', name: 'B', component: B}
地址栏中的显示: 可以看出地址栏不会带有传入的参数,且再次刷新页面后参数会丢失
http://localhost:8080/#/b
四、通过query来传递参数
父组件:
<button @click="deliverQuery()">query传参</button> deliverQuery () { this.$router.push({ path: '/c', query: { sometext: '这是小羊同学' } }) }
子组件:
<template> <div id="C"> This is page C! <p>这是父组件传入的数据: {{this.$route.query.sometext}}</p> </div> </template>
路由配置: 不需要做任何修改
{path: '/c', name: 'C', component: C}
地址栏中的显示: (中文做了转码)
http://localhost:8080/#/c?sometext=%E8%BF%99%E6%98%AF%E5%B0%8F%E7%BE%8A%E5%90%8C%E5%AD%A6
58.组件缓存
keep-alive
keep-alive是Vue提供的一个抽象组件,用来对组件进行缓存,从而节省性能,由于是一个抽象组件,所以在v页面渲染完毕后不会被渲染成一个DOM元素
当组件在keep-alive内被切换时组件的activated、deactivated这两个生命周期钩子函数会被执行
被包裹在keep-alive中的组件的状态将会被保留,例如我们将某个列表类组件内容滑动到第100条位置,那么我们在切换到一个组件后再次切换回到该组件,该组件的位置状态依旧会保持在第100条列表处
59.vuex优点,应用场景
60.说下从输入网址到页面显示的过程
\1) 在客户端浏览器中输入网址URL。
\2) 发送到DNS(域名服务器)获得域名对应的WEB服务器的IP地址。***//DNS解析, 将域名解析成IP地址***
\3) 客户端浏览器与WEB服务器建立TCP(传输控制协议)连接。***//TCP连接: TCP三次握手***
\4) 客户端浏览器向对应IP地址的WEB服务器发送相应的HTTP或HTTPS请求。***//发送HTTP请求***
\5) WEB服务器响应请求,返回指定的URL数据或错误信息;如果设定重定向,则重定向到新的URL地址。 //服务器处理请求并返回HTTP报文
\6) 客户端浏览器下载数据,解析HTML源文件,解析的过程中实现对页面的排版,解析完成后,在浏览器中显示基础的页面。***//浏览器解析渲染页面***
\7) 分析页面中的超链接,显示在当前页面,重复以上过程直至没有超链接需要发送,完成页面的全部显示。***//断开连接: TCP四次挥手***
61.说一下Promise是什么
62.async
63.双向数据绑定
64.this指向问题
65.构造函数怎么理解,实例怎么理解
66.七层协议和四层协议
67.vue-router,守卫有什么作用,怎么监听url地址栏中参数变化
68.讲讲你所学的编程语言中的两种,并比较区别
69.vue3中的setup
70.hash模式和history模式的区别,以及如何解决history刷新后报错的问题
71.如何实现vue中插件的封装
72.v-if和v-for怎么才能一起使用
73.返回原数组的方法有哪些
74.输入url到页面加载完成发生了什么
75.less中怎么定义使用变量
76.匿名函数
77.对vue缓存的理解
78.vue的内置命令有哪些
typeof有哪些,typeof NaN,typeof null返回什么