+@[TOC]
此题比较简单,但一定要回答的全面
1.get 参数通过 url 传递,post 放在 body 体中。(get把请求的数据在URL后通过?连接,通过&进行参数分割。psot将参数存放在HTTP的包体内)
2.get传递数据是通过URL进行传递,对传递的数据长度是受到URL大小的限制,URL最大长度是2048个字符。post没有长度限制
3.get后退不会有影响,post后退会重新进行提交
4.get请求可以被缓存,post不可以被缓存
5.get请求只URL编码,post支持多种编码方式
6.get请求的记录会留在历史记录中,post请求不会留在历史记录
7.get只支持ASCII字符,post没有字符类型限制
8、get不安全,因为参数直接暴露在 url 中,所以不能用来传递敏感信息。
此题有过开发经验的都知道几个,但还是那句话,一定要回答的详细且全面。
1xx(临时响应)
100: 请求者应当继续提出请求。
101(切换协议) 请求者已要求服务器切换协议,服务器已确认并准备进行切换。
2xx(成功)
200:正确的请求返回正确的结果
201:表示资源被正确的创建。比如说,我们 POST 用户名、密码正确创建了一个用户就可以返回 201。
202:请求是正确的,但是结果正在处理中,这时候客户端可以通过轮询等机制继续请求。
3xx(已重定向)
300:请求成功,但结果有多种选择。
301:请求成功,但是资源被永久转移。
303:使用 GET 来访问新的地址来获取资源。
304:请求的资源并没有被修改过
4xx(请求错误)
400:请求出现错误,比如请求头不对等。
401:没有提供认证信息。请求的时候没有带上 Token 等。
402:为以后需要所保留的状态码。
403:请求的资源不允许访问。就是说没有权限。
404:请求的内容不存在。
5xx(服务器错误)
500:服务器错误。
501:请求还没有被实现。
是超文本传输协议,信息是明文传输;https 是基于 ssl 加密的 http 协议,比 http 协议安全。使用不同的链接方式,端口也不同,一般而言,http 协议的端口为 80,https 的端口为443。Https 协议需要 ca 证书,费用较高。
HTTP1.0 定义了三种请求方法: GET, POST 和 HEAD 方法。 HTTP1.1 新增了五种请求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT 方法
同源策略限制 不同源会造成跨域。以下任意一种情况不同,都是不同源。
同源:协议 域名 端口号全部相同 只要有一个不相同就是非同源策略
原理:动态创建一个script标签。script 叫做作用域属性。利用script标签的src属性不受同源策略限制。因为所有的src属性和href属性都不受同源策略限制。可以请求第三方服务器数据内容。
开发环境的跨域配置proxyTable 在config文件夹中的index.js中设置proxyTable
TCP协议是一种面向连接的、可靠的、基于字节流的传输层通信协议,采用全双工通信。
那为什么需要三次握手呢?请看如下的过程:
A向B发起建立连接请求:A——>B;
B收到A的发送信号,并且向A发送确认信息:B——>A;
A收到B的确认信号,并向B发送确认信号:A——>B。
四次挥手
那为什么需要四次挥手呢?请看如下过程:
A向B发起请求,表示A没有数据要发送了:A——>B;
B向A发送信号,确认A的断开请求:B——>A;
B向A发送信号,请求断开连接,表示B没有数据要发送了:B——>A;
A向B发送确认信号,同意断开:A——>B。
可能有朋友会问,为什么2、3次挥手不能合在一次挥手中?那是因为此时A虽然不再发送数据了,但是还可以接收数据,B可能还有数据要发送给A,所以两次挥手不能合并为一次。
挥手次数比握手多一次,是因为握手过程,通信只需要处理连接。而挥手过程,通信需要处理数据+连接。
Ok,TCP连接就这样关闭了!
cookies 是网站为了表示用户身份而储存在用户本地终端上的数据, Cookies 的数据始终在同源的 http 请求中携带,会在浏览器和服务器中来回传递,大小不能 4K(通常经过加密,所以不用担心账号被盗, 同源策略[同源是指"协议+域名+端口" 三者相同] 可以防止 XSS 和 CSRF 攻击浏览器,XSS 就是用过浏览 器的 cookies,截取用户数据,CSRF 是模拟用户在网页上面的操作,完成数据请求、异步策略牵扯到了 JSONP) sessionStorage 和 localStorage 的数据都是在本地存储,不会把数据发给服务器,localStorage 是关闭 浏览器,数据还存在不会丢失,而 sessionStorage 是离开浏览器后,数据会自动删除.localStorage 和 sessionStory 两种本地离线缓存
Websocket/SharedWorker 都是可以将不同线程共享为一个线程,他们的数据也是共享的。 LocalStorage 也可以实现浏览器多个标签页之间的通信。 localStorage 在另一个浏览器被添加/删除/修改时,会触发一个事件, 我们可以通过对 loacalStorage 监听事件,控制他的值来进行信息通信。
11、对盒模型的理解
标准盒子模型、IE盒子模型
可以通过修改元素的box-sizing属性来改变元素的盒模型:
box-sizing: content-box
表示标准盒模型(默认值)
box-sizing: border-box
表示IE盒模型(怪异盒模型)reset.css ====》 重置css样式的
非要说他问题:体积大了一点点点
normalize.css 是现在用的比较多的,但是和reset有区别。
是干什么:为了增强跨浏览器渲染的一致性(一定程度上),维护的一个CSS 重置样式库。
CSS3实现圆角边框(border-radius),阴影(box-shadow),
rem是CSS3新增的一个相对单位
对文字加特效(text-shadow、),线性渐变(gradient),旋转(transform)
transform:rotate(9deg) scale(0.85,0.90) translate(0px,-30px) skew(-9deg,0deg);// 旋转,缩放,定位,倾斜
增加了更多的CSS选择器 多背景 rgba
在CSS3中唯一引入的伪类是 ::selection.
媒体查询,多栏布局
border-image
雪碧图 === 精灵图
1. 是什么 : 把一堆小图标放在一张大图片上。
2. 优点:减少了http请求,做了性能上的优化。
3. 缺点:维护性,修改性,较差。
static [默认] 没有定位
fixed 相对于浏览器窗口
absolute 相对于第一个拥有relative的父元素的
relative 相对于自身
1. relative不脱离文档流,absolute脱离文档流
2. relative只有俩个值(left、right、top、bottom如果同时存在left干掉right,top干掉bottom)
absolute可以写四个值
height : 是高度
line-height : 是行高
height就是盒子的高度,line-height是每一行文字的高度(高度值会随着内容发生改变的)。【重点】
引入flexible.js文件。单位使用rem
当父盒子不设置高度,子盒子设置高度时,父盒子的高度取决于子盒子的高度, 如果子盒子浮动了, 子盒子就会脱离标准流,俗称脱标,就会导致父盒子高度变为0,这个时候,就需要清除浮动带来的影响,让父盒子重新获得高度, 称为清除浮动.
第二种方法:给父元素添加 overflow:hidden 优点:代码较少,简单方便 缺点:不能配合定位使用
第三种方法:在子元素并级后面添加一个新元素,添加 clear:both 属性 优点:通俗易懂,容易掌握 缺点:添加无意义空标签,不方便后期维护
第四种 : :after 方法(作用于浮动元素的父元素) 优点:结构和语义化完全正确 缺点:复用方式不当,会造成代码量增加
.clearfix:after{/*伪元素是行内元素 正常浏览器清除浮动方法*/
content: "";
display: block;
height: 0;
clear:both;
visibility: hidden; }
.clearfix{
*zoom: 1;/*ie6清除浮动的方式 *号只有IE6-IE7执行,其他浏览器不执行*/ }
block 元素转化为块级元素 inline 元素转化为行内元素 inline_block 元素转化问行内块元素 None 次元素不会显示,脱离文档流 List-item 元素转化为行内样式,并添加列表样式(如UL 下的li) Table 元素会以块级表格来显示
可以使用变量($变量名=值);变量 、嵌套、Mixin混合、function函数、插值
Class中嵌套class,从而减少重复的代码
less是一种动态样式语言. 对CSS赋予了动态语言的特性,如变量、继承、运算、函数。
宽度 0,高度 0,边框加宽,给一边加颜色,其余三边使用 transparent
23. Label 的作用是什么?怎么用?
label 标签是定义表单控制间的关系,当用户点击 label 里面的文字时,浏览器会自动把光标转载表单控件上
24、 满屏品字布局?
上面 div 宽度 100%; 下面两个宽度 width50%+float/display:inline/inlin-block
行内块排列会受到(空格/回车)等的影响,因为空格也属于字符,把字符大小 设置为 0 就 ok 了
.wrap ul{font-size:0px;}
浏览器的兼容性问题,有些浏览器对标签的默认值是不一样的,如果没有设置 CSS 初始化,浏览器之间 的页面会有差异,简单的方式:
*{ padding: 0; margin: 0; }
响应式页面主要为了配合各种用户设备的窗口宽度,主要用得到的一个是媒体查询,一个是 bootstrap,一个 是 rem 单位,rem 根据页面字体大小等比缩放, 可以用 vw/vh+rem,vw/vh 是将窗口大小评分为 100 份;
横向滚动:父元素 overflow-x:auto; overflow-y:hidden; 竖向滚动:父元素 overflow-x:hidden;overflow-y:auto;
Scrollbar 样式属性,有很多种,很少用,单词没怎么记住;
行内元素:a/img/span/b/strong/input/buttonj/select/section 块级元素:div/p/table/ul/ol/li/h1-h6
浮动后,元素的 display 值自动变为 display:block;
宽高自适应,高度恒为宽度的70% (padding-top:50% ,则高度恒为宽度的一半):
width:100% ; height:0; padding-top:70%
visibilty:hidden:元素任然在文档流中,并占用空间; display:none:元素脱离文档流,不占用空间; position:left:-999999px:将内容至于屏幕之外 text-index:-9999:只适用于 block 元素中的文本
display:none与visibilty:hidden: 隐藏元素
区别:1、display:none:元素脱离文档流,不占用空间;visibilty:hidden:元素任然在文档流中,并占用空间;(原理:display:none 第一次不绘制,visibility:hidden进行第一次绘制)
2、display:none重绘回流 。visibilty:hidden 重绘(触发回流必定会触发重绘,触发重绘不一定会触发回流)
元素的规模尺寸、布局、隐藏等改变而需要重新构建;这就被称为回流。
元素需要更新的属性只是影响元素的外观、风格,而不影响布局的,为重绘。回流必将引起重绘,但是重绘不一定会引起回流(回流比重绘的代价要更高,回流的花销跟render tree有多少节点需要重新构建有关系)
overflow : hidden ; text-overflow : (值为 clip 是修剪文本;ellipsis 为显示省略符号); white-space : nowrap
string 为使用给定的字符串来代表被修剪的文本。 ; 还需要加宽度 width 属性来兼容部分浏览器
实现多行文本溢出显示...display : -wedkit-box ; -webkit-box-orient : vertical ; -webkit-line-clamp : 3 ; overflow : hidden
适用范围 : 因使用了Webkit 的CSS 扩展属性,该方法适用于Webkit 浏览器以及移动端 注:
-webkit-line-clamp 用来限制在一个块元素显示的文本的行数,为了实现该效果,它需要组合其它的 webkit 属性。
常见结合属性:
display:-webkit-box; 必须结合的属性,将对象作为弹性伸缩盒子模式显示。 -webkit-box-orient 必须结合的属性,设置或减缩伸缩盒对象的子元素排列方式。
使用场景:
vw/vh 和百分比很类似,两者的区别:
%
):当浏览器的宽度或者高度发生变化时,通过百分比单位可以使得浏览器中的组件的宽和高随着浏览器的变化而变化,从而实现响应式的效果。一般认为子元素的百分比相对于直接父元素。一般认为子元素的百分比相对于直接父元素。水平居中:行内元素: text-align: center
----------块级元素: margin: 0 auto(必须有宽度)
垂直居中: 行内元素:设置line-height 等于height
块级元素:1、 position:absolute +top:50%+ transform:translateY(-50%)
2、display: flex + align-items: center+justify-content: center;
3、display: table+display:table-cell + vertical-align: middle
4、关键语句:父元素display: flex;(弹性盒子)子元素margin: auto;(上下左右居中)
元素水平垂直居中
方案1:position 元素已知宽度
父元素设置为:position: relative;
子元素设置为:position: absolute;
距上50%,据左50%,然后减去元素自身宽度的距离就可以实现(绝对定位+transform实现垂直水平居中,可以不知道子元素高宽度:position:absolute;top:50%;left:50%;transform:translate(-50%,-50%))
方案2:flex布局
display: flex;//flex布局
justify-content: center;//使子项目水平居中
align-items: center;//使子项目垂直居中
方案3:元素有宽度和高度时,利用margin:auto
设置元素水平垂直居中:
3、使用display为table,子元素为display:table-cell;vertical-align:center;text-align:center子子元素设置为vertical-align:center
子元素设置为margin:auto;position:absolute;top:0;left:0;right:0;bottom:0
图片居中对齐(图片和旁边的文字垂直居中对齐):vertical-align:middle
38 link 标签和 import 标签的区别
link 属于 html 标签,而@import 是 css 提供的
页面被加载时,link 会同时被加载,而@import 引用的 css 会等到页面加载结束后加载。
link 是 html 标签,因此没有兼容性,而@import 只有 IE5 以上才能识别。
link 方式样式的权重高于@import 的
Border-radius
id 选择器,class 选择器,标签选择器,伪元素选择器,伪类选择器等
内联选择器:将CSS样式写在元素的style属性当中
类别选择器:类别选择器是通过class属性去选中元素
!important>内联选择器>ID选择器>类别选择器>属性选择器>伪类>元素选择器>通配符选择器>继承选择器
样式表的来源不同时,优先级顺序为:内联样式> 内部样式 > 外部样式 > 浏览器用户
自定义样式 > 浏览器默认样式
伪元素和伪类的区别和作用?
伪元素:在内容元素的前后插入额外的元素或样式,但是这些元素实际上并不在文档中生成。它们只在外部显示可见,但不会在文档的源代码中找到它们,因此,称为“伪”元素。例如:
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}
总结:伪类是通过在元素选择器上加⼊伪类改变元素状态,⽽伪元素通过对元素的操作进⾏对元素的改变。
text-overflow 属性,值为 clip 是修剪文本;ellipsis 为显示省略符号来表被修剪的文本;
string 为使用给定的字符串来代表被修剪的文本。。要实现溢出时产生省略号的效果还须定义另外两个属性:强制文本在一行内显示(white-space:nowrap)及溢出内容为隐藏(overflow:hidden)
Calc 用户动态计算长度值,任何长度值都可以使用 calc()函数计算,需要注意的是,运
算符前后都需要保留一个空格,例如:width: calc(100% - 10px);
BFC-块级格式化上下文。
是一个独立的布局环境,其中的元素布局是不受外界的影响,并且在一个BFC中,块盒与行盒(行盒由一行中所有的内联元素所组成)都会垂直的沿着其父元素的边框排列。
只要元素满足下面任一条件即可触发 BFC 特性:
body 根元素
浮动元素:float 除 none 以外的值
绝对定位元素:position (absolute、fixed)
display 为 inline-block、table-cells、flex
overflow 除了 visible 以外的值 (hidden、auto、scroll)
BFC 特性及应用
1. 同一个 BFC 下外边距会发生折叠(如果想要避免外边距的重叠,可以将其放在不同的 BFC 容器中。)
3. BFC 可以阻止元素被浮动元素覆盖
flex-grow重点说明落在 剩余 这两个字上,父元素剩余的空间,那什么算父元素剩余空间呢,简单的理解就是(父元素的宽度-子元素总和的宽度),
是一个标签 、 @import是css的内容。加载页面时,link
标签引入的 CSS 被同时加载;@import
引入的 CSS 将在页面加载完毕后被加载。
1. title是网页标题,h1是内容。
2. 在做网站seo的层面上 title > h1 【重点】
1. 语义化
2. b只是一个加粗的标签,没什么特殊含义。
strong也是一个加粗标签,但是有特殊含义(强调:阅读器、seo)。
i与em的区别:
1. 语义化
2. 都是倾斜,i没有特殊含义,em有特殊含义。i一般现在都来做图标了。
title::鼠标移入显示的问题
alt :图片没有加载显示的文字
在做seo,alt属性是可以解决蜘蛛抓取不到图片的问题的。
jpg、jpeg : 适合大图片(banner) , 同样的相对于png体积小一点。【失桢】
png : 适合小图标(图标), 同样的图片体积大。 【不怎么失桢】
gif : 动图
HTML5 新特性: 绘图方面:加入了 canvas 绘图
媒体方面: 加入了 video 和 audio 标签
语义化标签: 比如 header、nav、footer、section 、article
本地离线存储: localStorage 和 sessionStory 两种本地离线缓存
localStorage 是长期储存数据,关闭浏览器后数据不会丢失 sessionStorage 是关闭浏览器后数据自动删除
表单控件: calendar、date、time、email、url、search ; 以及一些新技术: webwoker / websocket (säkit)/ GelolCation(ˌjēōlōˈ kāSHən)
H5的新特性。canvas 输出的是一副画布,放大会失真或者锯齿。适合比较小型的动态绘制。我们项目有个连线题是使用的canvas做的,根据选项与答案的坐标,在中间进行连线。。
svg 输出的图形是矢量图形,后期可以修改参数来自由放大缩小,不会失真和锯齿。我们项目有个字帖模块就是用这个做的。百度地图就是用svg做的。
由于商城图片过多时,就会给图片加一个懒加载的缓冲效果。当图片进入可视化区域的时候才会加载, 否则图片只是一个空标签。这样可以优化页面渲染速度,提升用户体验。先将img标签中的src链接设置为空,将真正的图片链接放在自定义属性(data-src),当js监听到图片元素进入到可视窗口的时候,将自定义属性中的地址存储到src中,达到懒加载的效果。
:闭包。一个函数能够访问另一个函数内部作用域的变量。外部函数执行完毕之后他的活动对象会被销毁,但是由于内部函数一直持有一个对外部函数变量的引用,导致他不会被垃圾清除算法所清除,会一直占用这块内存。形成闭包,所以闭包容易产生内存泄露。
垃圾清除算法。
闭包的最大用处有两个,一个是可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。
1.保护函数内的变量安全:如迭代器(执行一次函数往下取一个值)、生成器
2.函数防抖:在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。 实现的关键就在于setTimeOut
这个函数,由于还需要一个变量来保存计时,考虑维护全局纯净,可以借助闭包来实现。
由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,解决方法是,在退出函数之前,将不使用的局部变量全部删除。
如何防止内存泄露。定时器计时器及时销毁。合理使用闭包
两种定时器 setTimeout只在指定时间后执行一次。setInterval以指定时间为周期循环执行
防抖:所谓防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
节流:所谓节流,就是指连续触发事件但是在 n 秒中只执行一次函数。两种方式可以实现,分别是时间戳版和定时器版。
每一个实例对象都有一个叫做原型的私有属性----__proto__,指向它的构造函数的原型对象(prototype)。原型对象也有自己的__proto__,层层向上直到一个对象的原型对象为null
。这一层层原型就是原型链。 作用:实例对象的__proto__
指向构造函数的prototype
,从而实现继承。
55-2.js的继承方式有哪些
三种:1、原型链继承 2.构造函数继承 3.组合继承(两种方式混合)
作用域说明:作用域就是一个变量可以使用的范围,主要分为全局作用域和函数作用域
Es6中新增了块级作用域(由大括号包裹,比如:if(){},for(){}等)
1、作用域链:先在内部找,内部找不到去外部找
2、变量提升【悬挂声明】
3、优先级:变量>声明函数(不看书写顺序的)>参数>提升
****注意:
1、window.xxx或者xxx(前面没有var、let、const)
2、除了函数外,其他的没有作用域(if、for、switch)
字面量:
字面量创建对象更简单,方便阅读
不需要作用域解析,速度更快
new内部都实现了什么
1. 创建一个新对象
2. 构造函数的this指向于新对象
3. 执行构造函数中所有代码
4. 返回新对象
创建对象的方式(4种):new Object、字面量、构造函数、原型。
new 操作符 + Object 创建对象
字面式创建对象
工厂模式
构造函数模式
原型模式
混合模式(构造函数模式+原型模式)
尽量少使用全局变量,尽可能的使用局部变量,这样不仅会减少变量重名的几率,更会减少内存开校, 因为局部变量一般会在函数结束后自动销毁释放内存, 而全局变量会到程序结束后才会被销毁
60、== 和 ===的区别
==是非严格意义上的相等
值相等就相等
===是严格意义上的相等,会比较两边的数据类型和值大小
值和引用地址都相等才相等
延迟加载:defer
async:立即执行脚本,但不妨碍页面其他的操作(简单粗暴:谁加载快谁先执行)
单线程 :只有一个线程,只能做一件事
先执行主线程,主线程执行完毕后,去执行消息队列/事件队列(定时器、ajax等等)里,消息队列/时间队列=>先进先出
由于JS是单线程,在代码执行的时候,如果代码顺序执行,当前一段代码执行需要很长一段时间,就会影响后面代码的执行,带来的后果可能就是代码执行效率低,页面卡顿,用户体验差,为了避免这个问题,就出现了异步编程,通过回调函数来存放和执行异步代码,任务也划分为两种:同步任务和异步任务。
同步任务:即主线程上的任务,按照顺序由上至下依次执行,当前一个任务执行完毕后,才能执行下一个任务。
异步任务:不进入主线程,而是进入任务队列的任务,当主线程上的任务执行完后,才会执行任务队列里的任务,异步任务又分为宏任务和微任务
宏任务:script(整体代码)、setTimeout、setInterval、setImmediate(Node.js 环境)、UI事件、I/O(Node.js)
微任务:promise中的.then和.catch,process.nextTick()
执行顺序的总结:
1.主线程上的同步任务可以看做第一个宏任务,先执行主线程上的同步任务,将异步任务放入队列,宏任务放入下一个宏任务队列,微任务放入微任务队列,当主线程任务执行完成之后,就按照先进先出的原则执行所有的微任务,微任务执行完成后,开始执行下一个宏任务队列
2.当一个宏任务执行完成,如果微任务队列有微任务,会执行完所有微任务,再执行下一个宏任务
3.promise不属于微任务,只是promise.then()和.catch()才属于微任务
4.简单记法:主线程同步任务 = promise > promise.then() > setTimeout
64、call apply bind:
改变函数内部的this指向
call、apply、bind三个方法都有两个参数
call和apply都是立即执行函数,不必调用。第一个参数都是 this 的指向对象。call第二个参数可以接收任意个参数,apply第二个参数必须是数组或者类数组
bind(不会立即执行,需要调用 bind 返回的是一个新的函数,你必须调用它才会被执行),传参和call一样
string number boolen null undefined symbol
typeof undefinde //undefined
typeof 'abc' // string
typepf 123 //number
typeof true //boolen
typeof {} //object
typeof [] //object
typeof null //object
typeof console.log //function
instanceof 用来检测引用类型 object,包含function、Array
console.log([] instanceof Array);//true
console.log({} instanceof Object);//true
Object.prototype.toString 对象的一个原生原型扩展函数,用来精确的区分数据类型
var type=Object.prototype.toString
console.log(type.call(''));//object String
console.log(type.call([]));//object Array
console.log(type.call({}));//object Object
console.log(type.call(false));//object Boolean
console.log(type.call(null));//object Null
console.log(type.call(undefined));//object Undefined
console.log(type.call(function(){}));//object Function
作者先设计出来的null后设计的undefined
1、表示无的值最好别是对象,null typeof是object
2、null可以被自动转换成0·
作者又设计了undefined,来填补之前自己设计null的坑。
null表示"没有对象",即该处不应该有值。典型用法是:
undefined表示"缺少值",就是此处应该有一个值,但是还没有定义。NAN是一个数值类型但不是一个具体的数 NAN+数值返回的都是NAN
基本数据类型 是按值访问 相互不会产生影响(a=b a的值变了 b的值不会变)
引用类型 是按引用传递的
浅拷贝:浅拷贝只复制某个对象的引用,而不复制对象本身,新旧对象还是共享同一块内存
Object.assign() //是浅拷贝2、直接复制对象
深拷贝:深拷贝就是把一个对象,从内存中完整的拷贝出来,从堆内存中开辟了新区域,用来存新对象,并且修改新对象不会影响原对象
1>JSON.parse()【从一个字符串中解析出json对象】 + JSON. stringify()【从一个对象中解析出字符串】(缺点:1、如果obj里有RegExp(正则表达式的缩写)、Error对象,则序列化的结果将只得到空对象;2、如果obj里有函数,undefined,则序列化的结果会把函数或 undefined丢失;)
2>递归
③ 递归( 通用,从底层的角度 ) 基本思想 : 判断obj 是基本类型就简单赋值,对象(数组)的话 ,创建一个空[ ](obj是对象)或空{ }(obj是对象),再判断obj的属性有没有对象(数组),有递归调用递归(就是在运行的过程中不断地调用自己),没有简单赋值,直到全部赋值完毕,返回赋值后的new_obj ,
join:将数组中的每一个元素放进一个字符串. 例子:
arr={"I","love","you"};
str=arr.join(" ");//通过空格将数组组合成字符串 输出结果为 I love you
splite():用于把一个字符串分割成字符串数组
search():用于减缩字符串中指定的子字符串,或检索与正则表达式相匹配的字符串 indexOf():可返回某个字符换字符串中首次出现的位置
substring():用于提取字符串中介于两个指定下标之间的字符
trim():移除字符串两边的空格
replace():替换字符
数组操作方法
length:计算数组的长度 索引:通过索引获取数组中对应值,同时也可以改变索引对应的值 indexOf:返回指定元素的位置,若元素不存在返回-1
slice:接受 1-2 个参数,参数对应的是要返回的是要返回项的起始位置和结束位置,若只有一个 参数,该方法返回从参数指定位置到数组结尾的所有项,如果还有两个参数,则返回起始位置到结 束位置项,但是不包括结束位置项,返回的结果是一个新数组。
splice:t添加删除:删除任意数量的项,只需要传入两个参数即可。要删除的第一项的位置和要删除的项数。.添加:可以向指定位置添加任意的项,只需要提供三个参数即可:起始位置,0(要删除的项数)和要添加的项。如果要添加多项可以继续在后面写参数用逗号分隔。
push:向数组末位添加若干元素,返回添加元素后数组的长度
pop:删除数组末位后一个元素,但会被删除元素
unshift:向数组头部添加若干元素,返回添加元素后的数组长度
shift:删除数组头部的第一个元素,返回被删除的元素
sort:对数组进行排序,返回排序后的数组
reverse:对数组中的数据进行反转,返回反转后的数组
concat:将两个数组合并,返回新数组(可以接受任意元素和数组,并进行拆分放 入数组)
toFixed() 方法可把 Number 四舍五入为指定小数位数的数字。
Math.random()方法返回大于等于 0 小于 1 的一个随机数。
findIndex() 查找这一组数 符合条件的第一数的下标 给他返回出来 没有返回 -1
forEach:没有返回值 map:有返回值 filter能通过筛选条件快速给出遍历结果,不符合条件的就不会去遍历,符合条件的才会遍历,极大的节省了遍历开销成本 for of
71、for in for of的区别
1、推荐在循环对象属性的时候使用 for...in,在遍历数组的时候的时候使用 for...of
2、for...in 循环出的是 key,for...of 循环出的是 value
一、新增了const和let
var与let、const的区别
①var可以变量提升、var只有全局作用域和函数作用域、变量可以重复声明
②let不存在变量提升、属于块级作用域,声明的变量不能重复声明
④const 用于声明常量,必须赋值并且声明后不能再修改,无法重复声明,块级作用域。如果声明/的是复合类型数据,可以修改其属性。
二、模板字符串
我们想要将字符串和变量拼接起来,用反引号(``)将内容括起来,在反引号中,可以使用${}来写入需要引用到的变量。更方便地将字符串和变量连接起来。
三、剪头函数
箭头函数只有一个参数的时候可以省略小括号,只有一行代码的时候可以直接写在=>后面,不用写大括号return 当我们要把一个函数作为参数传入到另外一个函数里的时候用箭头函数是最多的
setTimeout(() =>{},1000)
剪头函数没有自己的this,会捕获其所在的上下文的this值,作为自己的this。(普通函数的this指向它的调用者,如果没有调用者则指向window)
箭头函数是匿名函数,不能作为构造函数,不能使用new
箭头函数没有自己的arguments对象
不需要 function 关键字来创造 省略 return 关键字
四、类和继承
class 和 extend 是一种语法糖,也是基于原型继承实现的 class 和 super calls,实例化,静态方法和构造函数
五、增强的对象字面量:
对象字面量被增强了,写法更加简洁与玲姐,同时在定义对象的时候能够做的事情更多了。
具体表现在:
可以在对象子里面量里面定义原型 定义方法可以不用 function 关键词 直接调用父类方法
六、解构:es6允许按照一定的模式,从数组和对象中提取值,对变量进行赋值,这被称为解构
单层解构:
const earth = {
people: '人类',
animal: '动物'
}
const { people, animal } = earth
console.log(people, animal);//人类 动物
七、参数默认值,不定参数,拓展参数:
默认参数值:
可以在定义函数的时候指定参数的默认值,而不用像以前那样通过逻辑或操作符来达到目的了。
八、for of 值遍历:
1、for in遍历的是数组的索引(即键名),而 for of遍历的是数组元素值。
2、for in会遍历数组所有的可枚举属性,包括原型。for of遍历的只是数组内的元素,而不包括数组的原型
3、for in遍历顺序有可能不是按照实际数组的内部顺序
4、for-of循环不支持普通对象,可以通过内建的Object.keys()方法:
for (var key of Object.keys(someObject)) {
console.log(key + ": " + someObject[key]);
}
//Object.keys:处理对象,返回可枚举的属性数组;(处理数组,返回索引值数组)
let person = {name:"张三",age:25,address:"深圳",getName:function(){}}
Object.keys(person) // ["name", "age", "address","getName"]
九、Map、Set 和WeakMap、WeakSet
新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。
Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。
Set 和 Map 主要的应用场景在于 数据重组 和 数据储存。
Set 是一种叫做集合的数据结构,Map 是一种叫做字典的数据结构。
Set 本身是一种构造函数,用来生成 Set 数据结构。
Set: Set 实例的方法分为两大类:操作方法(用于数据操作)和遍历方法(用于遍历数据)
操作方法:
add(value) 添加数据,并返回新的 Set 结构
delete(value) 删除数据,返回一个布尔值,表示是否删除成功
has(value) 查看是否存在某个数据,返回一个布尔值
clear() 清除所有数据,没有返回值
let set = new Set([1, 2, 3, 4, 4]);
// 添加数据 5
let addSet = set.add(5);
console.log(addSet); // Set(5) {1, 2, 3, 4, 5}
// 删除数据 4s
let delSet = set.delete(4);
console.log(delSet); // true 此处返回值是个boolean 表示 是否删除成功
// 查看是否存在数据 4
let hasSet = set.has(4);
console.log(hasSet); // false
// 清除所有数据
set.clear();
console.log(set); // Set(0) {}
数组去重的方法
ES6 set 方法:var arr = new Set([1,2,2,3,4]); console.log([...arr]); //(4) [1, 2, 3, 4]
遍历数组去重(indexOf方法)
实现思路:新建一个数组,遍历去要重的数组,当值不在新数组的时候(indexOf为-1)就加入该新数组中
十、Proxies
proxy 可以监听对象身上发生了什么事情,并在这些事情发生后执行一些相应的操作。一下子让我们对 一个对象有了很强的跟踪能力,同时咋数据绑定方面也很有用处。
十一、symbols
symbols 是一种基本类型,像数字、字符串还有布尔一样。表示独一无二的值。
十三、拓展运算符(...)对象中的扩展运算符(...)用于取出参数对象中的所有可遍历属性,拷贝到当前对象之中
let bar = { a: 1, b: 2 };
let baz = { ...bar }; // { a: 1, b: 2 }
[...'hello']
// [ "h", "e", "l", "l", "o" ]
十二、Promises
promise 是异步编程的一种解决方案:promise是一个对象,从它可以获取异步操作的消息;promise有三种状态: pending(等待态),fulfiled(成功态),rejected(失败态);promise是用来解决两个问题的:
new promise()Promise在创建的是时候 ,要求传入一个参数,这个参数本身是一个函数。我们可以传入一个剪头函数 new promise(()=>{}),这个函数本身包含两个参数new Promise((resolve,reject)=>{
}) //resolve,reject 本身它们又是函数
成功的时候用resolve
失败的时候用reject
// setTimeout(() => {
// console.log('Hello World')
// }, 1000);
// 参数->函数
new Promise((resolve,reject) =>{
setTimeout(() => {
resolve()
}, 1000)
}).then(()=>{
console.log('Hello World');
})
什么情况下用promise 一般情况下有异步操作时使用promise对异步操作进行封装
new完promise之后
sync同步 async异步
operation 操作 async poeration 异步操作
Promse.all在处理多个异步处理时非常有用,比如说一个页面上需要等两个或多个ajax的数据回来以后才正常显示,在此之前只显示loading图标。(Promise.all获得的成功结果的数组里面的数据顺序和Promise.all接收到的数组顺序是一致的,即p1的结果在前,即便p1的结果获取的比p2要晚。这带来了一个绝大的好处。)在前端开发请求数据的过程中,偶尔会遇到发送多个请求并根据请求顺序获取和使用数据的场景,使用Promise.all毫无疑问可以解决这个问题。 有任何一个失败,返回失败。失败的话就返回最先失败的结果,。比如当一个页面需要在很多个模块的数据都返回回来时才正常显示,否则loading。
Promse.race就是赛跑的意思,意思就是说,Promise.race([p1, p2, p3])里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态。race的使用场景就是,多台服务器部署了同样的服务端代码,假如我要获取一个商品列表接口,我可以在 race 中写上所有服务器中的查询商品列表的接口地址,哪个服务器响应快,就从哪个服务器拿数据。
宏任务:setTimeout、setInterval、setImmediate、requestAnimationFrame
微任务:process.nextTick、Promise.then catch finally
我们常见的异步操作例如:
有用过promise 吗?请写出下列代码的执行结果,并写出你的理解思路:
首先要讲一下,js 是单线程执行,那么代码的执行就有先后; 有先后,那就要有规则(排队),不然就乱套了,那么如何分先后呢?
73、JS同步任务和异步任务
单线程 :只有一个线程,只能做一件事
由于JS是单线程,在代码执行的时候,如果代码顺序执行,当前一段代码执行需要很长一段时间,就会影响后面代码的执行,带来的后果可能就是代码执行效率低,页面卡顿,用户体验差,为了避免这个问题,就出现了异步编程,通过回调函数来存放和执行异步代码,任务也划分为两种:同步任务和异步任务。
同步任务:即主线程上的任务,按照顺序由上至下依次执行,当前一个任务执行完毕后,才能执行下一个任务。
异步任务:不进入主线程,而是进入任务队列的任务,当主线程上的任务执行完后,才会执行任务队列里的任务,异步任务又分为宏任务和微任务
宏任务:script(整体代码)、setTimeout、setInterval、setImmediate(Node.js 环境)、UI事件、I/O(Node.js)
微任务:promise中的.then和.catch,process.nextTick()
执行顺序的总结:
1.主线程上的同步任务可以看做第一个宏任务,先执行主线程上的同步任务,将异步任务放入队列,宏任务放入下一个宏任务队列,微任务放入微任务队列,当主线程任务执行完成之后,就按照先进先出的原则执行所有的微任务,微任务执行完成后,开始执行下一个宏任务队列
2.当一个宏任务执行完成,如果微任务队列有微任务,会执行完所有微任务,再执行下一个宏任务
3.promise不属于微任务,只是promise.then()和.catch()才属于微任务
4.简单记法:主线程同步任务 = promise > promise.then() > setTimeout
nextTick(),是将回调函数延迟在下一次dom更新数据后调用,简单的理解是:当数据更新了,在dom中渲染后,自动执行该函数,更改数据后当你想立即使用js操作新的视图的时候需要使用它
Vue生命周期的created()钩子函数进行的DOM操作一定要放在Vue.nextTick()的回调函数中,原因是在created()钩子函数执行的时候DOM 其实并未进行任何渲染,而此时进行DOM操作无异于徒劳,所以此处一定要将DOM操作的js代码放进Vue.nextTick()的回调函数中。
场景:
1)第三方插件,在vue生成的某些dom动态发生变化时重新应用该插件。
2)视图更新之后,基于新的视图进行操作。
性能是留住用户很重要的一环,如果一个网页三秒钟打不开,很多人就会离开,性能优化也是程序高效运行的保障。
我们优化的对象是什么?
优化对象是程序,以及程序所运行在的载体(如浏览器)
我们已经知道了性能优化的对象是什么了,那么接下来就可以根据优化对象分开几个大类总结,对于前端来说,程序和载体无非以下5点:
html
css
js
程序相关的工具
浏览器
这样我们再展开去说就能说的清楚,不会遗漏。
总结每个大类的时候,先从整个文档格式开始,再到外部资源,再到代码层面
1. html
html应该首先想到语义化标签,正确的语义化可以我们的文档结构更加清晰。
语义化标签,结构清晰
js文件正确放置,防止阻塞
2.css
css文件应该放在body标签顶部,防止页面二次渲染而抖动。
当小图片多的时候可以使用雪碧图,减少页面请求。
公共的css抽离,代码复用
多个css合并,减少HTTP请求
选择器优化嵌套,尽量避免层级过深,缩短查找过程
充分利用css继承属性,减少代码量
减少页面的重绘,可以先用一个变量操作所有样式后,最后一步把这个变量关联到dom上
3.js 总结(语义化标签,结构清晰;css文件应该放在body标签顶部,防止页面二次渲染而抖动。当小图片多的时候可以使用雪碧图,减少页面请求。公共的css抽离,代码复用,抽离公共的js,代码复用;抽离公共的组件,代码复用;定时器记得清除,较少内存的耗用
v-if和v-show正确使用,较少页面dom的构建;节流、防抖,防止意外的触发;v-for 遍历 添加 key,且避免同时使用 v-if;路由懒加载;图片懒加载;)
抽离公共的js,代码复用
抽离公共的组件,代码复用
定时器记得清除,较少内存的耗用
v-if和v-show正确使用,较少页面dom的构建
节流、防抖,防止意外的触发
长列表滚动到可视区域动态加载(大数据渲染)
computed 和 watch 区分使用场景,减少性能消耗
v-for 遍历 添加 key,且避免同时使用 v-if
4.webpack
去除代码注释,压缩程序
Webpack 对图片进行压缩-------先引入npm install image-webpack-loader --save-dev,然后在 webpack.config.js 中配置
减少 ES6 转为 ES5 的冗余代码
提取公共代码
模板预编译
优化 SourceMap
构建结果输出分析
使用webpack-bundle-analyzer查看项目所有包及体积大小
5. 浏览器
首屏加载loading,优化体验
使用缓存,减少重复请求
启用gzip压缩,减少请求
使用cnd,缩短请求链
使用图片懒加载,组件懒加载,路由懒加载,减少请求
第三方插件的按需引入
服务端渲染 SSR or 预渲染
使用 Chrome Performance 查找性能瓶颈,针对性的优化
MVVM 分为 Model、View、ViewModel 三者。
Model 和 View 通过 ViewModel 来进行联系的 采用双向绑定(data-binding)这种模式实现了 Model 和 View 的数据自动同步,因此开发者只需要专注对数据的维护操作即可,而不需要自己操作 dom。
v-if:判断是否为真,然后重组、销毁 DOM 节点
v-for:数据循环
v-bind:v-bind用来绑定数据和属性以及表达式
v-model:实现双向绑定
v-on:添加事件 v-on 指令用于绑定HTML事件 :v-on:click 缩写为 @click
v-on可以监听多个方法吗?
v-else:配合 v-if 使用
自定义指令:使用vue.dirctive。// 注册一个全局自定义指令 v-focus 该指令的功能是在页面加载时,元素获得焦点 Vue.directive('focus', { // 当绑定元素插入到 DOM 中。 inserted: function (el) { // 聚焦元素 el.focus()
全局自定义指令和局部自定义指令
1.首先我们来看全局自定义指令 :用Vue.directive来注册。
比如一个input自动聚焦的例子:在main.js中写入以下内容:
// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el) {
// 聚焦元素
el.focus()
}
})
directives
属性
directives: {
focus: {
// 指令的定义
inserted: function (el) {
el.focus()
}
}
}
v-focus
:做一个唯一标识。key的作用主要是为了高效的更新虚拟DOM。key值是在DOM树进行diff算法(同层的树节点进行比较)时候发挥作用。一个是用来判断新旧Vnode(虚拟DOM)是否为同一个,从而进行下一步的比较以及渲染。另外一个作用就是判断组件是否可以复用,是否需要重新渲染。
v-for比v-if优先级高,同时作用在同一个元素上,(每次渲染都会先循环再进行条件判断)这意味着 v-if 将分别重复运行于每个 v-for 循环中带来性能上的浪费。需要v-if
置于外层元素或在外层嵌套template(页面渲染不生成dom节点),在这层进行v-if判断,然后在内部进行v-for循环。
因为组件是可以复用的, JS 里对象是引用关系, 如果组件 data 是一个对象, 那么子组件中的 data 属性值 会互相污染, 产生副作用。
所以一个组件的 data 选项必须是一个函数, 因此每个实例可以维护一份被返回对象的独立拷贝。new Vue 的实例是不会被复用的,因此不存在以上问题。
用普通js对象来描述DOM结构 ,以对象嵌套的方式来表示 dom 树及其层级结构,那么每次 dom 的更改就变成了对 js 对象的属性的增删改查,这样一来性能开销小。因为不是真实DOM,所以称之为虚拟DOM,
vue的双向绑定是采用数据劫持结合发布者-订阅者模式的方法,通过object,define.property()来劫持各个属性的setter和getter,在数据发生变化时发布消息给订阅者,触发相应的监听回调。
不能监听到对象属性的监听添加和删除,需要vue.set()来添加和删除
区别: computed 计算属性: 依赖其它属性值, 并且computed 的值有缓存, 只有它依赖的属性值发生改变, 下一 次获取 computed 的值时才会重新计算computed 的值 。不支持异步
watch
1、watch是监听器,可以监听某一个数据,然后执行相应的操作;
2、不支持缓存,数据变直接会触发相应的操作;
3、监听的函数接收两个参数,第一个参数是最新的值;第二个参数是输入之前的值;
4、支持异步操作;
methods:表示一系列具体的操做,适合书写大量的业务逻辑
当一个属性受多个属性影响的时候,使用computed-------购物车商品结算。watch----当一条数据影响多条数据的时候,使用watch-------搜索框。
是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。
在vue中用axios进行网络请求。 这个是vue的作者推荐使用的
功能特点:
支持promise API
支持拦截请求和响应
支持转换请求和响应数据
axios有哪些常用方法?
一、axios.get(url[, config]) //get请求用于列表和信息查询
二、axios.delete(url[, config]) //删除
三、axios.post(url[, data[, config]]) //post请求用于信息的添加
四、axios.put(url[, data[, config]]) //更新操作
axios是通过promise实现对ajax技术的一种封装,新建一个Axios对象时,会有两个拦截器。request拦截器,response拦截器。
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么,例如加入token
.......
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
axios.interceptors.response.use(function (response) {
// 在接收响应做些什么,例如跳转到登录页
......
return response;
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error);
});
3、说下你了解的axios相关配置属性?
答:url
是用于请求的服务器URL
method
是创建请求时使用的方法,默认是get
baseURL
将自动加在url
前面,除非url
是一个绝对URL。它可以通过设置一个baseURL
便于为axios实例的方法传递相对URL
transformRequest
允许在向服务器发送前,修改请求数据,只能用在'PUT','POST'和'PATCH'这几个请求方法
headers
是即将被发送的自定义请求头
headers:{'X-Requested-With':'XMLHttpRequest'},
params
是即将与请求一起发送的URL参数,必须是一个无格式对象(plainobject)或URLSearchParams对象
params:{
ID:12345
},
auth
表示应该使用HTTP基础验证,并提供凭据
这将设置一个Authorization
头,覆写掉现有的任意使用headers
设置的自定义Authorization
头
auth:{
username:'janedoe',
password:'s00pers3cret'
},
'proxy'定义代理服务器的主机名称和端口auth
表示HTTP基础验证应当用于连接代理,并提供凭据
这将会设置一个Proxy-Authorization
头,覆写掉已有的通过使用header
设置的自定义Proxy-Authorization
头。
proxy:{
host:'127.0.0.1',
port:9000,
auth::{username:'mikeymike',password:'rapunz3l'}},
Ajax可以实现动态不刷新(局部刷新)
就是能在不更新整个页面的前提下维护数据。这使得Web应用程序更为迅捷地回应用户动作,并避免了在网络上发送那些没有改变过的信息
1、什么是vue生命周期?
答: Vue 实例从创建到销毁的过程,就是生命周期。
2、vue生命周期的作用是什么?
答:它的生命周期中有多个事件钩子,让我们在控制整个Vue实例的过程时更容易形成好的逻辑。
3、vue生命周期总共有几个阶段?
答:它可以总共分为8个阶段:创建前/后, 载入前/后,更新前/后,销毁前/销毁后。
4、第一次页面加载会触发哪几个钩子?
答:第一次页面加载时会触发 beforeCreate, created, beforeMount, mounted 这几个钩 子。
5、DOM 渲染在 哪个周期中就已经完成?
答:DOM 渲染在 mounted 中就已经完成了。
6、生命周期的含义:
beforecreate
:el 和 data 并未初始化,还不能访问data、computed、watch、methods上的方法和数据 可以在这加个loading加载事件,在加载实例时触发created
:完成了 data 数据的初始化,el没有,可以访问到data、computed、watch、methods上的方法和数据,在这里结束loading加载事件,可以做前后端的交互, 例:异步请求如ajaxbeforeMount
:完成了 el 和 data 初始化
mounted
当前生命周期el已经挂载到文档里 可以操作DOM节点
beforeUpdate
在数据更新之前调用,发生在虚拟DOM重新渲染和打补丁之前。可以在该钩子中进一步地更改状态,不会触发附加的重渲染过程。
updated
当前生命周期更新的数据与模板结合完毕 可以做一个确认停止事件的确认框
beforeDestroy
在实例销毁之前调用。实例仍然完全可用。当前生命周期做一些移除的操作。例:监听的移除,定时器的移除,事件的解绑
destroyed
在实例销毁之后调用。调用后,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务器端渲染期间不被调用。
7、简单描述每个周期具体适合哪些场景?
生命周期钩子的一些使用方法:
beforecreate : 可以在这加个loading事件,在加载实例时触发 ;
created : 初始化完成时的事件写在这里,如在这结束loading事件,异步请求也适宜在这里调用 ;
mounted : 挂载元素,获取到DOM节点 ;
updated : 如果对数据统一处理,在这里写上相应函数 ;
beforeDestroy : 可以做一个确认停止事件的确认框 ;
nextTick : 更新数据后立即操作dom;
created和mounted的区别
答:created:在模板渲染成html前调用,即通常初始化某些属性值,然后再渲染成视图。
mounted:在模板渲染成html后调用,通常是初始化页面完成后,再对html的dom节点进行一些需要的操作。
父子组件的生命周期中,首先走父组件的生命周期,当父组件的生命周期走完beforeMount(挂在前)这个函数时就会走子组件的生命周期,当子组件挂载完成后(执行完mounted)父组件在挂载dom节点。
vue获取数据在哪个周期函数
答:一般 created/beforeMount/mounted 皆可.
比如如果你要操作 DOM , 那肯定 mounted 时候才能操作.
调接口在哪个周期:created、mounted
使被包含的组件保留状态,或避免重新渲染 。也就是所谓的组件缓存。当用了keep-alive以后会多两个生命周期。deactivat、activatede.如果使用了keep-alive在第一次加载会执行五个生命周期。第二次或第n次进入只执行deactivat、 activatede
v-show 指令是通过修改元素的 display 的 属性让其显示或隐藏
v-if 指令是直接销毁和重建 DOM 节点,达到让元素显示和隐藏的效果
89.echarts 分辨率
有个resize()
答:Vuex是为vue.js应用程序开发的状态管理工具。应用遇到多个组件共享状态时,使用vuex。场景:多个组件共享数据或者是跨组件传递数据时。每一个vuex应用核心就是store(仓库)。store基本上就是一个容器,它包含着你的应用中大部分的state(状态)
安装 npm i vuex --save/...在src文件目录下新建store>index.js文件
import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); const store = new Vuex.Store(); export default store;xl
const store = new Vuex.Store({...});
2.Vuex解决了什么问题?
答:多个组件共享数据或者是跨组件传递数据时。
3.vuex使用与什么场景?
答:单页应用中,组件之间的状态。音乐播放、登录状态、加入购物车
4.vuex有哪几种属性?
答:state、getters、mutations、actions、modules 。
①state:vuex的基本数据,用来存储变量(state:{userId:''}),在vue中使用this.$store.state.userid
②getter:从基本数据(state)派生的数据,相当于state的计算属性,具有返回值的方法。getter:{userIdDouble:function(state){return state.userId×2}在vue中使用this.$store.getters.useridDouble
③mutation:提交更新数据的方法,必须是同步的(如果需要异步使用action)。在Vuex中修改数据只能在Mutations中,不能再其他地方修改。不能直接调用一个 mutations 中的处理函数 要使用this.$store.commit(“mutations中你要修改的函数名”) 来进行调用
mutations: {
SET_USER: (state, userId) => {
state.userId = "我被修改了“
},
},
commit:同步操作,写法: this.$store.commit(‘SET_USER’)
在实际项目中往往会有值传递给Mutations 给store.commit传一个附加参数,他就叫做mutation的载荷
也就是你在调用vuex中的方法的同时,可以传递一个参数过去,对vuex中的数据进行了修改
如果需要传递多个参数可以直接传递一个对象如:
列如:this.$store.commit('SET_USER','我是传递过来的数据')、、、
mutations: {
SET_USER: (state, newmsg) => {
state.useId =newmsg /newmsg接受了传递过来的数据将数据复制给了state中的userId
} },
回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数,提交载荷作为第二个参数
④. action:和mutation的功能大致相同,不同之处在于 ==》1. Action 提交的是 mutation,而不是直接变更状态。 2. Action 可以包含任意异步操作。
actions: { // {} 是es6中解构,把对象解构成属性
login({ commit }, value) {
commit('SET_USER', value)
// commit('SET_TOKEN', value2) },}
dispatch:异步操作,写法: this.$store.dispatch(‘mutations方法名’,值)
⑤. modules:模块化vuex,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。
简单来说就是可以把以上的 state、mutation、action、getters 整合成一个user.js,然后放到store.js里面
5.Vuex中状态储存在哪里,怎么改变它?
答:存储在state中,改变Vuex中的状态的唯一途径就是显式地提交 (commit) mutation。
6.Vuex中状态是对象时,使用时要注意什么?
答:对象是引用类型,复制后改变属性还是会影响原始数据,这样会改变state里面的状态,是不允许,所以先用深度克隆复制对象,再修改。
7.怎么在组件中批量使用Vuex的state状态?
答:使用mapState辅助函数, 利用对象展开运算符将state混入computed对象中
import {mapState} from 'vuex' export default{ computed:{ ...mapState(['price','number']) } }
8.Vue.js中ajax请求代码应该写在组件的methods中还是vuex的actions中?
答:如果请求来的数据是不是要被其他组件公用,仅仅在请求的组件内使用,就不需要放入vuex 的state里。
如果被其他地方复用,这个很大几率上是需要的,如果需要,请将请求放入action里,方便复用。
登录后用户信息用mutation储存到vuex的states里,然后在beforeach里面从state里把状态取出来,这样就避免每跳一个路由就要登录。但是在页面刷新的时候会丢失数据。所有存的就全部都丢失,刷新了,所以额外加了一个用localstorage,如果用sessionstorage的话,你当前页面一关下个页面你就还要再登,我们项目里其实用的是localstorage,就是说在state里面也去存,也在localstorage里面也去存。
Async await 是用来使异步操作同步化的,比如项目需求里有的流程需要按照顺序去执行异步请求,就可以使用await去阻塞后面的代码,确保请求按照我们想要的顺序执行。
1.会自动将常规函数转换成Promise,返回值也是一个Promise对象
2.只有async函数内部的异步操作执行完,才会执行then方法指定的回调函数
3.异步函数内部可以使用await
4.await 放置在Promise调用之前,await 强制后面点代码等待,直到Promise对象resolve,得到resolve的值作为await表达式的运算结果
5.await只能在async函数内部使用,用在普通函数里就会报错
父传子数据,在子组件中不能修改会报错,如果要修改,需要在子组件新建一个data属性,进行修改。vuex是单向数据流
父子通信: 父向子传递数据是通过 props,子向父是通过 $emit;通过 $parent / $children 通信;$ref 也可以访问组件实例(为子组件赋予一个ID引用,父组件用来访问子组件实例或子元素
1、在子组件中:
是必须要存在的 2、在父组件中:首先要引入子组件 import Child from './child';3、);provide / inject ;$attrs / $listeners;
兄弟通信: EventBus;Vuex;
跨级通信: EventBus;Vuex;provide / inject ;$attrs / $listeners;
是将回调函数延迟在下一次dom更新数据后调用,简单的理解是:当数据更新了,在dom中渲染后,自动执行该函数,
Vue生命周期的created()钩子函数进行的DOM操作一定要放在Vue.nextTick()的回调函数中,原因是在created()钩子函数执行的时候DOM 其实并未进行任何渲染,而此时进行DOM操作无异于徒劳,所以此处一定要将DOM操作的js代码放进Vue.nextTick()的回调函数中。
拉取远程仓库:$ git pull [remoteName] [localBranchName]
推送远程仓库:$ git push [remoteName] [localBranchName]
查看本地分支:$ git branch
查看所有分支:$git branch -a
查看远程分支:$ git branch -r
新建分支:git checkout -b '分支名称'
git branch –set-upstream 本地新建分支名 origin/远程分支名
拉取远程分支并创建本地分支 git checkout -b 本地分支名x origin/远程分支名x
切换到master分支上 git checkout master
一.git提交代码简单流程
第一次使用前的指令:
git config user.name [用户名] 第一次使用前,需要配置用户名
git config user.email [邮箱] 第一次使用前,需要配置邮箱
git clone [git的仓库地址] 克隆git仓库代码
开发常用指令:
git status 查看有变更的文件
git diff [文件名] / . 查看文件修改内容/查看所有文件修改内容
git add [文件名] / . 提交文件/所有文件到暂存区
git checkout [文件名] 撤销文件修改
git commit -m '提交信息' 提交文件到仓库区
git log 查看提交记录
git pull origin [分支名] 拉取远程分支的最新代码,在push之前最好进行这个指令
git push origin [分支名] 上传本地指定分支到远程仓库
多人开发常用指令:
git cheackout [分支名] 切换到分支
git checkout -b [分支名] 创建并且切换到新分支上
git branch 查看分支
git merge [分支名] 合并分支
是把要合并的分支合并到当前分支上,注意当前分支是哪条分支
如果有冲突conflict用vscode解决冲突
merge之后需要进行 git commit -m '提交信息'
Git提交代码步骤
1.1 第1步:同步远程仓库代码:git pull
1.2 第1步:查看当前状态:git status
1.3 第2步:提交代码到本地git缓存区:git add
1.4 第3步:推送代码到本地git库:git commit git commit 文件名 -m "提交代码备注"
1.5 第5步:提交本地代码到远程仓库:git push
git解决冲突步骤
git命令在提交代码前,没有pull拉最新的代码,因此再次提交出现了冲突
1、git stash (这是将本地代码回滚值至上一次提交的时候,就是没有你新改的代码)。
2、git pull origin master(将远程的拉下来)。
3、git stash pop(将第一步回滚的代码释放出来,相等于将你修改的代码与下拉的代码合并)。
然后解决冲突,你本地的代码将会是最新的代码。
4、git add .
5、git commit -m""。
6、git push origin master。
这几步将代码推至了远程,最后再git pull origin master 一下,确保远程的全部拉下来。
提交代码:
合并分支:
合并步骤:
1、进入要合并的分支(如开发分支合并到master,则进入master目录)
git checkout master
git pull
2、查看所有分支是否都pull下来了
git branch -a
3、使用merge合并开发分支
git merge 分支名
4、查看合并之后的状态
git status
添加:$git add
撤销:$git reset
创建本地分支:$ git branch [name] ----注意新分支创建后不会自动切换为当前分支
写完代码要先拉取,再推送
1.3提交时发生冲突如何解决?
原因:
因为在合并分支的时候,master和dev分支恰好有人都修改了同一个文件,git不知道以哪一个文件为准,就产生了冲突。
解决:
发生冲突时,对比本地文件和远程分支上的文件,然后把远程分支上的内容手工修改到本地文件,然后再提交冲突文件。必要时可以和同时沟通。
git stash //把工作区的修改提交到栈区,目的是保存工作区的修改
git pull //拉取远程分支上的代码并合并到本地分支,目的是消除冲突
git stash pop //把保存在栈区的修改部分合并到最新的工作空间中\
产品宣贯。然后UI根据产品宣贯的东西出UI图,后端出后端设计,然后后端设计评审。前端前期根据UI设计画图,后期和后端进行接口联调。然后提测,出几个版本。缺陷收敛了之后再发布上线.前期。后端会先给我提供假数据方便我们开发,这样接口联调的时候会快一些
单页面应用(SPA),通俗一点说就是指只有一个主页面的应用,浏览器一开始要加载所有必须的 html, js, css。所有的页面内容都包含在这个所谓的主页面中。
多页面(MPA),就是指一个应用中有多个页面,页面跳转时是整页刷新
单页面的优点:
1,用户体验好,快,内容的改变不需要重新加载整个页面,基于这一点spa对服务器压力较小
2,前后端分离
3,页面效果会比较炫酷(比如切换页面内容时的专场动画)
单页面缺点:
1,不利于seo
2.不可以使用浏览器的导航按钮需要自行实现前进后退
3,初次加载时耗时多
4,页面复杂度提高很多
1.安装 2.配置相关信息:引用(import) 通过vue.use(插件),安装 创建VueRouter对象。 将router对象传入到实例中(导出再main.js中导入)
路由的默认路径:const routes = [{path:'', (//redirect 重定向) redirect:'/home},
history模式:传入mode:'history'
active-class是router-link终端属性,用来做选中样式的切换,当router-link标签被点击时将会应用这个样式
路由之间是怎么跳转的?有哪些方式
1.
2、this.$router.push()跳转到指定的url,并在history中添加记录,点击回退返回到上一个页面
3、this.$router.replace()跳转到指定的url,但是history中不会添加记录,点击回退到上上个页面
4、this.$touter.go(n)向前或者后跳转n个页面,n可以是正数也可以是负数
this.$router.push('/home')/this.$router.replace('/home')页面也会通过路由跳转
1、 this.$router.push进行编程式路由跳转
2、 router-link 进行页面按钮式路由跳转
3、 this.$route.params获取路由传递参数
4、this.$route.query获取路由传递参数
路由传参三种方式:第一种(页面刷新不会丢失):直接调用$router.push实现携带参数的跳转 this.$router.push({path:'/particulars/${id}'.需要在path中添加/:id来对应 $router.push 中path携带的参数。子组件中获取传递的参数值:this.$route.params.id
第二种(页面刷新数据会丢失):通过路由属性中的name来确定匹配的路由,通过params来传递参数。this.$router.push({name:'particulars',params:{id:id})
对应路由配置: 注意这里不能使用:/id来传递参数了,因为组件中,已经使用params来携带参数了.
path:'/particulars', name:'particulars', component:particulars
子组件中获取传递的参数值:this.$route.params.id
第三种方法:使用path来匹配路由,然后通过query来传递参数this.$router.push({path:'particulars',query:{id:id})
这种情况下 query传递的参数会显示在url后面?id=?
path:'/particulars', name:'particulars', component:particulars
子组件中获取传递的参数值:this.$route.query.id
路由懒加载 将路由对应的组件打包成一个个的js代码块,只有在这个路由被访问到的时候,才加载对应的组件。const routes=[{path:'/home', compoent: ()=>import('/..components/Home'}
路由嵌套:实现路由嵌套有两个步骤:①创建对应子组件,并且在路由映射中配置相应的 子路由②组件内部使用
路由嵌套:
{path:'/home',
component:Home,
children:[
{path:'new',
component:HomeNews}]
$route和$router的区别:$router为VueRouter实例,想要导航到不同URL,则使用$router.push方法 $route对象表示当前的路由信息,里面可以获取name、path、query、params等
导航守卫:全局守卫:beforeEach afterEach
前置守卫(guard):跳转前回调:beforeEach。必须调用next()函数。回调函数中的参数,to:进入到哪个路由去,from:从哪个路由离开,next:函数,决定是否展示你要看到的路由页面。
1. beforeEnter:(to,from,next)=>{},用法与全局守卫一致。只是,将其写进其中一个路由对象中,只在这个路由下起作用。
后置钩子(hook):跳转后回调。也就是afterEach,不需要主动调用next()函数
问你路由守卫你就说,我们项目里用过全局前置守卫 beforeEach 用来在路由跳转前确认用户是否登录,是否拥有这条路由的权限。还有就是组件内守卫beforeRouteleave,用来在用户发作业流程中退出,给他弹二次确认弹窗,确认是否要退出用的
100、vue项目中实现用户登录及token验证
在前后端完全分离的情况下,Vue项目中实现token验证大致思路如下:
1、第一次登录的时候,前端调后端的登陆接口,发送用户名和密码
2、后端收到请求,验证用户名和密码,验证成功,就给前端返回一个token
3、前端拿到token,将token存储到localStorage和vuex中,并跳转路由页面
4、前端每次跳转路由,就判断 localStroage 中有无 token ,没有就跳转到登录页面,有则跳转到对应路由页面
5、每次调后端接口,都要在请求头中加token
6、后端判断请求头中有无token,有token,就拿到token并验证token,验证成功就返回数据,验证失败(例如:token过期)就返回401,请求头中没有token也返回401
7、如果前端拿到状态码为401,就清除token信息并跳转到登录页面
1.hash模式
特点:在url地址上有#号
实现的原理:原生的hasChange事件来实现,来监听hash值的变化
window.onhaschange=function(){}
刷新页面的时候:不会去发送请求,页面不会有任何问题,不需要后端来配合
2.history模式
特点:在url地址上没有#号,比较与hash模式看起来好看一些
实现的原理:利用的是history的api 来实现的 popState() 来实现的
刷新页面的时候:会去发送请求然后会导致页面出现找不到的情况,需要后端来配合解决
import 是 ES6 的模块化语法。require 是赋值过程并且是运行时才执行, import 是解构过程并且是编译时执行。require可以理解为一个全局方法,所以它甚至可以进行下面这样的骚操作,是一个方法就意味着可以在任何地方执行。而import必须写在文件的顶部。require的性能相对于import稍低,因为require是在运行时才引入模块并且还赋值给某个变量,而import只需要依据import中的接口在编译时引入指定模块所以性能稍高3.在commom.js 中module.export 之后 导出的值就不能再变化,但是在es6的export中是可以的。
父子组件生命周期顺序
父beforeCreate -> 父created -> 父beforeMount -> 子beforeCreate -> 子created -> 子beforeMount -> 子mounted -> 父mounted
103.你都做过哪些 Vue 的性能优化?
这里只列举针对 Vue 的性能优化,整个项目的性能优化是一个大工程。
对象层级不要过深,否则性能就会差。
不需要响应式的数据不要放在 data 中(可以使用 Object.freeze() 冻结数据)
v-if 和 v-show 区分使用场景
computed 和 watch 区分场景使用
v-for 遍历必须加 key,key最好是id值,且避免同时使用 v-if
大数据列表和表格性能优化 - 虚拟列表 / 虚拟表格
防止内部泄露,组件销毁后把全局变量和时间销毁
图片懒加载
路由懒加载
异步路由
第三方插件的按需加载
适当采用 keep-alive 缓存组件
防抖、节流的运用
服务端渲染 SSR or 预渲染
Axios是AJAX的封装,基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。
vue项目中使用ajax时需要axios插件
下载方式cnpm install axios --save
import axios from './index'
const preUrlPath = _global.config.API_HOST
/**
* 查询全部数据
* @param params
* @returns {*}
*/
const getData = (params) => {
return axios.get(preUrlPath + '/rest/system/capabilityEvaluation/capabilityEvaluation', {params: params})
}
/**
* 查询全部数据
* @param params
* Put
* @returns {*}
*/
const updateData = (params) => {
return axios.post(preUrlPath + '/rest/system/capabilityEvaluation/capabilityEvaluation', params)
}
吸顶——滚动吸顶
项目有个滚动吸顶的需求。主要是用到了两个属性。一个是offsettop(当前对象到期上级顶部的距离),一个是scrollTope(页面被卷去的高度,只有可以滚动的页面里有)。通过监听页面的滚动事件。在监听回调里获取scrollTop的值,与offsetTop做对比。当scrollTop>=offsetTop时,使吸顶元素的css样式变为固定定位。小于时,再使吸顶元素回到文档流中。
106、大屏适配
在做大屏可视化项目的时候,一般设计稿会设计成1920*1080,但是页面写死1920*1080在2k、4k等分辨率的屏幕下是不适配的。
适配方式一:
适配方案采用rem布局, 根据屏幕分辨率大小不同,调整根元素html的font-size, 从而达到每个元素宽高自动变化,适配不同屏幕
适配方式二:
等比缩放,css3的transform:scale进行等比缩放
使用 roc-scale-box 组件,vue2与vue3都支持,使用非常简单,引入之后组件内所有内容都会按照设置的宽高比例进行缩放,还有屏幕缩放防抖优化
也适用于项目开发完成后发现需要做适配,引入组件包裹项目根节点即可。
属性:
width 宽度 默认 1920
height 高度 默认 1080
bgc 背景颜色 默认 "transparent"
delay自适应缩放防抖延迟时间(ms) 默认 100
@scaleChange 缩放值发生改变的方法 可动态获取 scale 改变后的值