目录
一、canvas:
(1)创建canvas标签:
(2)使用JS获得这个canvas标签的DOM对象:
(3)决定是画二维还是三维的画:
(4)API:
(5)截图:
二、QPS(每秒查询率)达到峰值时, 该如何处理?
(1)数据库优化:
(2)缓存优化:
(3)代码优化:
(4)负载均衡:
(5)异步处理:
(6)CDN加速:
(7)硬件升级:
三、js 超过 Number 最大值的数怎么处理
四、常见的块元素、行内元素以及行内块元素,三者有何不同?
(1)块级元素(Block Elements)
(2)行内元素(Inline Elements)
(3)行内块级元素(Inline-Block Elements)
五、HTML、XML、XHTML它们之间有什么区别?
七、网站TDK三大标签以及SEO优化:
(1)TDK标签:
(2)SEO优化(搜索引擎优化):
(3)如何实现搜索引擎优化(SEO)
1.关键词研究与选择
2.网站内容优化
3.网站结构优化
4.外部链接建设
5.网站速度优化
6.移动优化
八、img标签的title属性与alt属性的区别是什么?
九、src 和 href 的区别、title 与 h1 的区别、b 与 strong 的区别、i 与 em 的区别?
(1)src 和 href 的区别
(2)title与h1的区别
(3)b 与 strong 的区别
(4)i 与 em 的区别
十、iframe的优点和缺点 ?
优点:
缺点:
十一、 link 与 @import 的用法和区别?
用法:
区别:
1、从属关系区别
2、加载顺序区别
3、兼容性区别
4、DOM可控性区别
十二、rgba和opacity的透明效果有什么不同?
(1)取值范围不同:
(2)透明计算方式不同:
(3)rgba和opacity的兼容性问题:
(4)应用场景不同:
十四、定位布局 position中的relative、absolute、fixed、sticky它们之间的区别?
十五、CSS3盒子模型:标准盒模型、怪异盒模型
十六、浮动(float)以及清除浮动的方法
浮动特点:
清除浮动:
十七、伪元素和伪类的区别和作用?
伪元素:
伪类:
十八、img 的 alt 与 title 的异同,还有实现图片懒加载的原理是什么?
异同:
图片懒加载:
1、概念:
2、作用:
3、原理:
十九、BFC 是什么?
BFC的布局规则
触发BFC
二十、JS基础类型和复杂类型
JS数据基础类型有:
JS有三种 复杂类型 (引用数据类型):
二十一、箭头函数与普通函数的区别?
二十二、JS中null和undefined的判断方法和区别?
判断方法:
区别:
二十三、原型链
二十四、v-show 与 v-if 的区别?
二十五、keep-alive 的作用是什么?
主要作用:
二十六、闭包的理解
概念:
特点:
优点:
缺点:
用途:
二十七、JS垃圾回收机制及内存泄漏
垃圾回收机制:
标记清除方式(最常见)
引用计数方式
内存泄漏:
二十八、nextTick的实现
概念:
使用场景:
二十九、混入mixin的原理
Mixin和Vuex的区别:
三十、js列举和数组操作相关的方法(常用)
添加元素
删除元素
查找元素
排序和翻转
遍历和过滤
归并数组
其它方法
三十一、typeof和instanceof的区别?
三十二、JS中 “==”和“===”的区别?
三十三、var、let和const的区别?
三十四、js的call、apply和bind区别?
概念:
区别:
三十五、Webpack
概念:
Webpack的基本功能有哪些?
Webpack构建过程?
Loader和Plugin的区别?
如何优化 Webpack 的构建速度?
Webpack 的热更新原理:
什么是bundle?什么是chunk?什么是module?
webpack和grunt以及gulp有什么不同?
三十六、const定义的对象属性是否可以改变?
三十七、栈溢出及解决方法?
栈溢出(stack Overflow):
栈溢出的解决方法:
三十八、JS如何实现多线程?
多线程概念:
实现多线程的方式:
如何保证多线程安全?
三十九、浅拷贝和深拷贝区别?
浅拷贝
深拷贝
区别:
四十、事件循环,Promise和async/await
事件循环event loop它的执行顺序:
Promise:
async/await:
Promise和async/await的区别:
JavaScript的异步机制包括以下几个步骤:
链式调用
链式调用的基本步骤包括:
四十一、Vuex
Vuex主要包括以下几个核心模块:
四十二、vue 的生命周期(八个阶段)
1、beforeCreate
2、created
3、beforeMount
4、mounted
5、beforeUpdate
7、beforeDestroy
8、Destroyed
四十三、Vue每个周期具体适合哪些场景?
四十四、简述MVVM 和MVC的原理以及区别?
1、MVVM的优点:
2、什么是MVC?
3、MVC的优点:
4、MVC与MVVM的区别?
四十五、vue常见指令
四十六、vue中的data为什么是一个函数?起到什么作用?
四十七、vue中ref的作用?
1、获取DOM元素的引用:
2、获取子组件的引用:
3、利用 v-for 和 ref 获取一组数组或者dom 节点
四十八、vue中hash和history的区别 ?
四十九、Vue2.0和Vue3.0的区别?
五十、Vue3带来了什么改变?
性能的提升:
源码的升级:
拥抱TypeScript:
新的特性:
Composition API(组合API)
新的内置组件
其他改变
五十一、vue2.0的响应式原理是什么?vue3.0的响应式原理是什么?
vue2.x的响应式:
Vue3.0的响应式:
五十二、什么是 JSX ?
JSX的特点:
五十三、React 的生命周期方法有哪些?
挂载阶段:
更新阶段:
卸载阶段:
五十四、React中的Hooks是什么?
Hook是什么:
React常用Hooks列表:
五十五、React和Vue.js的相似性和差异性是什么?
相似性:
差异性:
五十六、React
React的主要功能:
React的一些主要优点:
React的局限性:
React的特点:
五十七、React State不可变性的原则
关键点:
好处:
五十八、uniapp优缺点
优点
缺点
五十九、uniapp目录结构
六十、uniapp 常用的指令语句
六十一、uniapp 应用的生命周期、页面的生命周期、组件的生命周期
应用的生命周期:
页面的生命周期:
组件的生命周期:
六十二、Git和SVN有什么区别?
一、canvas:
是一个容器,可以使用JS在其中绘制图形或文字。
(1)创建canvas标签:
<canvas id="canvas" height="600" width="700"></canvas>
(2)使用JS获得这个canvas标签的DOM对象:
<script>
const canvas = document.getElementById('canvas')
</script>
(3)决定是画二维还是三维的画:
<script>
const ctx = canvas.getContext('2d')
</script>
(4)API:
-
moveTo(x,y)
:定义画线的起始点; -
lineTo(x,y)
:定义画线的折点; -
stroke()
:通过线条来绘制图形轮廓; -
arc(x, y, radius, startAngle, endAngle, anticlockwise):
绘制圆(默认顺时针);
-
ctx.setLineDash([10, 30, 5]):绘制虚线。
(5)截图:
调⽤ Canvas API 中的 toDataURL () ⽅法将 Canvas转化为 base64 编码的图⽚数据。
二、QPS(每秒查询率)达到峰值时, 该如何处理?
(1)数据库优化:
数据库的优化包括优化SQL语句、使⽤索引、避免全表扫描、分表分库等措施 ,以提高数据库的读写性能。
(2)缓存优化:
缓存可以降低对数据库的访问频率,提⾼响应速度。可以使⽤Redis、Memcached等缓存技术,减轻服务器负载。
(3)代码优化:
优化代码可以提⾼代码的执⾏效率 ,减少不必要的开销。可以通过⼀些优化⼿段,如减少不必要的代码执⾏、避免循环嵌套、避免不必要的递归调⽤等来提⾼代码的性能。
(4)负载均衡:
负载均衡可以将请求分发到多个服务器上,减少单个服务器的负载,提⾼整个系统的性能和可⽤性。
(5)异步处理:
将⼀些计算量⼤、耗时⻓的操作异步处理,减少对主线程的阻塞,提⾼响应速度。
(6)CDN加速:
使⽤CDN技术可以将静态资源缓存到CDN节点上,提⾼资源的加载速度,减少服务器的负载。
(CDN的基本原理:广泛采用各种缓存服务器,将这些缓存服务器分布到用户访问相对集中的地区或网络中;在用户访问网站时,利用全局负载技术将用户的访问指向距离最近的工作正常的缓存服务器上,由缓存服务器直接响应用户请求。)
(7)硬件升级:
可以通过升级服务器硬件,增加带宽等⽅式来提⾼系统的处理能⼒。
三、js 超过 Number 最大值的数怎么处理
使⽤第三⽅的 JavaScript 库,如 big.js 或 bignumber.js,这些库可以处理任意精度的数值;或者使用使⽤ BigInt类型来处理,它可以表⽰任意精度的整数,通过在数值后⾯添加⼀个后缀n来表⽰ BigInt 类型。
四、常见的块元素、行内元素以及行内块元素,三者有何不同?
(1)块级元素(Block Elements)
-
占整行,可以包含其他块级或行内元素。
-
默认宽度100%。
-
可设置宽高、内外边距。 例子:
<div>
,<p>
,<h1>
等。
(2)行内元素(Inline Elements)
-
和其他元素在同一行显示。
-
只占用所需宽度。
-
不可直接设置宽高。 例子:
<span>
,<a>
,<img>
等。
(3)行内块级元素(Inline-Block Elements)
-
同一行内显示,但可以设置宽高。
-
不可包含块级元素。
-
可设置内外边距。通过CSS设置:
display: inline-block;
例子:通常通过CSS将<div>
等变为行内块级元素。
五、HTML、XML、XHTML它们之间有什么区别?
-
HTML(HyperText Markup Language)主要用于描述网页的内容及其结构,它较为宽松,允许一些语法上的灵活性。
-
XML(eXtensible Markup Language)则是一种更为严格的语言,设计用于传输和存储数据,而不是展示数据。XML强调的是文档的一致性和格式的正确性,不允许有语法错误。
-
而XHTML(eXtensible HyperText Markup Language)是HTML向XML语法的一个过渡,它结合了HTML的内容描述能力和XML的严格规范,意味着所有的文档都应当是良好形成的(well-formed),并且遵循XML的规则,如所有标签必须关闭等。
六、session、cookie、token的区别?
-
Session 是一种服务器端技术,用来跟踪用户的活动。当用户访问网站时,服务器可能会创建一个唯一的 session ID,并且存储有关这个用户的会话信息,如登录状态等。这些信息通常保存在服务器的内存或数据库中,以便后续请求可以恢复会话状态。(仅在当前浏览器窗口关闭之前有效)
-
Cookie 是一种客户端技术,用于存储小块的数据到用户的浏览器上。当服务器需要记住某些关于用户的信息时,它可以在用户的计算机上设置一个 cookie。每次用户请求资源时,浏览器都会自动将相关的 cookies 发送到服务器,这样服务器就知道该用户之前有过交互行为。(只在设置的 cookie 过期时间之前有效,即使窗口关闭或浏览器关闭)
-
Token 则是一种轻量级认证机制,通常用于无状态的应用程序设计中。当用户成功登录后,服务器会生成一个 token 并返回给客户端。之后,客户端会在每个请求中包含这个 token,而服务器只需要验证 token 的有效性即可,不需要查询任何会话信息。这种方式减轻了服务器的负担,并且可以更容易地支持水平扩展。
-
cookie 的有效期可以设置较长时间,session 有效期都比较短。
七、网站TDK三大标签以及SEO优化:
(1)TDK标签:
-
Title Tag(标题标签):这是HTML文档中的
<title>
元素,显示在浏览器标签页上,并且是搜索引擎结果页面(SERP)中每个结果的第一行文字。一个好的标题应该包含关键字,准确描述页面内容,并且具有吸引力以鼓励点击。 -
Description Meta Tag(描述元标签):这是HTML中的
<meta name="description" content="...">
标签,通常用于描述页面内容的简短摘要。搜索引擎会使用这段描述作为搜索结果的一部分,因此它应该清晰地概述页面的主要内容,并包含相关的关键词。 -
Keywords Meta Tag(关键词元标签):这是
<meta name="keywords" content="...">
标签,用于列出页面的相关关键词。虽然它在过去对于SEO非常重要,但现在大多数主要搜索引擎已经不再考虑这个标签了。
(2)SEO优化(搜索引擎优化):
搜索引擎优化(Search Engine Optimization,简称SEO)是指通过优化网站的内容、结构和相关参数,使其更符合搜索引擎的算法规则,从而提高网站在搜索引擎结果页面中的排名,增加有针对性的流量,并最终实现网站的推广和营销目标。
(3)如何实现搜索引擎优化(SEO)
1.关键词研究与选择
关键词是指用户在搜索引擎中输入的词语,对于SEO而言非常重要。首先需要进行关键词研究,了解用户搜索的热点和趋势,以及竞争对手的情况。然后选择适合自己网站的关键词,并在网站的内容、标题、标签等位置合理地使用这些关键词。
2.网站内容优化
在SEO中,内容是至关重要的因素。优质的内容能够吸引用户的点击和阅读,也能被搜索引擎更好地收录和展示。因此,要提升网站的排名,需要不断更新高质量、原创的内容,并注意保持内容的相关性和完整性。
3.网站结构优化
良好的网站结构可以为搜索引擎提供更好的索引和跟踪网页的能力,从而提高网站的可访问性和可读性。
优化网站结构包括:设计清晰的导航菜单、构建良好的内部链接、使用简洁而有意义的URL地址等。
4.外部链接建设
外部链接是指其他网站指向自己网站的链接,也被称为反向链接。外部链接的质量和数量对于网站的排名有重要影响。建立高质量的外部链接,可以通过与行业相关的博客、论坛、社交媒体平台等发布有价值的内容,并引导用户到自己的网站去。
5.网站速度优化
网站的加载速度对用户体验和搜索引擎排名都至关重要。
优化网站的速度可以采取以下措施:优化图片大小和格式、减少HTTP请求、压缩代码、使用CDN服务等。
6.移动优化
随着移动设备的普及,移动优化已成为搜索引擎优化中不可忽视的一部分。确保网站能够在各种移动设备上正常显示,并且具备良好的移动用户体验。
八、img标签的title属性与alt属性的区别是什么?
-
alt
是给搜索引擎识别,在图像无法显示时的替代文本; -
title
属性是关于元素的注释信息,主要是给用户解读。
九、src 和 href 的区别、title 与 h1 的区别、b 与 strong 的区别、i 与 em 的区别?
(1)src 和 href 的区别
-
src
(source):这个属性用于指定一个资源的URL,这个资源是当前元素要加载的目标。通常用在<img>
,<script>
,<link>
,<iframe>
等标签中。例如,在<img>
标签中使用src
来指定图片文件的位置;在<script>
标签中,src
属性定义了外部JavaScript文件的位置。 -
href
(hypertext reference):这个属性用来创建一个到其他文档或资源的链接。它主要用于<a>
(锚点)标签来创建超链接,也可以用在<link>
标签中来引用样式表等资源。
(2)title与h1的区别
-
title
元素位于HTML文档的<head>
部分,并且只能出现一次。它定义了浏览器工具栏的标题,以及当页面被加入收藏夹或出现在搜索引擎结果中时所使用的标题;title
元素的内容不会显示在网页的主要内容区域,而是显示在浏览器标签页的标题上。 -
<h1>
元素则位于<body>
部分,它是页面中的主要标题,用于强调最重要的内容。在一个良好的文档结构中,通常只有一个<h1>
作为主标题,尽管HTML5规范并不强制要求如此(即可以有多个<h1>
);<h1>
内容会直接显示在网页上,并且对SEO(搜索引擎优化)有一定的影响。
(3)b 与 strong 的区别
-
<b>
标签是一个纯表现层的标签,它仅仅用于改变文本的样式,使其变为粗体。它不传达任何关于文本的重要性或意义的信息。在过去,<b>
被广泛用于仅仅是视觉上的加粗文本。 -
strong标签更注重于内容上的应用,在html中,对关键词的标明,然而还有一些网站上,也有使用strong标签登对小标题进行强调,但是在页面中,如果出现过多的strong标签,可能会对排名不利。
(4)i 与 em 的区别
-
<i>
标签是一个纯表现层的标签,它没有特定的语义含义,主要用于改变文本的样式为斜体。它可以用来表示多种类型的文本,比如声音、电影名、外文短语、思想、船名等。然而,由于<i>
缺乏明确的语义,它的使用不如<em>
推荐。 -
<em>
标签则具有明确的语义含义。它用于强调文本的一部分。当浏览器解析到<em>
标签时,它会认为这部分文本是有特别强调的。对于辅助技术,如屏幕阅读器,这非常重要,因为它可以根据这一点来调整语音语调,以帮助视力受限的用户更好地理解哪些部分是强调的重点。同时,搜索引擎也可能认为<em>
标签内的文字更具有相关性,从而影响搜索排名。
十、iframe的优点和缺点 ?
iframe
(内嵌框架)是 HTML 中一种用于将一个网页嵌入到另一个网页中的标签,它可以在一个页面中显示来自其他页面的内容。在网页中,使用<iframe>
标签可以将一个网页嵌套在另一个网页中,实现网页间的互联互通。
基本用法:<iframe src="URL"></iframe>
优点:
1.独立性:iframe可以在页面上独立显示一个页面或者内容,不会与页面其他元素产生冲突。
2.可重用性:iframe可以在多个页面中重用同一个页面或者内容,可以减少代码的冗余。
3.异步加载:iframe的加载是异步的,页面可以在不等待 iframe 加载完成的情况下进行展示。
4.方便实现跨域访问:使用iframe可以方便地实现跨域访问,这在某些场景下非常有用。
缺点:
1.安全问题:iframe 可以嵌入来自其他网站的内容,这可能会导致安全问题,例如点击劫持等攻击。
2.SEO问题:搜索引擎可能无法正确解析 iframe 中的内容,这可能会影响页面的搜索排名。
3.页面加载速度:iframe中的内容需要额外的 HTTP 请求和页面加载时间,这可能会影响整个页面的加载速度。
4.可访问性问题:有些屏幕阅读器可能无法正确读取 iframe 中的内容,这会影响可访问性。
十一、 link 与 @import 的用法和区别?
用法:
<link>
是 HTML 文档中的一个标签,通常用于定义文档与外部资源的关系。当 <link>
标签的 rel
属性设置为 "stylesheet"
时,它用来链接一个 CSS 文件到 HTML 文档中。<link>
标签应该放在文档的 <head>
部分。
<head>
<link rel="stylesheet" type="text/css" href="styles.css">
</head>
@import
是 CSS 中的一个规则,它允许在样式表内部导入其他的样式表。@import
可以放在任何有效的 CSS 代码的位置,但在实际使用中通常位于文件的顶部。
/* styles.css */
@import url('other-styles.css');
body {
background-color: lightblue;
}
区别:
1、从属关系区别
link是HTML提供的标签,不仅可以加载 CSS 文件,还可以定义 RSS、rel 连接属性等;
@import是 CSS 提供的语法规则,只有导入样式表的作用。
2、加载顺序区别
加载页面时,link标签引入的 CSS 被同时加载;
@import引入的 CSS 将在页面加载完毕后被加载。
3、兼容性区别
link标签作为 HTML 元素,不存在兼容性问题;
@import是 CSS2.1 才有的语法,故只可在 IE5+ 才能识别。
4、DOM可控性区别
可以通过 JS 操作 DOM ,插入link标签来改变样式;
由于 DOM 方法是基于文档的,无法使用@import的方式插入样式。
十二、rgba和opacity的透明效果有什么不同?
(1)取值范围不同:
rgba用于设置一种颜色,并且可以指定其透明度,而opacity只能指定所有内容(包括文本、图片等)的总体透明度。
rgba的取值范围是0-255,代表红、绿、蓝三个颜色通道的色值和一个透明度通道,而opacity的取值范围是0-1,其中0表示完全透明,1表示完全不透明。
(2)透明计算方式不同:
在浏览器渲染时,当元素使用rgba设置透明度时,计算方式是通过将该元素与其下方的背景色混合来实现的,这意味着元素的透明度也可以影响到下面的元素。
而opacity属性则是直接作用于整个元素,从而使元素内部的所有内容变得更加透明。
(3)rgba和opacity的兼容性问题:
rgba则是CSS3中的属性,在一些旧版本的浏览器中可能会出现兼容性问题,需要额外做一些兼容性处理;
而opacity是CSS2规范中的属性,对于所有支持CSS2的浏览器都有较好的兼容性。
(4)应用场景不同:
由于rgba可以更精确地控制元素的透明度,因此它更适合处理需要不同透明度的颜色背景。
而opacity则更适合处理所有内容都需要透明度的情况,例如模态框、滤镜效果等。
十三、display:none与visibility:hidden的区别?
display:none
和 visibility:hidden
都可以用来控制网页元素的可见性,但是它们的作用方式有所不同:
-
display:none
会使得元素不会被渲染,并且不会占据页面上的任何空间,就好像该元素不存在于文档流中一样,display:none
的元素则不会接收任何用户事件。 -
相反地,
visibility:hidden
会让元素在视觉上变得不可见,但是元素仍然存在于文档流中并保留其原本的空间位置。此外,visibility:hidden
的元素虽然不可见,但仍然可以接收用户事件,比如点击。
十四、定位布局 position中的relative、absolute、fixed、sticky它们之间的区别?
-
relative
定位的元素相对于其正常位置进行定位。当设置了top
,right
,bottom
, 或left
属性后,元素会在其原始位置的基础上移动指定的偏移量,但是它的移动不会影响其他元素的位置。 -
absolute
定位的元素相对于最近的已定位祖先元素进行定位,如果找不到已定位的祖先,则相对于初始包含块(通常是<html>
元素)。这种定位方式使得元素可以从文档流中移除,因此不会影响到其它元素的位置。 -
fixed
定位的元素相对于浏览器窗口进行定位,而不是相对于文档或其他元素。即使页面滚动,元素的位置也保持不变。这通常用于创建固定导航栏等。 -
sticky
定位的元素在跨越特定边界之前表现为相对定位,一旦跨越设定边界,则转变为固定定位直到另一边界出现或到达视口底部。这种定位非常适合创建当用户滚动页面时暂时固定在视口中的头部或侧边栏。
十五、CSS3盒子模型:标准盒模型、怪异盒模型
在W3C 标准的盒子模型(标准盒模型)中,元素的实际宽度是 width
加上左右内边距 (padding
) 和左右边框 (border
) 的总和。同样,高度则是 height
加上上下内边距和上下边框的总和。这意味着当你设置一个元素的宽度为100px,实际占据的空间会比这个值更大,因为还要包括内边距和边框的宽度。
相比之下,在IE盒模型(或称怪异盒模型)中,元素的宽度 (width
) 包括了内边距和边框,即元素的总宽度就是 width
的值。高度也是同样的道理,它包含了上下内边距和上下边框。这意味着,当设置一个元素的宽度为100px时,这个元素的宽度将包括所有内边距和边框,实际内容区域可能会小于100px。
十六、浮动(float)以及清除浮动的方法
float
属性用于控制元素的浮动行为,当一个元素设置了浮动之后,它会尽可能地向容器的一侧靠近,并且可能会影响其周围元素的布局。
浮动特点:
-
脱离文档流:浮动元素不再占据文档流中的位置,其他元素会围绕浮动元素进行排列。
-
元素块化:浮动元素表现为块级元素,会独占一行或一块空间。
-
水平移动:浮动元素默认是水平移动的,可以通过设置
float: left;
或float: right;
来控制移动方向。
清除浮动:
-
使用
clear
属性:可以在元素自身上使用clear:both;
来确保该元素的上下方都不允许有浮动元素。但是这种方法并不总是能解决所有问题,因为它只是影响当前元素而不作用于父级容器。 -
使用伪元素清除法:可以创建一个伪元素(如
:before
或:after
)并应用clear:both;
或clearfix
类来清除内部浮动的影响。
.parent::after {
content: "";
display: block;
clear: both;
}
-
使用
overflow
属性:将父级容器的overflow
设置为auto
或hidden
可以触发BFC(Block Formatting Context),这也会自动清除内部的浮动元素。注意这样做会使元素不可滚动,如果内容超出容器范围的话。 -
使用 Flexbox 或 Grid 布局:在支持Flexbox或Grid布局的浏览器中,可以使用现代布局模式来代替浮动,因为这两种布局模式提供了更强大且更灵活的方式来排列元素,并且不需要额外的清除技术。
-
使用
display: flex;
(弹性盒子)或display: grid;(网格布局)
:如果整个容器中的子元素都是通过浮动来定位的,那么可以将容器本身的display
属性改为flex
或grid
,这样所有的子元素都会按照新的显示模式重新排列,并且不会有浮动相关的布局问题。
十七、伪元素和伪类的区别和作用?
伪元素:
在内容元素的前后插入额外的元素或样式,但是这些元素实际上并不在文档中生成。它们只在外部显示可见,但不会在文档的源代码中找到它们,因此,称为“伪”元素。
p::before {content:"第一章:";}
p::after {content:"Hot!";}
p::first-line {background:red;}
p::first-letter {font-size:30px;}
伪类:
将特殊的效果添加到特定选择器上。它是已有元素上添加类别的,不会产生新的元素。
a:hover {color: #FF00FF}
p:first-child {color: red}
十八、img 的 alt 与 title 的异同,还有实现图片懒加载的原理是什么?
异同:
-
alt 是图片加载失败时,显示在网页上的替代文字; title 是鼠标放上面时显示的文字, title 是对图片的描述与进一步说明;
-
alt 是 img 必要的属性,而 title 不是;
-
对于网站 seo 优化来说,title 与 alt 还有最重要的一点: 搜索引擎对图片意思的判断,主要靠 alt 属性。所以在图片 alt 属性中以简要文字说明,同时包含关键词,也是页面优化的 一部分。条件允许的话,可以在 title 属性里,进一步对图片说明,由于过多的图片会严重影响网页的加载速度,并且移动网络下的流量消耗巨大,所以说延迟加载几乎是标配了。
图片懒加载:
1、概念:
图片懒加载是一种延迟加载图片的技术,只在图片即将进入可视区域时才开始加载。这与传统的立即加载所有图片的方式不同,懒加载可以提高页面的加载性能,尤其对于包含大量图片的页面更为有效。
2、作用:
(1)减少初始页面加载时间: 随着页面的增大,加载所有图片可能导致较长的初始加载时间。图片懒加载允许浏览器仅加载可视区域内的图片,加快了页面的首次加载。
(2)节省带宽和服务器资源: 当页面中包含大量图片时,仅加载用户实际查看的部分可以减少不必要的带宽消耗和服务器资源。
(3)优化用户体验: 用户在滚动页面时,仅当图片进入可视区域时才加载,提高了用户体验,尤其在移动设备上更为显著。
3、原理:
页面中的img元素,如果没有src属性,浏览器就不会发出请求去下载图片,只有通过javascript设置了图片路径,浏览器才会发送请求。懒加载的原理就是先在页面中把所有的图片统一使用一张占位图进行占位,把真正的路径存在元素的“data-url”(这个名字起个自己认识好记的就行)属性里,当js监听到该图片元素进入可视窗口时,即将自定义属性中的地址存储到src属性中,达到懒加载的效果。
十九、BFC 是什么?
BFC (Block formatting context) 直译为 "块级格式化上下文"。指浏览器中创建了一个独立的渲染区域,并且拥有一套渲染规则,他决定了其子元素如何定位,以及与其他元素的相互关系和作用。即,BFC
是一个完全独立的空间(布局环境),让空间里的子元素不会影响到外面的布局。
BFC的布局规则
-
内部的Box会在垂直方向,一个接一个地放置。
-
Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠 。
-
从左往右的格式化,包括浮动。
-
BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
-
计算BFC的高度时,浮动元素也参与计算。
触发BFC
-
position
:absolute
、fixed
; -
display
:inline-block
、flex
、inline-flex
、grid
、inline-grid
、flow-root(推荐)
; -
overflow
值不为visible
的块元素(overflow:auto;推荐)。
二十、JS基础类型和复杂类型
JS数据基础类型有:
String、Number、Boolean、Null、undefined五种基本数据类型,加上新增的两种ES6的类型Symbol、BigInt。
JS有三种 复杂类型 (引用数据类型):
Object(对象)、Array(数组)、function(函数)。
二十一、箭头函数与普通函数的区别?
// 普通函数
let sum = function(a, b) {
return a + b;
}
// 箭头函数
let sum1 = (a, b) => {
return a + b;
}
-
外形不同:箭头函数使用箭头定义,普通函数中没有。
-
箭头函数全都是匿名函数;普通函数可以有匿名函数,也可以有具名函数。
-
箭头函数不能用于构造函数;普通函数可以用于构造函数,以此创建对象实例。
-
箭头函数中 this 的指向不同;在普通函数中,this 总是指向调用它的对象,如果用作构造函数,它指向创建的对象实例。
-
箭头函数不具有 arguments 对象;每一个普通函数调用后都具有一个arguments 对象,用来存储实际传递的参数。但是箭头函数并没有此对象。
-
其他区别:箭头函数不具有 prototype 原型对象;箭头函数不具有 super;箭头函数不具有 new.target。
二十二、JS中null和undefined的判断方法和区别?
判断方法:
-
使用
typeof
操作符:
console.log(typeof undefined); // 输出 "undefined"
console.log(typeof null); // 输出 "object" (这是一个历史遗留问题)
-
比较运算符:
使用 ==
运算符,undefined
和 null
是相等的,因为它们都会进行类型转换:
console.log(undefined == null); // 输出 true
使用 ===
运算符,它们是不相等的,因为 ===
不会进行类型转换:
console.log(undefined === null); // 输出 false
区别:
-
类型:
-
undefined
是变量未赋值时的默认值。如果声明了一个变量而没有给它赋值,它的值就是undefined
。 -
null
是一个明确的值,表示“没有对象”(即该处没有任何东西),通常用来表示尚未指定的对象值或者作为算法中的占位符。
-
-
数据类型:
-
undefined
是一种原始数据类型,它只有单一的值undefined
。 -
null
同样是一种原始数据类型,但它的值是固定的null
。
-
二十三、原型链
(1)prototype:所有的函数都有原型prototype属性,这个属性指向函数的原型对象。
(2) __proto__,这是每个对象(除null外)都会有的属性,叫做__proto__,这个属性会指向该对象的原型。
(3)constructor: 每个原型都有一个constructor属性,指向该关联的构造函数。
原型链:获取对象时,如果这个对象上本身没有这个属性时,它就会去它的原型__proto__上去找,如果还找不到,就去原型的原型上去找……直到找到最顶层(Object.prototype)为止。Object.prototype对象也有__proto__属性,值为null。
此外,每一个prototype原型上都会有一个constructor属性,指向它关联的构造函数。
二十四、v-show 与 v-if 的区别?
-
v-show
指令是通过修改元素的display
的CSS
属性让其显示或者隐藏; -
v-if
指令是直接销毁和重建DOM
达到让元素显示和隐藏的效果; -
使用
v-show
会更加节省性能上的开销; -
当只需要一次显示或隐藏时,使用
v-if
更加合理。
二十五、keep-alive 的作用是什么?
Keep-Alive是一种HTTP协议中的机制,它的作用是在客户端和服务器之间保持持久的网络连接,以减少连接建立和断开的开销。当启用Keep-Alive时,同一客户端和服务器之间的多个HTTP请求可以共享同一个TCP连接,而无需每次请求都进行连接的建立和关闭。
主要作用:
1. 减少连接建立开销:在没有Keep-Alive的情况下,每次HTTP请求都需要经过TCP三次握手建立连接,这会导致较大的延迟和资源消耗。而使用Keep-Alive,可以在一个TCP连接上发送多个HTTP请求,减少了建立连接的开销。
2. 降低网络负载:每次建立和关闭连接时,都会消耗网络带宽和服务器资源。通过保持持久连接,可以减少连接的频繁建立和关闭,从而降低了网络负载和服务器负载。
3. 提高性能和响应时间:由于避免了连接建立和关闭的开销,Keep-Alive可以提高请求的响应时间和整体性能。客户端可以在同一个连接上连续发送请求,而服务器也可以在保持连接的情况下更快地响应这些请求。
4. 支持HTTP管道化:Keep-Alive与HTTP管道化(HTTP pipelining)结合使用,可以进一步提高性能。HTTP管道化允许客户端在发送一个请求的同时,还可以发送后续的请求,而无需等待前一个请求的响应。这样可以更充分地利用网络连接和服务器资源,提高请求的并发性和吞吐量。
Keep-Alive并非永久保持连接,而是在一定时间内保持连接处于打开状态,超过一定时间没有新的请求时,连接会自动关闭。服务器可以通过设置Keep-Alive超时时间来控制连接的持续时间。
二十六、闭包的理解
概念:
闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,创建的函数可以访问到当前函数的局部变量。
特点:
1、让外部访问函数内部变量变成可能;
2、变量会常驻在内存中;
3、可以避免使用全局变量,防止全局变量污染。
优点:
可以读取其他函数内部的变量,并将其一直保存在内存中。
缺点:
可能会造成内存泄漏或溢出。
用途:
闭包的第一个用途是使我们在函数外部能够访问到函数内部的变量。通过使用闭包,可以通过在外部调用闭包函数,从而在外部访问到函数内部的变量,可以使用这种方法来创建私有变量。
闭包的另一个用途是使已经运行结束的函数上下文中的变量对象继续留在内存中,因为闭包函数保留了这个变量对象的引用,所以这个变量对象不会被回收。
二十七、JS垃圾回收机制及内存泄漏
垃圾回收机制:
垃圾回收机制(Garbage Collection)简称GC:是JavaScript中使用的内存管理系统的基本组成部分。JavaScript 是在创建变量(对象,字符串等)时自动进行了分配内存,并且在不使用它们时会 “自动” 释放、释放的过程成为垃圾回收。内存在不使用的时候会被垃圾回收器自动回收。
标记清除方式(最常见)
工作原理:是当变量进入环境时,将这个变量标记为“进入环境”。当变量离开环境时,则将其标记为“离开环境”。标记“离开环境”的就回收内存。
工作流程:
1、垃圾回收器,在运行的时候会给存储在内存中的所有变量都加上标记。
2、去掉环境中的变量以及被环境中的变量引用的变量的标记。
3、再被加上标记的会被视为准备删除的变量。
4、垃圾回收器完成内存清除工作,销毁那些带标记的值并回收他们所占用的内存空间。
引用计数方式
工作原理:跟踪记录每个值被引用的次数。
工作流程:
1、声明了一个变量并将一个引用类型的值赋值给这个变量,这个引用类型值的引用次数就是1。
2、同一个值又被赋值给另一个变量,这个引用类型值的引用次数加1。
3、当包含这个引用类型值的变量又被赋值成另一个值了,那么这个引用类型值的引用次数减1。
4、当引用次数变成0时,说明没办法访问这个值了。
5、当垃圾收集器下一次运行时,它就会释放引用次数是0的值所占的内存。
内存泄漏:
1、意外的全局变量引起的内存泄漏
原因:全局变量,不会被回收。
解决:使用严格模式避免。
2、闭包引起的内存泄漏
原因:闭包可以维持函数内局部变量,使其得不到释放。
解决:将事件处理函数定义在外部,解除闭包,或者在定义事件处理函数的外部函数中,删除对dom的引用。
3、没有清理的DOM元素引用
原因:虽然别的地方删除了,但是对象中还存在对dom的引用
解决:手动删除。
4、被遗忘的定时器或者回调
原因:定时器中有dom的引用,即使dom删除了,但是定时器还在,所以内存中还是有这个dom。
解决:手动删除定时器和dom。
5、子元素存在引用引起的内存泄漏
原因:div中的ul li 得到这个div,会间接引用某个得到的li,那么此时因为div间接引用li,即使li被清空,也还是在内存中,并且只要li不被删除,他的父元素都不会被删除。
解决:手动删除清空。
二十八、nextTick的实现
概念:
nextTick主要用于将某些操作推迟到下次 DOM 更新循环之后执行。Vue.js 使用虚拟 DOM(Virtual DOM)来提高性能,当数据发生变化时,并不会立即更新实际的 DOM,而是先通过虚拟 DOM 计算出最有效的更新方案,然后再一次性地更新真实 DOM。这就意味着,当你修改了数据后,直接进行依赖于 DOM 变化的操作可能会得不到预期的结果,因为此时 DOM 还没有更新。
使用场景:
-
在 DOM 更新后执行某些操作,例如获取更新后的元素尺寸、位置等。
-
在更新后触发某些异步操作,例如发送请求、执行动画等。
-
在修改数据后立即访问更新后的数据。
二十九、混入mixin的原理
混入 (mixin)将组件的公共逻辑或者配置提取出来,哪个组件需要用到时,直接将提取的这部分混入到组件内部即可。这样既可以减少代码冗余度,也可以让后期维护起来更加容易。
Mixin和Vuex的区别:
-
Vuex公共状态管理,如果在一个组件中更改了Vuex中的某个数据,那么其它所有引用了Vuex中该数据的组件也会跟着变化。
-
Mixin中的数据和方法都是独立的,组件之间使用后是互相不影响的。
三十、js列举和数组操作相关的方法(常用)
添加元素
-
push()
: 在数组的末尾添加一个或多个元素,并返回新的长度。 -
unshift()
: 在数组的开头添加一个或多个元素,并返回新的长度。
删除元素
-
pop()
: 删除数组的最后一个元素,并返回那个元素。 -
shift()
: 删除数组的第一个元素,并返回那个元素。 -
splice()
: 通过删除、替换或添加新元素来改变数组的内容。
查找元素
-
indexOf()
: 查找元素在数组中的索引。 -
lastIndexOf()
: 从数组的末尾开始查找元素。 -
find()
: 查找第一个满足测试函数的元素。 -
findIndex()
: 查找第一个满足测试函数的元素的索引。
排序和翻转
-
sort()
: 对数组元素进行排序。 -
reverse()
: 颠倒反转数组中元素的顺序。
遍历和过滤
-
forEach()
: 对数组的每个元素执行一次提供的函数。 -
map()
: 创建一个新数组,其结果是该数组中的每个元素都调用一次提供的函数后的返回值。 -
filter()
: 创建一个新数组,包含通过所提供函数实现的测试的所有元素。 -
reduce()
: 对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值。 -
reduceRight()
: 类似reduce()
,但是从数组的末尾开始累加。
归并数组
-
concat()
: 合并两个或多个数组。 -
slice()
: 提取原数组的一部分,返回一个新数组。
其它方法
-
join()
: 将数组(或一个类数组对象)的所有元素连接成一个字符串并返回这个字符串。 -
toString()
: 返回一个表示数组内容的字符串。 -
split
()
: 把字符串转换成数组。 -
toLocaleString()
: 返回一个表示数组内容的本地化字符串。
三十一、typeof和instanceof的区别?
-
typeof 的返回值是一个字符串,用来说明变量的数据类型;
-
instanceof的返回值是布尔值,用于判断一个变量是否属于某个对象的实例。instanceof 可以准确地判断复杂引用数据类型,但是不能正确判断基础数据类型。
三十二、JS中 “==”和“===”的区别?
-
==:两个等号我们称为等值符,当等号两边的值为相同类型时比较值是否相同,类型不同时会发生类型的自动转换,转换为相同的类型后再作比较。也就是说两个等号只要值相等就可以。
-
===:三个等号我们称为等同符,当等号两边的值为相同类型的时候,直接比较等号两边 的值,值相同则返回 true,若等号两边的值类型不同时直接返回 false。也就是说三个等号既要判断值也要判断类型是否相等。
三十三、var、let和const的区别?
-
块级作用域:var定义的变量,没有块的概念,可以跨块访问, 不能跨函数访问;let定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问;const用来定义常量,使用时必须初始化(即必须赋值),只能在块作用域里访问,而且不能修改。
-
变量提升:var存在变量提升,let和const不存在变量提升,即在变量只能在声明之后使用,否在会报错。
-
给全局添加属性:浏览器的全局对象是window,Node的全局对象是global。var声明的变量为全局变量,并且会将该变量添加为全局对象的属性,但是let和const不会。
-
重复声明:var声明变量时,可以重复声明变量,后声明的同名变量会覆盖之前声明的遍历。let和const不允许重复声明变量。
-
暂时性死区:在使用let、const命令声明变量之前,该变量都是不可用的。这在语法上,称为暂时性死区。使用var声明的变量不存在暂时性死区。
-
初始值设置:在变量声明时,var 和 let 可以不用设置初始值。而const声明变量必须设置初始值。
-
指针指向:let和const都是ES6新增的用于创建变量的语法。 let创建的变量是可以更改指针指向(可以重新赋值)。但const声明的变量是不允许改变指针的指向。
三十四、js的call、apply和bind区别?
概念:
-
call( ) 是接收一个及其以上的参数,第一个参数表示this要指向的对象,其余参数表示调用函数需要传入的参数,返回调用函数的返回结果,属于立即执行函数;
-
apply( ) 是接收两个参数,第一个参数表示this要指向的对象,第二参数表示调用函数需要传入的参数所组成的数组,返回调用函数的返回结果,属于立即执行函数;
-
bind( ) 是接收一个及其以上的参数,和call( )一致,但是其返回是一个函数,而不是调用函数的返回结果。(当 bind 返回的函数使用new作为构造函数时,绑定的 this 值会失效,this指向实例对象,但传入的参数依然生效 (new调用的优先级 > bind调用))
区别:
-
call和apply唯一的区别是:call传入的是参数列表,apply传入的是数组,也可以是类数组;
-
bind和call、apply的区别: bind返回的是一个改变了this指向的函数,便于稍后调用,而call和apply会立即调用;bind和call很像,传入的也是参数列表,但是可以多次传入,而call需要一次传入。
三十五、Webpack
概念:
-
Webpack是一个模块打包工具,可以使用它管理项目中的模块依赖,并编译输出模块所需的静态文件。
-
它可以很好地管理、打包开发中所用到的HTML,CSS,JavaScript和静态文件(图片,字体)等,让开发更高效。
-
对于不同类型的依赖,Webpack有对应的模块加载器,而且会分析模块间的依赖关系,最后合并生成优化的静态资源。
Webpack的基本功能有哪些?
-
代码转换:TypeScript 编译成 JavaScript、SCSS 编译成 CSS 等等;
-
文件优化:压缩 JavaScript、CSS、HTML 代码,压缩合并图片等;
-
代码分割:提取多个页面的公共代码、提取首屏不需要执行部分的代码让其异步加载;
-
模块合并:在采用模块化的项目有很多模块和文件,需要构建功能把模块分类合并成一个文件;
-
自动刷新:监听本地源代码的变化,自动构建,刷新浏览器;
-
代码校验:在代码被提交到仓库前需要检测代码是否符合规范,以及单元测试是否通过;
-
自动发布:更新完代码后,自动构建出线上发布代码并传输给发布系统。
Webpack构建过程?
-
从entry里配置的module开始递归解析entry依赖的所有module;
-
每找到一个module,就会根据配置的loader去找对应的转换规则;
-
对module进行转换后,再解析出当前module依赖的module;
-
这些模块会以entry为单位分组,一个entry和其所有依赖的module被分到一个组Chunk;
-
最后Webpack会把所有Chunk转换成文件输出在整个流程中Webpack会在恰当的时机执行plugin里定义的逻辑。
Loader和Plugin的区别?
-
Loader 本质就是一个函数,在该函数中对接收到的内容进行转换,返回转换后的结果。 因为 Webpack 只认识 JavaScript,所以 Loader 就成了翻译官,对其他类型的资源进行转译的预处理工作。
-
Plugin 就是插件,基于事件流框架 Tapable,插件可以扩展 Webpack 的功能,在 Webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果。
-
Loader 在 module.rules 中配置,作为模块的解析规则,类型为数组。每一项都是一个 Object,内部包含了 test(类型文件)、loader、options (参数)等属性。
-
Plugin 在 plugins 中单独配置,类型为数组,每一项是一个 Plugin 的实例,参数都通过构造函数传入。
如何优化 Webpack 的构建速度?
(1)使用高版本的 Webpack 和 Node.js;
(2)压缩代码:
-
通过 uglifyjs-webpack-plugin 压缩JS代码;
-
通过 mini-css-extract-plugin 提取 chunk 中的 CSS 代码到单独文件,通过 css-loader 的 minimize 选项开启 cssnano 压缩 CSS。
(3)多线程/多进程构建:thread-loader, HappyPack;
(4)压缩图片: image-webpack-loader;
(5)缩小打包作用域:
-
exclude/include (确定 loader 规则范围);
-
resolve.modules 指明第三方模块的绝对路径 (减少不必要的查找);
-
resolve.mainFields 只采用 main 字段作为入口文件描述字段 (减少搜索步骤,需要考虑到所有运行时依赖的第三方模块的入口文件描述字段);
-
resolve.extensions 尽可能减少后缀尝试的可能性;
-
noParse 对完全不需要解析的库进行忽略 (不去解析但仍会打包到 bundle 中,注意被忽略掉的文件里不应该包含 import、require、define 等模块化语句);
-
ignorePlugin (完全排除模块)。
Webpack 的热更新原理:
-
Webpack 的热更新又称热替换(Hot Module Replacement),缩写为 HMR。 这个机制可以做到不用刷新浏览器而将新变更的模块替换掉旧的模块。
-
HMR的核心就是客户端从服务端拉去更新后的文件,准确地说是 chunk diff (chunk 需要更新的部分),实际上 WDS 与浏览器之间维护了一个 Websocket,当本地资源发生变化时,WDS 会向浏览器推送更新,并带上构建时的 hash,让客户端与上一次资源进行对比。客户端对比出差异后会向 WDS 发起 Ajax 请求来获取更改内容(文件列表、hash),这样客户端就可以再借助这些信息继续向 WDS 发起 jsonp 请求获取该chunk的增量更新。
-
后续的部分(拿到增量更新之后如何处理?哪些状态该保留?哪些又需要更新?)由 HotModulePlugin 来完成,提供了相关 API 以供开发者针对自身场景进行处理,像react-hot-loader 和 vue-loader 都是借助这些 API 实现 HMR。
什么是bundle?什么是chunk?什么是module?
-
bundle:是webpack打包后的一个文件;
-
chunk:代码块,一个chunk 可能有很多的模块组成,用于合并和分割代码;
-
module:模块,在webpack中,一切都是模块,一个文件就是一个模块,她从入口开始查找webpack依赖的所有模块。
webpack和grunt以及gulp有什么不同?
-
grunt和gulp是基于任务处理的工具,我们需要把我们要做的事分配成各种各样的任务,grunt和gulp会自动执行各种分配的任务,像流水线一样,把资源放上去通过不同的插件进行加工,他的插件非常丰富,能够为我们打造各种工作流;
-
webpack是模块化打包工具,把所有文件都当作模块进行处理,也就是说webpack和grunt和gulp是两种完全不一样的东西。
三十六、const定义的对象属性是否可以改变?
情况一:const定义的变量存在块级作用域,且不存在变量提升,一般用于定义常量,定义的时候必须初始化。
答案:不可以。
原因:const定义的如果是基本数据类型(string,number,boolean,null,undifined,symbol),定义后就不可再修改,如果修改,会报错。
情况二:那么如果是const定义的对象呢?是否可以修改对象中的属性?
答案:可以。
原因:对象是引用类型的,const定义的对象t中保存的是指向对象t的指针,这里的“不变”指的是指向对象的指针不变,而修改对象中的属性并不会让指向对象的指针发生变化,所以用const定义对象,对象的属性是可以改变的。
三十七、栈溢出及解决方法?
栈溢出(stack Overflow):
-
缓冲区溢出是由于C语言系列设有内置检查机制来确保复制到缓冲区的数据不得大于缓冲区的大小,因此当这个数据足够大的时候,将会溢出缓冲区的范围。
-
栈溢出就是缓冲区溢出的一种。 由于缓冲区溢出而使得有用的存储单元被改写, 往往会引发不可预料的后果。程序在运行过程中,为了临时存取数据的需要,一般都要分配一些内存空间,通常称这些空间为缓冲区。如果向缓冲区中写入超过其本身长度的数据,以致于缓冲区无法容纳,就会造成缓冲区以外的存储单元被改写,这种现象就称为缓冲区溢出。缓冲区长度一般与用户自己定义的缓冲变量的类型有关。
-
由于缓冲区溢出而使得有用的存储单元被改写,往往会引发不可预料的后果。向这些单元写入任意的数据,一般只会导致程序崩溃之类的事故,对这种情况我们也至多说这个程序有Bug。但如果向这些单元写入的是精心准备好的数据,就可能使得程序流程被劫持,致使不希望的代码被执行,落入攻击者的掌控之中,这就不仅仅是bug,而是漏洞(exploit)了。
栈溢出的解决方法:
-
减少栈空间的需求,不要定义占用内存较多的auto变量,应该将此类变量修改成指针,从堆空间分配内存。
-
函数参数中不要传递大型结构/联合/对象,应该使用引用或指针作为函数参数。
-
减少函数调用层次,慎用递归函数,例如A->B->C->A环式调用。
三十八、JS如何实现多线程?
多线程概念:
JavaScript本身是单线程的,但是可以通过实现多线程来提高性能和用户体验。多线程允许JavaScript在等待用户交互或网络请求时,执行其他任务,从而提高页面加载速度和响应速度。
实现多线程的方式:
JavaScript有多种实现多线程的方式,包括Web Workers、SharedArrayBuffer、WebAssembly等。其中,Web Workers允许在后台线程中运行JavaScript代码,而SharedArrayBuffer和BufferSource API则允许在多个线程之间共享数据。
(使用Web Workers实现多线程需要创建一个新的worker线程,并将需要执行的代码作为字符串传递给worker。worker线程可以访问全局对象messageChannel的postMessage方法来发送消息,主线程可以使用onmessage方法来接收消息并执行相应的操作。)
如何保证多线程安全?
多线程环境下的安全问题主要包括数据竞争和死锁等。为了解决这些问题,需要使用同步机制,如使用Promise、async/await等异步编程方式,或者使用事件循环、共享内存等机制来保证数据的一致性和安全性。
三十九、浅拷贝和深拷贝区别?
浅拷贝
-
浅拷贝创建一个新的对象,但是只复制原始对象的基本数据类型的字段或引用(地址),而不复制引用指向的对象。这意味着新对象和原始对象中的引用指向相同的对象。
-
如果原始对象中的字段是基本数据类型,那么这些字段会被复制到新对象中,而如果字段是引用类型,则新对象和原始对象的对应字段将引用同一个对象。
-
因此,对新对象所做的修改可能会影响到原始对象,因为它们共享相同的引用。
深拷贝
-
深拷贝创建一个新的对象,并且递归地复制原始对象的所有字段和引用指向的对象,而不仅仅是复制引用本身。
-
深拷贝会递归复制整个对象结构,包括对象内部的对象,确保新对象和原始对象之间的所有关系都是独立的。
-
这意味着对新对象所做的修改不会影响到原始对象,因为它们拥有彼此独立的副本。
区别:
-
直接区别:浅拷贝就是双方不是独立的,还会互相影响;深拷贝是不会影响到彼此,是独立的个体;
-
内在区别:浅拷贝就是简单的把指向别人的值的一个指针给复制过来,深拷贝就是实实在在的把别人的值给复制过来。
四十、事件循环,Promise和async/await
事件循环event loop它的执行顺序:
-
一开始整个脚本作为一个宏任务执行;
-
执行过程中同步代码直接执行,宏任务进入宏任务队列,微任务进入微任务队列;
-
当前宏任务执行完出队,检查微任务列表,有则依次执行,直到全部执行完;
-
执行浏览器UI线程的渲染工作;
-
检查是否有Web Worker任务,有则执行;
-
执行完本轮的宏任务,回到2,依此循环,直到宏任务和微任务队列都为空。
Promise:
是一种用于处理异步操作的对象。它可以表示一个异步操作的最终完成或失败,并返回相应的结果或错误信息。Promise有三种状态:pending(进行中)、fulfilled(已完成)和rejected(已拒绝)。通过调用Promise的then()方法可以注册回调函数来处理异步操作的结果。
async/await:
是ES8引入的一种更加简洁的处理异步操作的方式。async函数是一个返回Promise对象的函数,其中可以使用await关键字来等待一个Promise对象的解决。await关键字可以暂停async函数的执行,直到Promise对象解决为止,并返回解决后的结果。
Promise和async/await的区别:
-
语法上,Promise使用then()和catch()方法来处理异步操作的结果,而async/await使用async函数和await关键字来等待异步操作的结果。
-
可读性上,async/await更加直观和易于理解,代码结构更加清晰,而Promise则需要通过链式调用then()方法来处理多个异步操作。
-
错误处理上,Promise使用catch()方法来捕获错误,而async/await可以使用try-catch语句来捕获错误。
JavaScript的异步机制包括以下几个步骤:
(1)所有同步任务都在主线程上执行,行成一个执行栈;
(2)主线程之外,还存在一个任务队列,只要异步任务有了结果,就会在任务队列中放置一个事件;
(3)一旦执行栈中的所有同步任务执行完毕,系统就会读取任务队列,看看里面还有哪些事件,哪些对应的异步任务,于是异步任务结束等待状态,进入执行栈,开始执行;
(4)主线程不断的重复上面的第三步。
链式调用
Promise链式调用是一种编程模式,允许在异步操作之间顺序执行多个操作。在每个操作中,可以使用.then()方法返回一个新的Promise,从而在异步流程中继续执行下一个操作。这样可以避免回调函数,提高代码的可读性和可维护性。
链式调用的基本步骤包括:
-
创建一个新的Promise对象,并调用resolve或reject来变更其状态。
-
在then或catch方法中,处理成功或失败的状态。
-
在then方法中,可以使用return关键字返回一个新的Promise对象,或者直接返回普通值。
-
继续在下一个then方法中处理返回的Promise对象,或者直接处理返回的普通值。
四十一、Vuex
Vuex 是一个专为 Vue 应用程序开发的状态管理模式。每一个 Vuex 应用的核心就是 store(仓库)。
Vuex 的状态存储是响应式的;当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新;改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation, 这样使得我们可以方便地跟踪每一个状态的变化。
Vuex主要包括以下几个核心模块:
-
State:定义了应用的状态数据;
-
Getter:在 store 中定义“getter”(可以认为是 store 的计算属性),就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来, 且只有当它的依赖值发生了改变才会被重新计算;
-
Mutation:是唯一更改 store 中状态的方法,且必须是同步函数;
-
Action:用于提交 mutation,而不是直接变更状态,可以包含任意异步操作;
-
Module:允许将单一的 Store 拆分为多个 store 且同时保存在单一的状态树中;
四十二、vue 的生命周期(八个阶段)
1、beforeCreate
在实例创建之间执行,数据是未加载状态。
创建一个Vue实例,此时实例上只有一些生命周期函数和默认的事件;
此时data computed watch methods上的方法和数据均不能访问。
2、created
在实例创建、数据加载后,能初始化数据,DOM渲染之前执行。
可以对data数据进行操作,可进行一些请求,请求不易过多,避免白屏时间太长。
3、beforeMount
虚拟DOM已创建完成,在数据渲染前最后一次更改数据。el未挂载。
判断el的挂载方式;
判断是否有template设置;
将template进行渲染保存到内存当中,还未挂载在页面上。
4、mounted
页面、数据渲染完成。el挂载完毕。可以访问DOM节点。
将内存中的模版挂载到页面上;
此时可以操作页面上的DOM节点;
此时组件从创建阶段进入运行阶段。
5、beforeUpdate
重新渲染之前触发。不会造成重渲染。
页面显示的数据是旧的,此时data里面的数据是最新,页面数据和data数据暂未同步。
6.updated
数据已经更新完成,DOM也重新render完成,更改数据会陷入死循环。
根据data里的最新数据渲染出最新的DOM树,然后将最新的DOM挂载到页面;
此时data和页面数据一致,都是最新的。
7、beforeDestroy
实例销毁前执行,实例仍然完全可用。
此时组件从运行阶段进入到销毁阶段;
组件上的data和methods以及过滤器等都出于可用状态,销毁还未执行。
8、Destroyed
实例销毁后执行,这时候只剩下DOM空壳。
组件已经被完全销毁,组件中所有的数据、方法、指令、过滤器等,都已不可用。
四十三、Vue每个周期具体适合哪些场景?
-
beforeCreate:在new一个vue实例后,只有一些默认的生命周期钩子和默认事件,其他的东西都还没创建。在beforeCreate生命周期执行的时候,data和methods中的数据都还没有初始化。不能在这个阶段使用data中的数据和methods中的方法。
-
created:data 和 methods都已经被初始化好了,如果要调用 methods 中的方法,或者操作 data 中的数据,最早可以在这个阶段中操作。
-
beforeMount:执行到这个钩子的时候,在内存中已经编译好了模板了,但是还没有挂载到页面中,此时,页面还是旧的。
-
mounted:执行到这个钩子的时候,就表示Vue实例已经初始化完成了。此时组件脱离了创建阶段,进入到了运行阶段。如果我们想要通过插件操作页面上的DOM节点,最早可以在和这个阶段中进行。
-
beforeUpdate:当执行这个钩子时,页面中的显示的数据还是旧的,data中的数据是更新后的, 页面还没有和最新的数据保持同步。
-
updated:页面显示的数据和data中的数据已经保持同步了,都是最新的。
-
beforeDestory:Vue实例从运行阶段进入到了销毁阶段,这个时候上所有的 data 和 methods,指令,过滤器……都是处于可用状态。还没有真正被销毁。
-
destroyed:这个时候上所有的 data 和 methods,指令,过滤器……都是处于不可用状态。组件已经被销毁了。
四十四、简述MVVM 和MVC的原理以及区别?
MVVM视图模型双向绑定,是Model-View-ViewModel的缩写
1、MVVM的优点:
-
低耦合。视图(View)可以独立于Model变化和修改,一个Model可以绑定到不同的View上,当View变化的时候Model可以不变化,当Model变化的时候View也可以不变;
-
可重用性。你可以把一些视图逻辑放在一个Model里面,让很多View重用这段视图逻辑。
-
独立开发。开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计。
-
可测试。
2、什么是MVC?
MVC是应用最广泛的软件架构之一,一般MVC分为:Model(模型),View(视图),Controller(控制器)。 这主要是基于分层的目的,让彼此的职责分开。View一般用过Controller来和Model进行联系。Controller是Model和View的协调者,View和Model不直接联系。基本都是单向联系。M和V指的意思和MVVM中的M和V意思一样。C即Controller,指的是页面业务逻辑。MVC是单向通信。也就是View跟Model,必须通过Controller来承上启下。
-
Model(模型)表示应用程序核心(如数据库)。
-
View(视图)显示效果(HTML页面)。
-
Controller(控制器)处理输入(业务逻辑)。
MVC 模式同时提供了对 HTML、CSS 和 JavaScript 的完全控制。
-
Model(模型)是应用程序中用于处理应用程序数据逻辑的部分。(通常模型对象负责在数据库中存取数据)
-
View(视图)是应用程序中处理数据显示的部分。(通常视图是依据模型数据创建的)
-
Controller(控制器)是应用程序中处理用户交互的部分。(通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据)
3、MVC的优点:
1、低耦合;
2、重用性高;
3、生命周期成本低;
4、部署快;
5、可维护性高;
6、有利软件工程化管理。
4、MVC与MVVM的区别?
MVC和MVVM的区别并不是VM完全取代了C,ViewModel存在目的在于抽离Controller中展示的业务逻辑,而不是替代Controller,其它视图操作业务等还是应该放在Controller中实现。也就是说MVVM实现的是业务逻辑组件的重用。
-
MVC中Controller演变成MVVM中的ViewModel;
-
MVVM通过数据来显示视图层而不是节点操作;
-
MVVM主要解决了MVC中大量的dom操作使页面渲染性能降低,加载速度变慢,影响用户体验。
四十五、vue常见指令
-
v-model 多用于表单元素实现双向数据绑定;
-
v-bind:简写为冒号:“:”,动态绑定一些元素的属性,类型可以是:字符串、对象或数组;
-
v-on:click 给标签绑定函数,可以缩写为:“@”,例如绑定一个点击函数 函数必须写在methods里面;
-
v-for 格式: v-for="字段名 in(of) 数组json" 循环数组或json,记得加上key;
-
v-show 显示内容;
-
v-if 指令:取值为true/false,控制元素是否需要被渲染;
-
v-else 指令:和v-if指令搭配使用,没有对应的值。当v-if的值false,v-else才会被渲染出来;
-
v-else-if 必须和v-if连用;
-
v-text 解析文本;
-
v-html 解析html标签 (一般常见的解决后台的富文本内容);
-
v-bind:class 三种绑定方法:对象型 "{red:isred}";三元型 " isred?"red":"blue";数组型 " [{red:"isred" },{blue:"isblue"}] ";
-
v-once 进入页面时 只渲染一次 不在进行渲染;
-
v-cloak 防止闪烁;
-
v-pre 把标签内部的元素原位输出。
四十六、vue中的data为什么是一个函数?起到什么作用?
-
在Vue组件中,data选项必须是一个函数,而不能直接是一个对象。这是因为Vue组件可以同时存在多个实例,如果直接使用对象形式的data选项,那么所有的实例将会共享同一个data对象,这样就会造成数据互相干扰的问题。
-
因此,将data选项设置为函数可以让每个实例都拥有自己独立的data对象。当组件被创建多次时,每个实例都会调用该函数并返回一个新的data对象,从而保证了数据的隔离性。
-
另外,data选项作为一个函数还具有一个重要的特性,就是它可以接收一个参数,这个参数是组件实例本身。这个特性在一些场景下非常有用,例如在定义组件时需要使用组件实例的一些属性或方法来计算初始数据。
因此,为了避免数据共享和保证数据隔离性,以及方便使用组件实例的属性和方法,Vue组件中的data选项必须是一个函数。
四十七、vue中ref的作用?
1、获取DOM元素的引用:
-
ref 加在普通的元素上,用this.ref.name 获取到的是dom元素;
-
vue给我们提供一个操作dom的属性,ref绑定在dom元素上时,用起来与id差不多,通过this.$refs来调用。
2、获取子组件的引用:
-
在Vue组件中使用ref可以获取子组件的引用,从而可以在父组件内部调用子组件的方法或访问其数据;
-
在父组件中将子组件引入,并在子组件标签上添加ref属性,然后就可以通过this.$refs.myChild获取子组件的引用,在父组件内部调用子组件的sayHello方法。
3、利用 v-for 和 ref 获取一组数组或者dom 节点
四十八、vue中hash和history的区别 ?
Vue-router的路由分为hash和history模式
Hash 模式:
-
在这种模式下,URL 的 hash 部分(即 # 符号后面的部分)被用来表示当前路由。例如,
http://example.com/#/user
。 -
当用户改变 URL 的 hash 部分时,浏览器会触发
hashchange
事件,Vue Router 就可以监听这个事件来实现页面的导航。 -
这种模式不需要服务器做任何配置,因为它只是改变了 URL 的 hash 部分,对服务器来说请求路径还是根路径。
-
在不支持 HTML5 History API 或者服务器端不能处理 HTML5 History 的情况下,通常会选择使用 Hash 模式。
History 模式:
-
History 模式利用了 HTML5 的 History API 来管理浏览器历史记录,这样可以让 URL 更加美观,并且没有 # 符号,例如
http://example.com/user
。 -
使用 History 模式时,需要后端的支持,因为当用户直接访问一个内部页面或者刷新页面的时候,服务器需要返回一个完整的 HTML 文件(通常是 index.html),然后由 Vue Router 决定渲染哪个组件。
-
如果服务器没有正确设置,直接访问或刷新 History 模式的页面可能会导致 404 错误。
-
这种模式提供了更好的用户体验,因为 URL 更加简洁。
四十九、Vue2.0和Vue3.0的区别?
1、vue2.0和3.0的初始化就存在着⼀定区别,⽐如vue3.0可以在安装脚⼿架同时提前安装好⼀些项⽬开发必备的插件,并且3.0提供了可视化创建脚⼿架,可以更加⽅便的对插件和依赖进⾏管理和配置,同时两个版本的⽬录结构也是有些许差别的。
2、在开发过程中两个版本的使⽤⽅法虽然在表⾯上没有太⼤的⼀个区别,但是在他的底层⽅⾯去看的话区别还是很⼤的,其中就包括渲染方式,数据监听,双向绑定,生命周期,vue3更精准变更通知。
关于双向绑定的更新:
-
vue2 的双向数据绑定是利⽤ES5 的⼀个 API ,Object.definePropert()对数据进⾏劫持结合发布订阅模式的⽅式来实现的。
-
vue3 中使⽤了 es6 的 ProxyAPI 对数据代理,通过 reactive() 函数给每⼀个对象都包⼀层 Proxy,通过 Proxy 监听属性的变化,从⽽ 实现对数据的监控。
3、另外vue3还新增了⼀些内置组件和⽅法,⽐如vue3可以默认进⾏懒观察,使⽤Function-based API,setup函数,对与插件或对象的⼀ 个按需引⼊,Computed Value ,新加⼊了 TypeScript 以及 PWA 的⽀持等等…
关于vue3的⼀个按需引⼊:
-
Vue2.x中new出的实例对象,所有的东西都在这个vue对象上,这样其实⽆论你⽤到还是没⽤到,都会跑⼀遍,这样不仅提⾼了性能消耗,也⽆疑增加了⽤户加载时间。
-
⽽vue3.0中可以⽤ES module imports按需引⼊,如:keep-alive内置组件、v-model指令,等等,不仅我们开发起来更加的便捷,减少 了内存消耗,也同时减少了⽤户加载时间,优化⽤户体验。
五十、Vue3带来了什么改变?
性能的提升:
-
打包大小减少41%;
-
初次渲染快55%, 更新渲染快133%;
-
内存减少54%。
源码的升级:
-
使用Proxy代替defineProperty实现响应式;
-
重写虚拟DOM的实现和Tree-Shaking。
拥抱TypeScript:
-
Vue3可以更好的支持TypeScript。
新的特性:
-
Composition API(组合API)
(1)setup配置
(2)ref与reactive
(3)watch与watchEffect
(4)provide与inject
-
新的内置组件
(1)Fragment
(2)Teleport
(3)Suspense
-
其他改变
(1)新的生命周期钩子
(2)data 选项应始终被声明为一个函数
(3)移除keyCode支持作为 v-on 的修饰符
五十一、vue2.0的响应式原理是什么?vue3.0的响应式原理是什么?
vue2.x的响应式:
-
实现原理:
-
对象类型:通过Object.defineProperty()对属性的读取、修改进行拦截(数据劫持)。
-
数组类型:通过重写更新数组的一系列方法来实现拦截。(对数组的变更方法进行了包裹)。
-
-
存在问题:
-
新增属性、删除属性,界面不会更新。
-
直接通过下标修改数组,界面不会自动更新。
-
Vue3.0的响应式:
-
实现原理:
-
通过Proxy(代理): 拦截对象中任意属性的变化,包括:属性值的读写、属性的添加、属性的删除等。
-
通过Reflect(反射): 对源对象的属性进行操作。
-
MDN文档中描述的Proxy与Reflect:
-
Proxy:Proxy - JavaScript | MDN
-
Reflect:Reflect - JavaScript | MDN
-
-
-
vue3响应式数据的判断
-
isRef: 检查一个值是否为一个 ref 对象;
-
isReactive: 检查一个对象是否是由 reactive 创建的响应式代理;
-
isReadonly: 检查一个对象是否是由 readonly 创建的只读代理;
-
isProxy: 检查一个对象是否是由 reactive 或者 readonly 方法创建的代理。
-
五十二、什么是 JSX ?
JSX(JavaScriptXML)是一种JavaScript语法的扩展,允许开发者在JavaScript代码中编写类似HTML的标签。尽管JSX看起来像HTML,但它最终会被转译为JavaScript对象,供React使用。
JSX的特点:
-
可以将HTML语言直接写在JavaScript语言之中,不加任何引号,这就是JSX的语法,它允许HTML与JavaScript的混写;
-
JSX允许直接在模板插入JavaScript变量。如果这个变量是一个数组,则会展开这个数组的所有成员;
-
防注入攻击;
-
在JSX中嵌入用户输入是安全的;
-
React DOM在渲染之前默认会过滤所有传入的值。它可以确保应用不会被注入攻击。所有的内容在渲染之前都被转换成了字符串。这样可以有效地防止XSS(跨站脚本攻击);
-
Babel转译器会把JSX转换成一个名为React.createElement()的方法调用;
-
如果在普通的html里面要写jsx语法,要将script的type改成text/jsx,这是因为React独有的JSX语法跟JavaScript不兼容。凡是使用JSX的地方,都要加上type=“text/jsx”。其次,React提供俩个库:react.js和JSXTransformer.js,它们必须首先加载。其中,JSXTransformer.js的作用是将JSX语法转为JavaScript语法。这一步很消耗时间,实际上线的时候,应该把它放到服务器完成。
五十三、React 的生命周期方法有哪些?
挂载阶段:
-
constructor:组件实例化时调用,用于初始化状态和绑定方法。
-
static getDerivedStateFromProps:在渲染之前调用,用于根据新的属性值计算并返回一个新的状态。
-
render:渲染组件的内容。
-
componentDidMount:组件挂载后调用,可以进行异步操作、订阅事件等。
更新阶段:
-
static getDerivedStateFromProps:在渲染之前调用,用于根据新的属性值计算并返回一个新的状态。
-
shouldComponentUpdate:在渲染之前调用,用于决定是否重新渲染组件,默认返回true。
-
render:渲染组件的内容。
-
getSnapshotBeforeUpdate:在最终将内容渲染到DOM之前调用,用于获取DOM更新前的快照。
-
componentDidUpdate:组件更新后调用,可以进行DOM操作、发起网络请求等。
卸载阶段:
-
componentWillUnmount:组件卸载前调用,可以进行清理操作,如取消订阅、清除定时器等。
五十四、React中的Hooks是什么?
Hook是什么:
-
Hook 是一些可以让你在函数组件里“钩入” React state 及生命周期等特性的函数。Hook 不能在 class 组件中使用 —— 这使得你不使用 class 也能使用 React。
-
React 内置了一些像 useState 这样的 Hook。你也可以创建你自己的 Hook 来复用不同组件之间的状态逻辑。
-
React提供了多个常用的Hooks,用于在函数组件中管理状态、处理副作用和访问React的上下文等。
React常用Hooks列表:
-
useState:用于在函数组件中添加状态。
-
useEffect:用于在函数组件中执行副作用操作。
-
useContext:用于在函数组件中访问React的上下文。
-
useReducer:用于在函数组件中使用Reducer模式来管理状态。
-
useRef:用于在函数组件中创建可变的引用。
-
useMemo:用于在函数组件中缓存计算的值。
-
useCallback:用于在函数组件中缓存函数。
-
useLayoutEffect:类似于useEffect,但在DOM更新之后同步执行。
-
useImperativeHandle:用于在函数组件中自定义外部组件实例的暴露。
-
useDebugValue:用于在自定义Hooks中显示自定义的调试值。
五十五、React和Vue.js的相似性和差异性是什么?
相似性:
(1)都是用于创建UI的 JavaScript库。
(2)都是快速和轻量级的代码库(这里指 React核心库)。
(3)都有基于组件的架构。
(4)都使用虚拟DOM。
(5)都可以放在单独的HTML文件中,或者放在 Webpack设置的一个更复杂的模块中。
(6)都有独立但常用的路由器和状态管理库。
差异性:
-
它们最大的区别在于 Vue. js通常使用HTML模板文件,而 React完全使用 JavaScript创建虚拟DOM。
-
Vue. js还具有对于“可变状态”的“ reactivity”的重新渲染的自动化检测系统。(React一般适用于大型项目)
五十六、React
React的主要功能:
-
它使用虚拟DOM而不是真实DOM。
-
它使用服务器端渲染。
-
它遵循单向数据流或数据绑定。
React的一些主要优点:
-
它提高了应用程序的性能;
-
它可以方便地在客户端和服务器端使用;
-
由于有了JSX,代码的可读性提高了;
-
React易于与其他框架(如Meteor,Angular等)集成;
-
使用React,编写UI测试用例变得非常容易。
React的局限性:
-
React只是一个库,而不是一个成熟的框架;
-
它的图书馆很大,需要花费一些时间来理解;
-
对于新手程序员而言,理解起来可能有点困难;
-
由于使用内联模板和JSX,编码变得复杂。
React的特点:
1. React速度很快
-
与其他框架相比,React采取了一种独特操作DOM的方式。
-
它并不直接对DOM进行操作。它引入了一个叫虚拟DOM的概念,安插在JavaScript逻辑和实际的DOM之间。这一概念提高了Web性能。在UI渲染过程中,React通过在虚拟DOM中的微操作来实现对实际DOM的局部更新。
-
将视图与数据进行单向绑定,绝大部分操作都可以不再直接操作DOM,而是通过改变数据来更新视图,这对于前端是具有里碑意义的。
2. 跨浏览器兼容
-
虚拟DOM帮助我们解决了跨浏览器问题,它为我们提供了标准化的API,甚至在IE8中都是没问题的。
3. 模块化
-
为程序编写独立的模块化UI组件,并且它们可以引入其他组件。这等同于提高了代码的可维护性。
4. 单向数据流,让事情一目了然
-
Flux是一个用于在JavaScript应用中创建单向数据层的架构,它随着React视图库的开发而被Facebook概念化。它只是一个概念,而非特定工具的实现。它可以被其它框架吸纳。例如,Alex Rattray有一个很好的Flux实例,在React中使用了Backbone的集合和模型。
5. 纯粹的JavaScript
-
现代Web应用程序与传统的Web应用有着不同的工作方式。
-
例如,视图层的更新需要通过用户交互而不需要请求服务器。因此视图和控制器非常依赖彼此。
-
许多框架使用Handlebars或Mustache等模板引擎来处理视图层。但React相信视图和控制器应该相互依存在一起而不是使用第三方模板引擎,而且最重要的是,它是纯粹的JavaScript程序。
6. 同构的JavaScript
-
单页面JS应用程序的最大缺陷在于对搜索引擎的索引有很大限制。React对此有了解决方案。
-
React可以在服务器上预渲染应用再发送到客户端。它可以从预渲染的静态内容中恢复一样的记录到动态应用程序中。
-
因为搜索引擎的爬虫程序依赖的是服务端相应而不是JavaScript的执行,预渲染你的应用有助于搜索引擎优化。
7. React与其他框架/库相比兼容性好
-
比如使用RequireJS来加载和打包,而Browserify和Webpack适用于构建大型应用。它们使得那些艰难的任务不再让人望而生畏。
8. 相比于其他的框架【vue】更灵活
-
没有那么多的条条框框,提供了一系列基础api自己随意组合。如果要我把他比作积木的话那么react提供的就是小型的积木,vue提供的是大型的积木。这就势必造成了react会比vue更加的灵活。
五十七、React State不可变性的原则
在 React 中,不可变性是指数据一旦被创建,就不能被修改。React 推崇使用不可变数据的原则,这意味着在更新数据时,应该创建新的数据对象而不是直接修改现有的数据。
关键点:
-
数据一旦创建就不能被修改:在 React 中,组件的状态(state)和属性(props)应该被视为不可变的。一旦创建了状态或属性对象,就不应该直接修改它们的值。这样可以确保组件的数据在更新时是不可变的,从而避免意外的数据改变和副作用。
-
创建新的数据对象:当需要更新状态或属性时,应该创建新的数据对象。这可以通过使用对象展开运算符、数组的 concat()、slice() 等方法,或者使用不可变数据库(如Immutable.js、Immer 等)来创建新的数据副本。
-
比较数据变化:React 使用 Virtual DOM 来比较前后两个状态树的差异,并仅更新需要更新的部分。通过使用不可变数据,React 可以更高效地进行比较,因为它可以简单地比较对象引用是否相等,而不必逐个比较对象的属性。
-
性能优化:使用不可变数据可以带来性能上的优势。由于 React 可以更轻松地比较前后状态的差异,可以减少不必要的重新渲染和组件更新,提高应用的性能和响应性。
好处:
-
简化数据变更追踪:由于数据不可变,可以更轻松地追踪数据的变化。这样可以更好地理解代码的行为和数据的流动。
-
避免副作用:可变数据容易引发副作用和难以追踪的bug。通过使用不可变数据,可以避免许多与副作用相关的问题。
-
方便的历史记录和回滚:不可变数据使得记录和回滚应用状态的历史变得更容易。可以在不改变原始数据的情况下,创建和保存不同时间点的数据快照。
五十八、uniapp优缺点
优点
-
一套代码可以生成多端
-
学习成本低,语法是vue的,组件是小程序的
-
拓展能力强
-
使用HBuilderX开发,支持vue语法
-
突破了系统对H5调用原生能力的限制
缺点
-
问世时间短,很多地方不完善
-
社区不大
-
官方对问题的反馈不及时
-
在Android平台上比微信小程序和iOS差
-
文件命名受限
五十九、uniapp目录结构
-
pages.json:配置文件,全局页面路径配置,应用的状态栏、导航条、标题、窗口背景色设置等;
-
main.js:入口文件,主要作用是初始化vue实例、定义全局组件、使用需要的插件如 vuex,注意uniapp无法使用vue-router,路由须在pages.json中进行配置。如果开发者坚持使用vue-router,可以在插件市场找到转换插件;
-
App.vue:是uni-app的主组件,所有页面都是在App.vue下进行切换的,是页面入口文件。但App.vue本身不是页面,这里不能编写视图元素。除此之外,应用生命周期仅可在App.vue中监听,在页面监听无效;
-
pages:页面管理部分用于存放页面或者组件;
-
应用配置 manifest.json:文件是应用的配置文件,用于指定应用的名称、图标、权限等,HBuilderX 创建的工程此文件在根目录,CLI 创建的工程此文件在 src 目录。我们也可以在这里为Vue 为H5设置跨域拦截处理器;
-
package.json:文件用来对 uni-app 进行全局配置,决定页面文件的路径、窗口样式、原生的导航栏、底部的原生tabbar 等。pages数组中第一项表示应用启动页。
六十、uniapp 常用的指令语句
-
v-for:循环渲染 (注意加:key)
-
v-if :控制元素的删除添加
-
v-show:控制元素的显示隐藏
-
v-model:双向数据绑定
-
v-on:事件绑定(简写@)
-
v-bind:属性绑定(简写:)
六十一、uniapp 应用的生命周期、页面的生命周期、组件的生命周期
应用的生命周期:
-
onLaunch——当uni-app 初始化完成时触发(全局只触发一次)
-
onShow——当 uni-app 启动,或从后台进入前台显示
-
onHide——当 uni-app 从前台进入后台
-
onError——当 uni-app 报错时触发
-
onUniNViewMessage——对 nvue 页面发送的数据进行监听,可参考 nvue 向 vue 通讯
-
onUnhandledRejection——对未处理的 Promise 拒绝事件监听函数(2.8.1+)
-
onPageNotFound——页面不存在监听函数
-
onThemeChange——监听系统主题变化
页面的生命周期:
-
onInit——监听页面初始化,其参数同 onLoad 参数,为上个页面传递的数据,参数类型为 Object(用于页面传参),触发时机早于 onLoad
-
onLoad——监听页面加载,其参数为上个页面传递的数据,参数类型为 Object(用于页面传参),参考示例
-
onShow——监听页面显示。页面每次出现在屏幕上都触发,包括从下级页面点返回露出当前页面
-
onReady——监听页面初次渲染完成。注意如果渲染速度快,会在页面进入动画完成前触发
-
onHide——监听页面隐藏
-
onUnload——监听页面卸载
-
onResize——监听窗口尺寸变化
组件的生命周期:
uni-app 组件支持的生命周期,与vue标准组件的生命周期相同
-
beforeCreate——在实例初始化之后被调用。
-
created——在实例创建完成后被立即调用。
-
beforeMount——在挂载开始之前被调用。
-
mounted——挂载到实例上去之后调用。详见 注意:此处并不能确定子组件被全部挂载,如果需要子组件完全挂载之后在执行操作可以使用$nextTickVue官方文档
-
beforeUpdate——数据更新时调用,发生在虚拟 DOM 打补丁之前。
-
updated——由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。
-
beforeDestroy——实例销毁之前调用。在这一步,实例仍然完全可用。
-
destroyed——Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
六十二、Git和SVN有什么区别?
-
git是分布式版本控制,svn是集中式版本控制(核心区别);
-
git相对于svn的优势就是不需要网络即可版本控制;
-
git把内容按数据方式存储,而svn是按文件;
-
git可以是公用的,可以分享,svn基本是公司内部才能访问,网外不方便访问;
-
git不依赖中央服务器,即使服务器有问题也不受影响,svn依赖服务器,一旦服务器有问题就会受影响;
-
git没有一个全局的版本号,svn有。