前端面试题(HTML+CSS+JS+VUE+REACT)

前端 专栏收录该内容
10 篇文章 0 订阅

HTML+css

1. 网络中使用最多的图片格式有哪些

• gif 支持动画,只有全透明和不透明两种模式,只有 256 种颜色
• jpg 采用有损压缩算法,体积较小,不支持透明,不支持动画
• png 采用有损压缩算法,体积也相对较小,支持透明背景,不支持动画
• svg 一般会保存颜色及形状相对简单的图片,可任意放大图形显示,边缘异常清晰
• BMP 无损压缩格式,画质最好,文件太大,不利于网络传输

2. 请简述 css 盒子模型

在网页中,一个元素占有空间的大小由几个部分构成,其中包括元素的内容(content),元素的内边距(padding),元素的边框(border),元素的外边距(margin)四个部分,这就是盒子模型。

3. 视频/音频标签的使用

• 视频

o 属性: controls 控件、autoplay: 自动播放谷歌和火狐静音下支持 ie 支持、muted 静音播放、loop 循环、poster 未播放前显示的内容
• 音频

o 属性: controls 控件、autoplay 自动播放谷歌不支持,火狐静音下支持 ie 支持、loop 循环播放、muted 静音播放

4.HTML5 新增的内容有哪些

• h5 的语法
o DOCTYPE 可以使用小写
o 单标签没有结束标签
o 可以省略结束的标签: li、dt、dd、p、option、colgroup(用于对表格中的列进行
组合,以便对其进行格式化)、thead、tbody、tfoot、 tr、td、th
o 可以省略的标签 html head body tbody
• 新增标签特点:语义化,ie8 及以下不生效
o header 标签头部
o section 划分板块
o article 与上下文无关的内容
o aside 可以放侧边工具栏
o nav 导航
o figure 和 figcaption 类似于 dl 标签
o footer 底部
o main 比较重要的部分
o mark 标记默认是黄色的高亮,可以修改样式内联10
• 多媒体标签
o 音频

<audio src="课堂示例/梦然-少年.mp3" controls autoplay loop muted></audio> 
内联
<audio controls>
<source src="./梦然-少年.ogg"
type="audio/ogg"></source>
<source src="./梦然-少年.mp3"
type="audio/mpeg"></source>

controls 控件
autoplay 自动播放谷歌不支持,火狐静音下支持 ie 支持
loop 循环播放
muted 静音播放
o 视频

<video src="./qr.ogg" controls height="300" autoplay loop muted>
</video>
<video controls>
<source src="./wje.mp4" type="video/mp4"></source>
<source src="./wje.ogg" type="video/ogg"></source>
<source src="./wje.webm" type="video/webm"></source>

controls 控件
autoplay: 自动播放谷歌和火狐静音下支持 ie 支持
muted 静音播放
loop 循环
poster 未播放前显示的内容
• 表单新增
o type 类型
email 邮件格式
number 限制输入是数字 min 最小值 max 最大值 step 每次增加的数
url 地址路径或者网址都可以
color 色块
time 时间
range 滑动条
o 属性
required 必填

placeholder 提示信息
autocomplete 自动提示 on 提示 off 不提示

autofocus 自动聚焦只能写一个
multiple 多选

pattern 正则限制输入的内容类型
限制输入 0-9 之间的数11

5.Css3 新增的特性

css3 选择器
o 属性选择器
[属性名] 可以选择到官方或者自定义的属性
[属性名=“属性值”] 匹配属性值
[属性名~=""] 包含该值必须单独出现的
[属性名*=""] 只要包含该值就行
[属性名^=""] 以该值开头
[属性名$=""] 以该值结尾
o 伪类选择器
构性伪类选择器(child 系列)
1.E:first-child E 必须是父元素里面的第一个孩子
2.E:last-child E 必须是父元素里面的最后一个孩子
3.E:nth-child(n) 不匹配前面的元素类型,如果对应的位置是该元素才匹

4. E:only-child 必须只有他自己一个孩子
结构性的伪类选择(type 系列)
1.E:first-of-type 匹配到该元素中的第一个孩子
2.E:last-of-type 匹配到该元素的最后一个孩子
3.E:nth-of-type(n) 匹配到该元素的第几个孩子 n 可以是表达式 2n 3n
2n+1 even(偶数) odd(奇数)
4.E:nth-last-of-type(n) 匹配到该元素的倒数第几个
目标伪类:结合锚点使用
状态伪类选择器
1.:enabled 元素可编辑
2.:disabled 元素不可编辑
3.:checked 选中
4.::selection 高亮状态一般修改字体颜色和背景色
动态伪类选择器
1.:link 未访问前
2.:visited 访问过后
3.:hover 鼠标滑过
4.:active 鼠标点击之后
层级选择器
后代选择器选择器选择器
子项选择器选择器>选择器
相邻的兄弟选择器+选择器紧挨着的兄弟
相邻的兄弟们选择器~选择器紧挨着的弟弟们
o css3 属性
阴影

  1. box-shadow:x 轴偏移 y 轴偏移模糊距离阴影的颜色阴影的位置
    (outset/inset);12
  2. text-shadow:x 轴偏移 y 轴偏移模糊距离阴影的颜色;
    透明
    rgba 设置透明度
    里面的内容不会被模糊
    opacity:0-1; 0 完全透明 1 不透明
    1.里面的内容也会被模糊
    2.可以设置图片的模糊
    3.过渡效果对 display 的隐藏和出现没有效果,可以通过设置 opacity
    的值
    背景
    背景图的原点 background-origin
    1.padding-box 默认值背景图从 padding 区域开始显示
    2.content-box 背景图从 content 区域开始显示
    3.border-box 背景图从 border 边框区域开始显示
    背景图的裁切 background-clip
    1.border-box 边框之外裁切
    2.padding-box padding 之外裁切
    3.content-box 内容区开始裁切
    背景图大小的设置 background-size
    圆角 border-radius
    1.一个值四个角
    2.两个值对角
    3.三个值左上角右上角/左下角右下角
    4.四个值左上角右上角右下角左下角(顺时针的角度)
    5.正圆 border-radius: 50%/100%;
    图片边框 border-image
    1.border-image:图片路径偏移重复
    2.border-image-source:url() 图片的路径
    3.border-image-slice:数值图片的裁切不要加单位
    4.border-image-repeat:平铺(repeat) 铺满(round) 拉伸(stretch)默认
    过渡 transition:transition-property transition-duration transition-delay
    transition-timing-function(顺序不固定,当只有一个时间的时候,表示
    过渡时间,两个时间第一个表示过渡时间,第二个表示延迟时间)
    transition-property 需要过渡的属性
    transition-duration 过渡所需要的时间 s(秒)/ms(毫秒) 1s=1000ms
    transition-delay 过渡延迟时间 s(秒)/ms(毫秒)
    transition-timing-function 过渡效果
    1.linear: 匀速
    2.ease: 逐渐慢下来
    3.ease-in: 加速
    4.ease-out: 减速
    5.ease-in-out 先加速后减速
    动画 animation:animation
    使用:animation: 动画名动画持续时间延迟时间动画效果执行次数13
    animation-name: 动画名
    animation-duration: 动画的持续时间 s/ms
    animation-delay: 动画的延迟时间 s/ms
    animation-timing-function: 动画的效果
    animation-iteration-count: 具体的数值/infinite(无限循环)
    anmiation-direction: 动画执行的方向
    1.normal 正向
    2.reverse 反向
  3. alternate 正向和反向交替运动
    animation-play-state 动画是否播放
    1.running 播放默认值
    2.paused 暂停
    定义动画
    css
    @keyframes 动画名{ from{} ==>0% to{} ==>100%
    }
    关键帧分的是时间
    @keyframes 动画名{
    0%{ css 属性:css 属性值
    }
    10%{} 0.5s
    20%{} 1s
    30%{}
    100%{}
    }
    渐变
    线性渐变
    background-image/background:linear-gradient(方向,颜色 1,颜色 2……)
    渐变方向
    to bottom 向下
    to right 向右
    to top 向上
    to left 向左
    to right bottom 向右下角
    to left top 向左上角
    to right top 向右上角
    to left bottom 向左下角
    数值+deg(角度)
    设置百分比
    css
    /* 0%-40% 是红色的纯色 40%-60% 红色到蓝色渐变
    60%-100% ;蓝色的纯色*/14
    background: linear-gradient(red 40%, blue 60%);
    重复性的线性渐变
    background:repeating-linear-gradient(red 40%, blue 60%);
    径向渐变
    bakrgound-image/background:radial-gradient(位置,颜色 1,颜色 2)
    位置
    center 中心
    水平方向:left/center/right
    垂直方向:top/center/bottom
    兼容写法
    css background: radial-gradient(left, red, blue);
    background: -webkit-radial-gradient(left, red, blue); background: -
    ms-radial-gradient(left, red, blue);
    重复性的径向渐变
    background: repeating-radial-gradient(red 20%, yellow 40%);
6.清除浮动的方式有哪些?请说出各自的优点

• 额外标签法(在最后一个浮动标签后,新加一个标签,给其设置 clear: both)不
推荐
o 优点:通俗易懂,方便
o 缺点:添加无意义标签,语义化差
• 父级添加 overflow 属性(overflow:hidden)不推荐
o 优点:代码简洁
o 缺点:内容增多的时候容易造成不会自动换行导致内容被隐蔽掉,无法显示要溢
出的元素
• 给父级设置高度
o 优点:简单,代码少,容易掌握
o 缺点:只适合高度固定的布局,要给出精确的高度,如果高度和父级 div 不一
样时,会产生问题
• 父级 div 定义 overflow:auto(必须定义 width 或 zoom:1,同时不能定义 height,
使用 overflow:auto 时,浏览器会自动检查浮动区域的高度)
o 优点:简单,代码少,浏览器支持好
o 缺点:内部宽高超过父级 div 时,会出现滚动条。
• 使用 after 伪元素清除浮动(推荐使用)
.clear:after{
content:"";
display:block;
clear:both;
height:0;
overflow:hidden;
visibility:hidden
}15
o 优点:符合闭合浮动思想,结构语义化正确
o 缺点:ie6-7 不支持伪元素:after,使用 zoom:1 触发 hasLayout

7.定位的属性值有何区别

• static 默认值
• relative 相对定位,参考自己本身的位置,不会脱离文档流,文字不能被遮挡
• absolute 绝对定位,参考有定位属性(除了 static)的祖先元素,定位元素通过一层一层
向上找,找到有定位的祖先元素,如果找到 body 依然没有找到有定位的祖先元
素,参考浏览器窗口(子绝父相),脱离文档流,且文字能被遮挡,块级元素设置
margin:0 auto;会失效,内联元素设置定位转换成块元素
• fixed 固定定位,参考浏览器的窗口,不会跟随滚动条的滚动而滚动,脱离文档流,
宽度自适应的时候,宽度不显示,可以通过设置 width:100%
• 粘性定位 sticky,参考浏览器的窗口,没有达到 top 值之前正常显示,达到 top 值
之后类似于固定定位,不会跟随滚动条滚动而滚动
8.子元素如何在父元素中居中
• 定位+margin:auto 父元素 position: relative 子元素 position: absolute
left:0;top:0;right:0;bottom:0;margin: auto;
• 定位+margin-left+margin-top 父元素 position: relative 子元素 position:absolute
left:50%; top:50%; margin-left: -当前盒子宽度的一半; margin-top: -当前盒子高度的一
半;
• 定位+transfrom(子元素未知宽高)父元素 position: relative 子元素 position:
absolute left:50%; top:50%; transform: translate(-50%,-50%); • 弹性盒子父元素 display:
flex; justify-content: center; align-items: center;
• flex+margin: auto 父元素 display: flex; 子元素 margin:auto;

9.border-box 与 content-box 的区别

• border-box o padding 和 border 被包含在定义的 width 和 height 之内。
o 对象的实际宽度就等于设置的 width 值,即使定义有 border 和 padding 也不
会改变对象的实际宽度;即 ( Element width = width+ margin)
o 此属性表现为怪异模式下的盒模型
• content-box
o padding 和 border 不被包含在定义的 width 和 height 之内。
o 对象的实际宽度等于设置的 width 值和 border、padding 之和;即( Element
width = width + border + padding + margin)
o 此属性表现为标准模式下的盒模型

10.元素垂直居中

• 如果是图片,直接设置 img 的属性 vertical-align: middle;前提是需要设置父级元素
为块级元素并且设置高度
• 如果是单行文本,可以通过设置子元素的 line-height 值等于父元素的 height,这种
方法适用于子元素为单行文本的情况。16
• 通过定位父元素 position: relative 子元素 position: absolute top:50%; transform:
translateY(-50%);
• 通过伪元素:before 实现 CSS 垂直居中
父元素:before{
content:"";
display:inline-block;
vertical-align:middle;
height:100%;
}
• 通过 display:table 实现,给父元素设置 display:table,子元素 display: table-cell 的
方式实现 CSS 垂直居中
• 通过 display:flex 实现,给父元素设置 display:flex; 子元素 align-self:center

11.如何让 chrome 浏览器显示小于 12px 的文字

• webkit-transform:scale(0.833); 0.833 是缩放比例

12.Css 选择器有哪些,哪些属性可以继承,优先级如何计

Css3 新增的伪类有哪些
• css 选择器
o id 选择器( # myid)
o 类选择器(.myclassname)
o 标签选择器(div, h1, p)
o 相邻选择器(h1 + p)
o 子选择器(ul > li)
o 后代选择器(li a)
o 通配符选择器( * )
o 属性选择器(a[rel = “external”])
o 伪类选择器(a: hover, li: nth - child)
• 可以继承
o 字体类:

  1. font-family:字体类型;
  2. font-weight:字体加粗;
  3. font-size:字体大小
  4. font-style: 字体样式
  5. text-indent: 缩进(只对块级元素生效)
  6. text-align:对齐方式
  7. line-height:行高
  8. word-spacing:字之间的距离;
  9. letter-spacing:字符之间的距离;
    10.text-decoration:文本修饰
    o 文本类:
  1. color:颜色

o 列表:17

  1. list-style-type:列表类型
  2. list-style-image:图标路径
  3. list-style-position:图标的位置
  4. list-style:none;去掉列表符号
    • 优先级就近原则,样式定义最近者为准; 载入样式以最后载入的定位为准;
    • 优先级为: !important > id > class > tag(标签选择器) important 比内联优先级高
    • css3 新增的伪类
    o 结构性伪类选择器(child 系列)
  5. E:first-child E 必须是父元素里面的第一个孩子
  6. E:last-child E 必须是父元素里面的最后一个孩子
  7. E:nth-child(n) 不匹配前面的元素类型,如果对应的位置是该元素才匹配
  8. E:only-child 必须只有他自己一个孩子
    o 结构性的伪类选择(type 系列)
  1. E:first-of-type 匹配到该元素中的第一个孩子
  2. E:last-of-type 匹配到该元素的最后一个孩子
  3. E:nth-of-type(n) 匹配到该元素的第几个孩子 n 可以是表达式 2n 3n 2n+1
    even(偶数) odd(奇数)
  4. E:nth-last-of-type(n) 匹配到该元素的倒数第几个

o 目标伪类:结合锚点使用
o 状态伪类选择器

  1. :enabled 元素可编辑
  2. :disabled 元素不可编辑
  3. :checked 选中
  4. ::selection 高亮状态一般修改字体颜色和背景色
    o 动态伪类选择器
  5. :link 未访问前
  6. :visited 访问过后
  7. :hover 鼠标滑过
  8. :active 鼠标点击之后
13.网页中有大量图片加载很慢你有什么办法进行优化?

• 图片懒加载,在页面上的未可视区域可以添加一个滚动条事件,判断图片位置与浏
览器顶端的距离与页面的距离,如果前者小于后者,优先加载
• 如果为幻灯片、相册等,可以使用图片预加载技术,将当前展示图片的前一张和后
一张优先下载
• 如果图片为 css 图片,可以使用 CSSsprite(精灵图),SVGsprite(精灵图),
Iconfont(字体图标)(精灵图,小图标…)
• 如果图片过大,可以使用特殊编码的图片,加载时会先加载一张压缩的特别厉害的
缩略图,以提高用户体验
• 如果图片展示区域小于图片的真实大小,则应该在服务器端根据业务需要先行进行
图片压缩,图片压缩后大小与展示一致18

14.行内元素/块级元素有哪些?

• 行内元素在同一行显示,不可以设置宽高,宽高由内容撑开,padding、margin 左
右显示准确,上下显示不准确,margin:0 auto,不生效,可以给内联元素添加一个外
层的盒子形成一个大的区域,给该盒子设置 text-align:center 的居中属性,添加浮动
可以解决内联元素之间的间歇,也能将内联元素的元素类型转换为块元素,例如
span b strong i em a u del img
• 块级元素可以设置宽高,盒模型属性都生效,独占一行,一般作为容器,例如:ES6
新增的 header footer section 等以及常用的 div p ul li h1-h6 ol dl dt dd
15.浏览器的标准模式和怪异模式
• 盒模型:
o 在怪异模式下,盒模型为 IE 模型。盒子所占区域宽度=width(宽)+margin(左
右),高度等同
o 在标准模式下,盒模型为 W3C 模型。盒子所占区域宽=width(宽)+padding(左
右)+border(左右)+margin(左右),高度等同
• 行内元素的垂直对齐方式:标准模式下 vertical-align 属性默认取值是 baseline;怪
异模式下 vertical-align 属性默认取值是 bottom。
• 字体样式:标准模式下,表格中的字体样式会被继承;怪异模式下,表格中的字体
样式不会被继承。
• 元素溢出的处理:标准模式下,overflow 取值默认为 visible;怪异模式下,当内容
超出容器高度时,会把容器拉伸。
• !important:标准模式下,IE7+认识!important 声明;怪异模式下,IE6/7/8 都不认
识!important 声明。
• 行内元素的宽高:标准模式下,给行内元素设置 wdith 和 height 都不会生效;怪
异模式下会生效。
• 水平居中:使用 margin:0 auto 在标准模式下可以使元素水平居中,但在怪异模式下
却会失效。
• 怪异模式下,颜色值必须用十六进制标记法。

16.margin 和 padding 在什么场合下使用

• margin:用来调整盒子到盒子之间的距离,不会撑大显示的区域,但是会影响到别
的盒子
o 使用场景:需要在 border 外侧添加空白时;空白处不需要背景(色)时;上下
相连的两个盒子之间的空白,需要相互抵消时;
• padding:用来调整子元素(内容)在父元素(盒子)内的位置,会把盒子撑大,如
果不想被撑大,要在原来宽高的基础上减去对应方向的 padding 值
o 使用场景:需要在 border 内测添加空白时;空白处需要背景(色)时;上下相
连的两个盒子之间的空白,希望等于两者之和时;

17.弹性盒子布局属性有哪些请简述

• 父元素:
o 主轴方向 flex-direction

  1. row 主轴从左向右默认值19
  2. row
    -revese 主轴从右向左
  3. column 主轴从上到下
  4. column
    -reverse 主轴从下到上
    o 主轴方向排列方式 justify
    -content
  5. flex
    -start 主轴起点默认值
  6. flex
    -end 主轴终点
  7. center 居中
  8. space
    -between 两端对齐
  9. space
    -around 中间的留白是两边的 2
  10. space
    -evenly 平均分配留白
    o 交叉轴排列方式 align
    -items
  11. stretch 拉伸默认值去掉子元素的高度
  12. flex
    -start 交叉轴的起点
  13. flex
    -end 交叉轴的终点
  14. center 居中
    o 换行 flex
    -wrap
    1 .nowrap 不换行,默认值,会将子元素压缩 2 .wrap 换行
  15. wrap
    -reverse 反向换行
    o 多行之间的排列方式 align
    -content
  16. stretch 拉伸默认值需要去掉子元素的高
  17. flex
    -start 主轴起点依次排列
  18. flex
    -end 主轴终点依次排列
  19. center 居中
  20. space
    -between 两端对齐
  21. space
    -around 中间的两端的 2
  22. space
    -evenly 平均分配
    • 子元素: o 重写子项对应的交叉轴的对齐方式 align
    -self
    1 .stretch 拉伸默认值去掉子元素的高度
  23. flex
    -start 交叉轴的起点
  24. flex
    -end 交叉轴的终点
  25. center 居中
  26. 放大 flex
    -grow
  27. 0 不放大 7. 数值填充剩余的空间
    o 压缩 flex
    -shrink
  28. 1 压缩
  29. 0 不压缩
  30. 实现导航的滚动效果 a. 子项的宽度超出了父容器的宽度 b. 设置子项不压缩 flex-shrink:0; c. 父元素设置溢出显示滚动条 overflow
    -x:auto;
    o 子项的宽度 flex
    -basis:数值+px 类似于宽度20
    o 排序 order 数值值越大越向后,可以设置负数
    18.怎么实现标签的禁用
    style=“pointer-events: none”
    19.flex 布局原理
    • flex 是 flexible Box 的缩写,意为“弹性布局”,用来为盒状模型提供最大的灵活性,
    任何一个容器都可以指定为 flex 布局。当为父盒子设置为 flex 布局之后,子元素的
    float、clear、vertical-align 属性将失效。
    • 采用 flex 布局的元素,称为 flex 容器(flex container),简称“容器”。他的所有子元
    素自动成为容器成员,称为 flex 项目(flex item),简称“项目”。
    • 总结:flex 布局就是通过给父盒子添加 flex 属性,来控制子盒子的位置和排列方
    式。
    20.px 与 rem 的区别
    • px:px 实际上就是像素,用 px 设置字体大小时,比较稳定和精确
    o px 像素(Pixel),相对长度单位。像素 px 是相对于显示器屏幕分辨率而言的。
    • em:em 就是根据基准来缩放字体的大小 em 的值并不是固定的;em 会根据父级
    元素的字体大小变化
    o em 是相对长度单位。相对于当前对象内文本的字体尺寸。如当前对行内文本的
    字体尺寸未被人为设置,则相对于浏览器的默认字体尺寸。
    • rem: rem 是根据根元素 字体大小变化,这样就意味着,我们只需要在根
    元素确定一个参考值。一般情况下将根元素的字体大小设置为 html{font-size:100px}
    rem 是 CSS3 新增的一个相对单位(root em,根 em),这个单位引起了广泛关
    注。
    21.网页的三层结构有哪些
    • 网页的结构层:
    o 由 HTML 或 XHTML 之类的标记语言负责创建。标签,也就是那些出现在尖括
    号里的单词,对网页内容的语义含义做出了描述,但这些标签不包含任何关于如
    何显示有关内容的信息。例如,P 标签表达了这样一种语义:“这是一个文本
    段。”
    • 网页的样式层:
    o 该层指示结构化 HTML 文档如何看待网站的访问者,并由 CSS(层叠样式表)
    定义。这些文件包含有关如何在 Web 浏览器中显示文档的样式说明。样式层通
    常包括基于屏幕大小和设备更改站点显示的媒体查询。网站的所有视觉样式都应
    位于外部样式表中
    • 网页的行为层:
    o 行为层使网站具有交互性,允许页面响应用户操作或基于一组条件进行更改。
    JavaScript 是行为层最常用的语言,但 CGI 和 PHP 也经常被使用。当开发人
    员引用行为层时,大多数都是指在 Web 浏览器中直接激活的层。21
    22.请简述媒体查询
    • 媒体指的就是各种设备 (移动设备, PC 设备),查询指的是要检测属于哪种设备,媒
    体查询就是通过查询当前属于哪种设备, 让网页能够在不同的设备下正常的预览
    • 语法 @media 关键字设备类型 and (媒体特性){}
    • 关键字:all(所有的设备类型)/only(限定某种设备)/not(排除设备)
    • 设备类型:
    o all(所有的设备)
    o screen 显示器移动设备笔记本
    o print 打印设备
    • 媒体类型
    o 最小宽度 min-width 大于最小宽度
    o 最大宽度 max-width 小于最大宽度
    • 书写说明
    o and 两侧必须有空格
    o 媒体特性属性值后面不要加分号
    o 多个媒体特性之间用 and 连接

• viewport 视口

o 视口 viewport

  1. 布局视口,默认情况下,布局视口的宽是 980px,设置 css 样式的样式是
    作用在布局视口
  2. 可视视口设备的宽度 device-width
  3. 完美/理想视口 width=device-width 布局视口和设备宽度一样
    o initial-scale 初始缩放比例默认值 1
    o minimum-scale 最小缩放比例默认值 1
    o maximum-scale 最大缩放比例默认值 1
    o user-scalable 用户是否可以手动缩放 no/0 不缩放
23.rem 缺点

• 有局限性,IE8 及以下版本不支持
• 对 pc 页面来讲使用次数不多
• 数据量大:所有的图片、盒子都需要给一个准确的值,才能保证不同机型的适配;

24.常见的兼容性一阶段内容中记几个

• 在 ie 浏览器中,a 标签套图片会自带边框 ie10 及以下
o 解决:去掉边框 img{border:none}
• 图片自带底部 3px 的留白22
o 解决:
vertical-align: bottom/middle/top 给图片添加
display:block; 给图片添加
font-size:0; 给父元素添加
• 表单元素对齐不一致
o 解决:
设置怪异盒模型
设置浮动
• 透明度 opacity 在 ie 浏览器中不支持 0-1
o 解决:
opacity 的值照常设置,适应正常的浏览器
单独设置 ie 中透明属性:filter:alpha(opacity=value);取值范围 value:
1-100(整数)1 完全透明 100 不透明

25.垂直与水平居中的方式

• 水平居中:
o 行内元素:为该行级元素的父元素设置 text-align:center 样式
o 块级元素:为其自身设置 margin:auto 样式
• 垂直居中:
o 行内元素:line-height: 父元素的高度
o 块级元素:

  1. 父元素 position:relative;子元素: position:absolute;top:50%;left:50%;
    transform:translate(-50%,-50%);
  2. 父元素: display:flex;justify-content: center; align-items:center;
26.三栏布局方式两边固定中间自适应

• 绝对定位法:将左右两边使用绝对定位,绝对定位使其脱离文档流,后面的 center
会自然流动到他们上面,然后使用 margin 属性,留出左右元素的宽度,就可以使
中间元素自适应屏幕宽度。
• 自身浮动法:对左右分别使用 float:left 和 float:right,浮动使左右两个元素脱离文
档流,中间元素正常在文档流中,使用 margin 指定左右外边距对其进行一个定
位。
• margin 负值法:左右两栏均左浮动,左右两栏采用负的 margin 值。中间栏被宽度
为 100%的浮动元素包起来。

27.doctype 作用

• 声明叫做文件类型定义(DTD),作用是为了告诉浏览器该文件的类型。让浏览器解析器
知道应该用哪个规范来解析文档。

28.常见的浏览器内核有哪些

• ie 浏览器:Trident
• 火狐:Gecko 代码开源
• 苹果 & 谷歌旧版本: Webkit
• 谷歌 & 欧鹏: Blink23

29.link 和 import 的区别

• 老祖宗的差别:link 属于 HTML 提供的引用方式,@import 是 css 提供的引用方
式,link 还可以引入其他文件类型,@import 只能引入 css 文件
o
o @import url(“图标路径”); 不可以引入
• 加载顺序的区别:link 和 HTML 是同时加载的,@import 是当所有 html 文件加载
后再去加载 css 文件,所以有时候浏览@import 加载 CSS 的页面时开始会没有样

• 兼容性 @import 只有 ie5 以上才支持

30.BFC(块级格式化上下文)触发条件

• float:值为 left/right
• position 的值为 absolute 和 fixed
• display 为 inline-block(内联块), table-cell(单元格), table-caption(表格标
题), flex(弹性盒), inline-flex(弹性盒)
• overflow 的值为 hidden/scroll/auto

31.css 实现边框三角形

div {
height: 0; border-top: 20px solid pink;
border-right: 20px solid transparent;
border-bottom: 20px solid transparent;
border-left: 20px solid transparent; /透明/
width: 0;
}

JavaScript

1.Js 基本数据类型有哪些

• 数值类型(number)包含数字
• 字符串类型(string)由单双引号包住的字符串内容会原样输出
• 布尔类型(boolean)只会输出 true ,false
• undefined 数值定义但未初始化
• null 空
• Symbol 表示独一无二的值(ES6 新增)

2.Ajax 如何使用

btn.onclick = function(){
// 1. 实例化一个 XMLHttpRequest 对象
let http = new XMLHttpRequest();
// 2. 规划一个请求(三要素)
// 2.1 请求方式 GET || POST
// 2.2 请求地址
// 2.3 同步还是异步可选的参数,如果省略就是异步的请求
http.open(“GET”,“http://10.35.170.103/data.php”);
//带有一个请求参数的请求
http.open(“GET”,http://10.35.170.103/data.php?age=${age.value}&sex=${sex.value});
// 3. 真实的发送请求
http.send();
// 4. 接收来自服务器端的响应
http.onreadystatechange = function(){
//服务器端已将返回的内容交付给客户端手里了
if(http.readyState === 4){ console.log(http.responseText);
}}}
• 创建 XMLHttpRequest 对象
o 浏览器使用 XMLHttpRequest 对象与服务器进行交互,获取数据。一般现在流
行的浏览器均支持 XMLHttpRequest 对象(IE5 和 IE6 使用 ActiveXObject)。
o 语法:
var xml=new XMLHttpRequest();
老版本的 IE 浏览器的创建方式为:var xml=new
ActiveXObject(“Microsoft.XMLHTTP”);
var xml;
if (window.XMLHttpRequest) {
xml=new XMLHttpRequest();
}else{
xml=new ActiveXObject(“Microsoft.XMLHTTP”);
}
• 向服务器发送请求25
o get 方式提交使用 XMLHttpRequest 对象的 open()方法向服务器发送请求
语法:
open(请求方式,请求地址(get 发送的数据拼接在 url 后面),true(异
步))
xml.open(“get”,“index.json”,true);
xmlH.send();// get 请求 send 保持为空
o post 方式提交 使用 XMLHttpRequest 对象的 open()与 send() 方法向服务器发
送请求
语法:
open(请求方式,请求地址,true(异步))
send()
xml.open(“post”,“index.json”,true);
//如果想要使用 post 提交数据,必须添加此行
xhr.setRequestHeader(“Content-type”,
“application/x-www-form-urlencoded”);
通过 send 方法传递 //将数据
xhr.send(‘name=fox&age=18’);
• onreadystatechange 事件
o 当向服务器发送请求时 redyState 的值发生改变时触发 onreadystatechange
事件。
o readyState 存有 XMLHttpRequest 的状态。从 0 到 4 发生变化。
0: 请求未初始化
1: 服务器连接已建立
2: 请求已接收
3: 请求处理中
4: 请求已完成,且响应已就绪
o status 有两种数值,分别表示: 200: “OK” 404: 未找到页面
xml.onreadystatechange(function(){
if(xmlHttp.readyState4&&xmlHttp.status200){
console.log(xhr.responseText);
}}

3.如何判断一个数据是 NaN

• NaN 不是一个数字且数据类型为 number,而且不等于自身
o 可直接采用内置方法 isNaN
function isNaN(n) {
if (n !== n) {
return true;
} else {
return false;
}}
• 利用 NaN 是唯一一个不等于任何自身的特点
var a=NaN;
a==a; //false26
• object.is 方法
console.log(Object.is(“a”, NaN));
console.log(Object.is(1, NaN));
console.log(Object.is(NaN, NaN));

4.Js 中 null 与 undefined 区别

• 相同点:if 判断语句中,两者都会被转换为 false
• 不同点:
o Number 转换的值不同,Number(null)输出为 0, Number(undefined) 输出为
NaN o null 表示一个值被定义了,但是这个值是空值
o undefined 表示缺少值,即此处应该有值,但是还没有定义

5.闭包是什么有什么特性,对页面会有什么影响

• 闭包可以简单理解成“定义在一个函数内部的函数“。当其中一个内部函数在包含它们
的外部函数之外被调用时,就会形成闭包。
let fn = (function(){
//局部变量
var count = 0;
return function(){
return ++count;
}})()
• 本质:外层函数嵌套一个内层函数,内层函数作为外层函数的 return 语句的返回
值。外层函数是自调用函数,并且将自身的返回值(也就是内层函数本身)赋给一
个变量。在 JS 执行环境上下文中调用该变量就等价于调用了内层函数,并且在内层
函数中可以访问到外层函数的局部变量又并且外层函数的局部变量不会被多次声
明,此时就形成了一种闭包的写法。
• 特点:
o 函数嵌套函数。
o 函数内部可以引用外部的参数和变量。
o 参数和变量不会被垃圾回收机制回收。
• 用处:
o 常驻内存会增大内存的使用量;
o 读取函数内部的变量;
o 这些变量的值始终保持在内存中,不会在外层函数调用后被自动清除。
• 优点:
o 变量长期驻扎在内存中;
o 避免全局变量的污染;
o 私有成员的存在;
• 缺点:会造成内存泄露

6.事件委托是什么?如何确定事件源

• 事件委托还有一个名字叫事件代理,JS 高程上讲:事件委托就是利用事件冒泡,只
制定一个时间处理程序,就可以管理某一类型的所有事件。27
• 将子元素的事情委托给它们的祖先级元素来干,然后使用 event.target(低版本 IE 用
的是 event.srcElement)来代替已经混乱 this 关键字
o 解决动态元素(刚进入页面时,元素不在页面内)无法绑定事件问题
o 在极端情况下可以提升客户端性能

7.本地存储与 cookie 的区别

• Cookie 是小甜饼的意思。顾名思义,cookie 确实非常小,它的大小限制为 4KB 左
右。它的主要用途有保存登录信息,比如你登录某个网站市场可以看到“记住密码”,
这通常就是通过在 Cookie 中存入一段辨别用户身份的数据来实现的。
• localStorage 是 HTML5 标准中新加入的技术,它并不是什么划时代的新东西。早在
IE 6 时代,就有一个叫 userData 的东西用于本地存储,而当时考虑到浏览器兼容
性,更通用的方案是使用 Flash。而如今, localStorage 被大多数浏览器所支持,如
果你的网站需要支持 IE6+,那以 userData 作为你方案是种不错的选择。
• sessionStorage 与 localStorage 的接口类似,但保存数据的生命周期与
localStorage 不同。做过后端开发的同学应该知道 Session 这个词的意思,直译过来
是“会话”。而 sessionStorage 是一个前端的概念,它只是可以将一部分数据在当前
会话中保存下来,刷新页面数据依旧存在。但当页面关闭后,sessionStorage 中的数
据就会被清空。
• cookie:兼容性很好,可以灵活的设置数据的生命周期,缺点是操作不方便,需要大
量的字符串处理
• localStorage:IE67 不认识,永久性存储,只要用户不删除或调用 clear 方法就永远
不会删,操作很方便
• sessionStorage:兼容性与 localStorage 一样,但是存储时间是会话(在当前标签页
无论跳转到该网站的哪一个页面都能获取到,但关闭浏览器就会销毁,并且在其他
标签页面中是获取不到的)
• 三者的异同

特性CookielocalStoragesessionStorage
数据的生命周期一般由服务器生成,可设置失效时间。如果在浏览器端生成 Cookie除非被清除,否则永久保存默认认是关闭浏览器后失效,关闭页面或浏览器后被清除
存放数据大小4K 左右一般为 5MB同左
与服务器端通信每次都会携带在 HTTP 头中,如果使用 cookie 保存过多数据会带来性能问题仅在客户端(即浏览器)中保存,不参与和服务器的通信同左
易用性需要程序员自己封装,原生的 Cookie 接口不友好源生接口可以接受,亦可 再 次 封 装 来 对Object 和 Array 有更好的支持同左
8.ES6 新特性

• const 和 let • 模板字符串
• 箭头函数
• 函数的参数默认值
• 对象和数组解构
• for…of 和 for…in
• ES6 中的类

9.Let 与 var 与 const 的区别

• var 声明的变量会挂载在 window 上,而 let 和 const 声明的变量不会;
• var 声明变量存在变量提升,let 和 const 不存在变量提升;
• let 和 const 声明变量都没有函数作用域的概念,而是遵守块级作用域的概念;
• 同一作用域下 let 和 const 不能声明同名变量,而 var 可以;
• let 有暂存死区(在声明之前就使用变量,就会报错,这就是暂时性死区)
• let 和 const 关键字:let 和 const 声明变量都没有函数作用域的概念,而是遵守块
级作用域的概念,并且没有变量提升的操作,不能重复声明。const 是声明常量版的
let,let 有暂时性死区的特性。

10.数组方法有哪些请简述

• push(新值) 向数组的尾端插入一个新的元素
• unshift(新值) 向数组的前端插入一个新的元素
• pop() 删掉数组中最后一个元素
• shift() 删掉数组中第一个元素
• splice(删除的下标,1) 从某一个下标上删除一个元素,有副作用
• splice(要插入的下标,0,要插入的数据) 从中间插入一个元素
• concat() 拼接数组,返回值为合并成的新数组,原数组不会改变
• join() 将数组转换为字符串,参数为分隔符,原数组不会改变
• reverse() 颠倒数组中元素的顺序,会改变原数组
• slice(start,end) 通过开始下标和结束下标截取数组元素,原数组不会发生改变
• toString() 将数组转换为字符串可以被 join 完美代替
• sort() 通过 Unicode 进行排序,在原数组上排序,不生成副本
var arr = [1, 5, 6, 1, 3, 4, 11, 2, 5]
//排序固定写法升序
arr.sort(function(num1, num2) { return num1 - num2;}) console.log(arr);
//排序固定写法降序
arr.sort(function(num1, num2) { return num2 - num1;}) console.log(arr);
• arr.forEach(callback) 遍历数组,无 return 即使有 return,也不会返回任何值,并且会
影响原来的数组
• arr.map(callback) 映射数组(遍历数组),有 return 返回一个新数组。
• arr.filter(callback) 过滤数组,返回一个满足要求的数组30

11.Json 如何新增/删除键值对

• JSON 是什么: JSON (JavaScript Object Notation, JS 对象标记) 是一种轻量级的数
据交换格式。
• JSON 规则:
o 1.必须是字符
o 2.基础格式参考 js 中的对象(array 和 object)
o 3.对象格式的 key 部分必须放在双引号中,单引号不行
o 4.不允许出现没有意义的逗号
o 5.不能出现 undefined、NaN,可以出现 null
o 6.不能出现单引号
• 字符串转 JSON(正解析): Var obj = JSON.parse(JSON 格式的字符串)
• JSON 转字符串(反解析): Var str = JSON.stringify(对象)
• 删除: delete json 对象[“属性名”];
• 增加: json 对象[“属性名”]=属性值例如:myObject[age]=10;//即可添加上 age 属

12.什么是面向对象请简述

• 面向对象就是将问题抽象成若干 object 对象,然后去对这些对象编程,将对象的属
性和操作封装到类中,让它们具有一定的功能。具有抽象性、封装性、继承性、多
态性的特点。类是具有相同或相似性质的对象的抽象。因此,对象的抽象是类,类
的具体化就是对象,也可以说类的实例是对象。
• 面向对象是把构成问题的的事物分解成各个对象,建立对象不是为了完成一个步
骤,而是为了描述某个事物在整个解决问题的过程中的行为。
• 优点:易维护、复用、扩展
• 缺点:性能低:因为在创建类的实例需要很大的开销。

13.普通函数和构造函数的区别

• 返回值类型的区别:
o 构造函数是没有返回值类型的
o 普通函数是有返回值类型的,即使函数没有返回值,返回值类型也要写上
void。
• 函数名的区别:
o 构造函数的函数名必须要与类名一致,习惯首字母大写
o 普通函数的函数名只要符合标识符的命名规则即可。
• 调用方式的区别:
o 构造函数是在创建对象的时候由 new 关键字调用的
o 普通函数是由我们使用对象调用的,一个对象可以调用多次普通函数
• 作用上的区别:
o 构造函数用于初始化一个对象。
o 普通函数是用于描述一类事物的公共行为。31

14.请简述原型/原型链/继承

• 原型:每一个构造函数都有一个 prototype 属性,这个属性会在生成实例的时候,
成为实例对象的原型对象。javascript 的每个对象都继承另一个对象,后者称为“原
型”(prototype)对象。
• 原型链:每一个对象都有一个 proto 属性,对象的属性和方法,有可能定义在自
身,也有可能定义在它的原型对象。由于原型本身也是对象,又有自己的原型,所
以形成了一条原型链(prototype chain)。(“原型链” 的作用是:读取对象的某个属
性时,JavaScript 引擎先寻找对象本身的属性,如果找不到,就到它的原型去找,如
果还是找不到,就到原型的原型去找。如果直到最顶层的 Object.prototype 还是找
不到,则返回 undefined。举例来说,如果让某个函数的 prototype 属性指向一个数
组,就意味着该函数可以当作数组的构造函数,因为它生成的实例对象都可以通过
prototype 属性调用数组方法。)
• 继承:继承就是在子类构造函数中继承父类构造函数的私有属性和原型属性。我们
在子类构造函数中使用 call 或 apply 方法调用父类构造函数并改变其 this 指向为
子类构造函数的 this,此时子类的构造函数就继承了父类的私有属性和私有方法。
将父类的实例化对象赋值给子类的原型对象,此时子类就继承了父类的原型属性和
原型方法。

15.Promise 的理解

• Promise 是一种异步操作的解决方案,将写法复杂的传统的回调函数和监听事件的异
步操作,用同步代码的形式表达出来。避免了多级异步操作的回调函数嵌套。
o 主要用于异步计算
o 可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果
o 可以在对象之间传递和操作 promise,帮助我们处理队列
• Promise 是一个对象,它的内部其实有三种状态。
o 初始状态( pending )。
o 已完成( resolve):resolve 方法可以使 Promise 对象的状态改变成成功
o 已拒绝( reject ):reject 方法则是将 Promise 对象的状态改变为失败
• Promise 常用的三种方法
o 第一种:then 表示异步成功执行后的数据状态变为 resolve
o 第二种:catch 表示异步失败后执行的数据状态变为 reject
o 第三种:all 表示把多个没有关系的 Promise 封装成一个 Promise 对象使用
then 返回一个数组数据。
• Promise 构造函数有两个变量 resolve 用于返回异步执行成功的函数 reject 用于返
回异步执行失败的函数,配合 then 与 catch 一起使用

16.Promise 在哪里使用过

• Ajax 异步请求的时候
• 函数嵌套层级多的时候使用 promise,优点在于,回调函数变成了链式写法,程序的
流程可以看得很清楚,而且有一整套的配套方法,可以实现许多强大的功能。32

17.请简述 async 的用法

• async 用于声明一个 function 是异步的,而 await 用于等待一个异步方法执行完
成,async 返回的是一个 Promise 对象。
• async 的主要作用是回调地狱的处理看起来比 promise 更美观,而且使用 async 来
传参的时候比较方便。
• async 函数必须要等到方法体中所有的 await 声明 Promise 函数执行完后, async
函数才会得到一个 resolve 状态的 Promise 对象。
• async/await 在遇到异步请求的情况下,能让代码以看似同步的方式来解决异步回调
• 使用步骤:
o 定义一个需要进行异步等待的方法,并在方法前加"async"关键字
o 在这个内部有异步请求的方法中用 await 等待相应的请求完成。
o 在这个异步请求的方法中返回一个 Promise 对象,并封装 resolve 和 reject 方

18.jQuery 相关的知识

• jQuery:类库(工具箱):宗旨是 write less do more,功能:DOM 操作,DOM 获取,动画,数据交互(ajax),链式调用
• jQuery 对象到底是啥? 是一个类数组。所有数组成员都是原生 JS 节点。jQuery 和原生 js 节点的属性和方法互不通用。是一个兼容多浏览器的 javascript 库(函数库),核心理念是 write less,do more(写的更少,做的更多)。
• 特点:是一个快速的简洁的 javascript 框架,可以简化查询 DOM 对象、处理时间、制作动画、处理 Ajax 交互过程
o 提供了强大的功能函数
o 解决浏览器兼容性问题
o 纠正错误的脚本知识
o 体积小,使用灵巧(只需引入一个 js 文件)
o 易扩展、插件丰富
• 作用:
o 程序员角度:简化 Javascript 和 Ajax 编程,能够使程序员从设计和书写繁杂的
JS 应用中解脱出来,将关注点转向功能需求而非实现细节上,从而提高项目的
开发速度。
o 用户体验角度:改善了页面视觉效果,增强了与页面的交互性,体验更绚丽的
网 页物资方便地选择页面元素(模仿 CSS 选择器更精确、灵活) 动态更改页面
样式/页面内容(操作 DOM,动态添加、移除样式) 控制响应事件(动态添加响应
事件) 提供基本网页特效(提供已封装的网页特效方法) 快速实现通信(ajax)。
o jQuery 获取方式: jQuery 库文件不需要安装,只需使用

19.Css 预处理 sass less 是什么?为什么使用他们

• 首先 Sass 和 Less 都是 CSS 预处理器,是 CSS 上的一种抽象层,是一种特殊的语
法/语言最终会编译成 CSS。less 是一种动态样式语言,将 CSS 赋予了动态语言的
特性,如变量,继承,运算,函数。less 既可以在客户端上运行 (支持 IE 6+,
Webkit, Firefox) 也可以在服务端运行(需要借助 Node.js)。
• 为什么使用:
o 结构清晰,便于扩展
o 可以方便地屏蔽浏览器私有语法差异
o 减少无意义的机械劳动 - 可以轻松实现多重继承
o 完全兼容 CSS 代码,可以方便地应用到老项目中

20.Js 中.call()与.apply()区别

每一个函数都有 call 和 apply 方法,都是帮助我们调用函数的,但是在调用的时候
可以改变本次执行函数中的 this 指向。他们的不同点就在于 call 是无限多个参数,
而 apply 有两个参数,第二个参数是数组,代表实参集合。一般来说我们也就是在
用 JS 实现面向对象的继承特点时会使用到这个方法。

21.为什么会造成跨域/请简述同源策略

• 造成跨域的原因:
因为浏览器的同源政策,协议、端口和域名有任意一个不同就会造成跨域。比如说
发送的异步请求是不同的两个源,就比如是不同的的两个端口或者不同的两个协议
或者不同的域名。
• 同源策略:
同源策略就是浏览器保护浏览器安全的一种机制,它不允许客户端请求从 A 服务器
请求过来的页面往 B 服务器去发送 Ajax 请求。两个页面地址中的协议、域名和端
口号一致,则表示同源。
• 同源策略的数据
o 存储在浏览器中的数据,如 localStroage、Cookie 和 IndexedDB 不能通过脚本
跨域访问
o 不能通过脚本操作不同域下的 DOM
o 不能通过 ajax 请求不同域的数据

22.This 指向

• 出现在一般函数中或者是全局作用域下,this 指向的 window 对象
• 出现在事件处理函数(事件句柄)中,this 指向的是触发事件的元素
• 出现在对象的方法中,指向该对象
• 出现在构造函数中,指向的是实例化对象

23.请说出三种减少页面加载时间的方式

• 优化图片
• 图像格式的选择(GIF:提供的颜色较少,可用在一些对颜色要求不高的地方)
• 优化 CSS(压缩合并 css,如 margin-top,margin-left…) 34
• 网址后加斜杠(如 www.campr.com/目录,会判断这个“目录是什么文件类型,或者
是目录。)
• 标明高度和宽度(如果浏览器没有找到这两个参数,它需要一边下载图片一边计算
大小,如果图片很多,浏览器需要不断地调整页面。这不但影响速度,也影响浏览
体验。当浏览器知道了高度和宽度参数后,即使图片暂时无法显示,页面上也会腾
出图片的空位,然后继续加载后面的内容。从而加载时间快了,浏览体验也更好
了。)
• 减少 http 请求(合并文件,合并图片)。

24.什么是 jsonp,工作原理是什么?他为什么不是真正的 ajax

• JSONP:是一种解决跨域限制问题的一种方式
• 工作原理:前端使用一个 script 标签来创建一个 HTTP 请求,并且事先声明一个回
调函数,该回调函数的名字由 callback 参数的参数值发送给后端。后端接收到来自
前端的请求后利用 callback 参数的参数值和要给前端返回的数据拼接成一段 JS 执
行函数的代码段,此时实参就是要返回给前端的数据。前端接收到后端返回的结果
后,会自动的执行事先声明好的回调函数,此时函数的形参就代表了后端要返回的
数据。
• 为什么不是真正的 ajax:JSONP(JSON with padding)可用于解决主浏览器的跨域
数据访问的问题,与 JSON 没有关系,只是一种跨域访问的技巧。 ajax 的核心是
通过 xmlHttpRequest 获取非本页内容,jsonp 的核心是动态添加 script 标签调用
服务器提供的 js 脚本;jsonp 只支持 get 请求,ajax 支持 get 和 post 请求。

25.请掌握 2 种以上数组去重的方式
• 穷举法:
function norepeat(arr){ 
	var result=[]; //新数组
	for(var i=0;i<arr.length;i++) { 
		var isRepeat=false; //没有重复
		for (var j=0;j<=result.length;j++){ 
			if(arr[i]===result[j]){ 
			isRepeat=true; 
}} 
• 数组下标判断法
var arr = [2,5,8,2,8,6,4] 
var newArr = []; 
for(var i=0;i<arr.length;i++){ 
	if(arr.indexOf(arr[i]) === i){ 
	newArr.push(arr[i]) 
} } 
Console.log(newArr) 
let arr = Array.from(new Set(arr)); 
•利用 SET 数据结构(set 数据结构不允许有重复数据)
26.深浅拷贝是什么,如何实现?

• 浅拷贝是什么:
拷贝就是增加了一个指针指向已存在的内存(JavaScript 并没有指针的概念,这里只
是用于辅助说明),浅拷贝只是拷贝了内存地址,子类的属性指向的是父类属性的内
存地址,当子类的属性修改后,父类的属性也随之被修改。
• 深拷贝是什么:深拷贝就是增加一个指针,并申请一个新的内存,并且让这个新增加
的指针指向这个新的内存地址使用深拷贝,在释放内存的时候就不会像浅拷贝一样出
现释放同一段内存的错误,当我们需要复制原对象但又不能修改原对象的时候,深拷
贝就是一个,也是唯一的选择。
• 如何实现:重新创建一个数组空间,将另一个空间中的元素循环复制到新空间中,这
实际是两个独立的空间,对一个空间中的元素进行操作,另一个空间中的元素不会受
到影响。
• 浅拷贝:通过展开运算符…来实现浅拷贝

let a ={age: 1 } 
let b = { ...a } 
a.age = 2 
console.log(b.age) 
• 深拷贝
1. 可以通过 JSON.parse(JSON.stringify(object))来解决。
let a = { age: 1, }
jobs: { 
first: 'FE' 
} 
let b = JSON.parse(JSON.stringify(a)) 
  1. 如果你所需拷贝的对象含有内置类型并且不包含函数,可以使用MessageChannel
function structuralClone(obj) { 
return new Promise(resolve => { 
const { port1, port2 } = new MessageChannel() port2.onmessage = ev => 
resolve(ev.data)
port1.postMessage(obj) }) }
var obj = {
	a: 1, b: {
		c: 2
	}
obj.b.d = obj.b
// 注意该方法是异步的
// 可以处理 undefined 和循环引用对象
const test = async () => { const clone = await structuralClone(obj) 
console.log(clone)
} 
test()
  1. 使用 lodash 的深拷贝函数
function deepClone(obj) { function isObject(o) { return (typeof o === 'object' || 
typeof o === 'function') && o !== null36
}
if (!isObject(obj)) {
throw new Error('非对象')
}
let isArray = Array.isArray(obj) let newObj = isArray ? [...obj] : { ...obj }
Reflect.ownKeys(newObj).forEach(key => {
newObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key]
})
return newObj
}
let obj = { a: [1, 2, 3], b: { c: 2, d: 3
}}
let newObj = deepClone(obj) 
newObj.b.c = 1 
console.log(obj.b.c) // 2
27.为什么 js 是弱类型语言

弱类型语言是相对强类型语言来说的,在强类型语言中,变量类型有多种,例如 int
char float boolean 等,不同的类型相互转换有时需要强制转换,而 javascript 只有
一种类型 var ,为变量赋值时会自动判断类型并进行转换,所以 javascript 是弱语
言,就体现在变量定义类型 VAR 上了

28.怎么转换 less 为 css

• 首先,你要确认你的电脑已经安装了 node。使用 npm 安装 lessc,命令行:
npm install-gless
• 然后,进入需要转换的 less 文件的目标位置。
• 最后,你只需输入以下两条命令: npm install -g less;lessc less 文件名.less 生
成的 css 文件名.css

29.echarts 使用最多的是什么

• Echarts 使用最多的一般是:有着丰富的可视化类型,可以实现多种数据格式无
需转换直接使用,可以实现千万数据的前端展现,一般使用在大数据可视化平
台。
• Echaets 是什么: ECharts 是百度开发的一个国内比较常用的网页图表工具,
也算是它旗下不可多得的优秀工具之一。如果你看过其它的 js 图表工具就可以
知道这玩意的强大之处了,相比其它 xxChart,ECharts 提供了基本上最完善的
图表类型模板,api 接口和配置项,其次,它用起来比较方便,现成的模板非常
易于使用,如果不需要一些高级特性,那么只需要一点前端知识就能完成数据
的可视化。
• (ECharts(4.0)特性:
1、 丰富的可视化类型提供了常规的图,盒形图,用于地理数据可视化的图,用
于关系数据可视化的图,多维数据可视化的平行坐标,并且支持图与图之间
的混搭 多种数据格式无需转换直接使用 ECharts 内置的 dataset 属性
(4.0+)通过简单的设置 encode 属性就可以完成从数据到图形的映射。37
2、 千万数据的前端展现 ECharts 同时提供了对流加载(4.0+)的支持,可以使
用 WebSocket 或者对数据分块后加载,不需要漫长地等待所有数据加载完
再进行绘制 移动端优化 例如移动端小屏上适于用手指在坐标系中进行缩
放、平移。 PC 端也可以用鼠标在图中进行缩放(用鼠标滚轮)、平移等。
3、 多渲染方案,跨平台使用 不同的渲染方式提供了更多选择,使得 ECharts
在各种场景下都有更好的表 现。深度的交互式数据探索提供了图例、视觉
映射、数据区域缩放、tooltip、数据刷选等开箱即用的交互组件,可以对数
据进行多维度数据筛取、视图缩放、展示细节等交互操作
4、 多维数据的支持以及丰富的视觉编码手段 ECharts 3 开始加强了对多维数据
的支持。除了加入了平行坐标等常见的多维数据可视化工具外,对于传统的
散点图等,传入的数据也可以是多个维度的。配合视觉映射组件 visualMap
提供的丰富的视觉编码,能够将不同维度的数据映射到颜色,大小,透明
度,明暗度等不同的视觉通道动态数据 ECharts 由数据驱动,数据的改变
驱动图表展现的改变。因此动态数据的实现也变得异常简单,只需要获取数
据,填入数据,ECharts 会找到两组数据之间的差异然后通过合适的动画去
表现数据的变化。配合 timeline 组件能够在更高的时间维度上去表现数据
的信息。
5、 绚丽的特效 ECharts 针对线数据,点数据等地理数据的可视化提供了吸引
眼球的特效。、通过 GL 实现更多更强大绚丽的三维可视化提供了基于
WebGL 的 ECharts GL,你可以跟使用 ECharts 普通组件一样轻松的使用
ECharts GL 绘制出三维的地球,建筑群,人口分布的柱状图,在这基础之上
还提供了不同层级的画面配置项,几行配置就能得到艺术化的画面。
6、 无障碍访问(4.0+)支持自动根据图表配置项智能生成描述,使得盲人可以
在朗读设备的帮助下了解图表内容,让图表可以被更多人群访问。)

30.For 循环与 map 循环有什么区别

• For 循环:在固定长度或者长度不计算的情况下 for 循环效率更高
• Map 循环:在不确定长度或者计算长度有损性能的时候用 map 比较方便,如
果需要操作元素里面的每一个值并且返回一个新数组的话,那么 map 就是最好
的选择, 数组中的元素为原始数组调用函数处理后的值。

31.请写出一个简单的类与继承

Person 类父类
function Person(name, age, sex) {
// 私有属性和私有方法
this.name = name; this.age = age;
this.sex = sex;
}
// 原型属性和原型方法
Person.prototype.type = “灵长类”;
Person.prototype.sayName = function(){ alert(this.name)
}
let lxg = new Person(“雷小盖”,18,“女”)
// SuperMan 类子类38
function SuperMan(name, age, sex, skill) {
// 继承了父类 Person 里面所有的特征(属性)
// 此时只继承了私有属性和私有方法
Person.apply(this, [name, age, sex]); this.skill = skill;
}
// 将父类的实例化对象赋值给子类的原型对象
// 原型链继承
SuperMan.prototype = new Person();
// 子类的原始中独有的一个方法,父类的原型里应该没有
SuperMan.prototype.showSkill = function() {
alert(this.skill)
}
let spiderMan = new SuperMan(“蜘蛛侠”, 18, “男”, “爬墙”);
//修复实例化对象的 constructor 指向问题
spiderMan.constructor = SuperMan;

32.同步与异步的区别/阻塞与非阻塞区别

• 同步与异步: 同步与异步是对应的,它们是线程之间的关系,两个线程之间要
么是同步的,要么是异步的。
• 区别:同步就是由调用者主动等待这个调用的结果。而异步则是相反,调用在发
出之后,这个调用就直接返回了,所以没有返回结果。同步就是在发出一个调用
时,在没有得到结果之前,该调用就不返回。但是一旦调用返回,就得到返回值
了。当一个异步过程调用发出后,调用者不会立刻得到结果。而是在调用发出
后,被调用者通过状态、通知来通知调用者,或通过回调函数处理这个调用。
• 阻塞与非阻塞:阻塞与非阻塞是对同一个线程来说的,在某个时刻,线程要么处
于阻塞,要么处于非阻塞。
• 区别:阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得
到结果之后才会返回。非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞
当前线程。

33.重绘和回流是什么

• 解析 HTML,生成 DOM 树,解析 CSS,生成 CSSOM 树,将 DOM 树和
CSSOM 树结合生成渲染树(Render Tree)
• Layout(回流):当渲染树中的一部分或者全部因为元素的尺寸、布局、隐藏等改变
而需要重新构建的时候,这时候就会发生回流。根据生成的渲染树,进行回流
(Layout),得到节点的几何信息(位置,大小)
• Painting(重绘):在回流的时候,浏览器会使渲染树中受到影响的元素部分失效,
并重新绘制这个部分的渲染树,完成回流以后,浏览器会重新绘制受到影响的部
分元素到屏幕中,这个过程就是重绘。根据渲染树以及回流得到的几何信息,得
到节点的绝对像素
• (什么时候会发生回流和重绘
o 添加或删除可见的 DOM 元素
o 元素的位置发生变化
o 元素的尺寸发生变化(包括外边距、内边框、边框大小、高度和宽度等)
o 内容发生变化,比如文本变化或图片被另一个不同尺寸的图片所替代。
o 页面一开始渲染的时候(这肯定避免不了)
o 浏览器的窗口尺寸变化(因为回流是根据视口的大小来计算元素的位置和大
小的)
o 回流一定会触发重绘,而重绘不一定会回流
• 如何减少回流,重绘?
o 修改 html 元素中对应的 class 名,利用 class 替换样式
o csstext(利用 cssText 属性合并所有改变,然后一次性写入)
o display:none(隐藏元素,应用修改,重新显示))

34.http 是什么?有什么特点

• HTTP(HyperText Transfer Protocol 超文本传输协议)是用于从万维网服务器传输
超文本到本地浏览器的传送协议。
• HTTP 基于 TCP/IP 协议模型来传递数据
• 特点:可靠传输、应用层协议、灵活可拓展、请求-应答、无状态。

35.HTTP 协议和 HTTPS 区别

• HTTPS 和 HTTP 的区别主要如下
o https 协议需要到 ca 申请证书,一般免费证书较少,因而需要一定费用。
o http 是超文本传输协议,信息是明文传输,https 则是具有安全性的 ssl 加
密传输协议。
o http 和 https 使用的是完全不同的连接方式,用的端口也不一样,前者是
80,后者是 443。
o http 的连接很简单,是无状态的;HTTPS 协议是由 SSL+HTTP 协议构建的
可进行加密传输、身份认证的网络协议,比 http 协议安全。
o HTTP:是互联网上应用最为广泛的一种网络协议,是一个客户端和服务器
端请求和应答的标准(TCP),用于从 WWW 服务器传输超文本到本地浏览
器的传输协议,它可以使浏览器更加高效,使网络传输减少。
o HTTPS:是以安全为目标的 HTTP 通道,简单讲是 HTTP 的安全版,即
HTTP 下加入 SSL 层,HTTPS 的安全基础是 SSL,因此加密的详细内容就
需要 SSL。
o HTTP 协议传输的数据都是未加密的,也就是明文的,因此使用 HTTP 协议
传输隐私信息非常不安全,为了保证这些隐私数据能加密传输,于是网景公
司设计了 SSL(Secure Sockets Layer)协议用于对 HTTP 协议传输的数据
进行加密,从而就诞生了 HTTPS。简单来说 HTTPS 协议是由 SSL+HTTP
协议构建的可进行加密传输、身份认证的网络协议,要比 http 协议安全。

36.原型和继承,prototype,call 和 apply 继承的区别(第一个

参数是相同的,第二个的区别在哪)
• 原型:每一个构造函数都有一个 prototype 属性,这个属性会在生成实例的时
候,成为实例对象的原型对象。javascript 的每个对象都继承另一个对象,后者
称为“原型”(prototype)对象。40
• 继承:继承就是在子类构造函数中继承父类构造函数的私有属性和原型属性。我
们在子类构造函数中使用 call 或 apply 方法调用父类构造函数并改变其 this
指向为子类构造函数的 this,此时子类的构造函数就继承了父类的私有属性和私
有方法。将父类的实例化对象赋值给子类的原型对象,此时子类就继承了父类的
原型属性和原型方法。
• call 和 apply 的区别:每一个函数都有 call 和 apply 方法,都是帮助我们调用
函数的,但是在调用的时候可以改变本次执行函数中的 this 指向。他们的不同
点就在于 call 是无限多个参数,而 apply 有两个参数,第二个参数是数组,代
表实参集合。一般来说我们也就是在用 JS 实现面向对象的继承特点时会使用到
这个方法。

37.数组的方法,字符串的方法,要知道每个的含义,掌握排序和去重的方法

• 数组:
o push(新值) 向数组的尾端插入一个新的元素
o unshift(新值) 向数组的前端插入一个新的元素
o pop() 删掉数组中最后一个元素
o shift() 删掉数组中第一个元素
o splice(删除的下标,1) 从某一个下标上删除一个元素,有副作用
o splice(要插入的下标,0,要插入的数据) 从中间插入一个元素
o concat() 拼接数组,返回值为合并成的新数组,原数组不会改变
o join() 将数组转换为字符串,参数为分隔符,原数组不会改变
o reverse() 颠倒数组中元素的顺序,会改变原数组
o slice(start,end) 通过开始下标和结束下标截取数组元素,原数组不会发生改

o toString() 将数组转换为字符串可以被 join 完美代替
o sort() 通过 Unicode 进行排序,在原数组上排序,不生成副本
var arr = [1, 5, 6, 1, 3, 4, 11, 2, 5]
//排序固定写法升序
arr.sort(function(num1, num2) {
return num1 - num2;
}) console.log(arr);
//排序固定写法降序
arr.sort(function(num1, num2) { return num2 - num1;
}) console.log(arr);
• 字符串:
o charAt() 根据下标查找字符
o concat() 字符串拼接,平时我们会用+运算代替
o indexOf() 根据字符查找对应的下标从一个字符串中检索某个字符的下标,
如果没有找到对应的字符,则返回-1;如果要寻找的字符有多个,则默认返
回第一个的下标
o lastIndexof() 根据字符查找对应的下标(从后往前找)
o replace(“原字符”,“新字符”) 替换字符41
//惰性匹配用 m 替换 e
console.log(str.replace(“e”, “m”));
//全局匹配
console.log(str.replace(/c/g, “m”));
o slice(start,end) 通过起始下标和终结下标截取一段字符串,结果中包含开始
位但不包含结束位;如果省掉第二个参数则代表一直截取到结束为止
o substring() 同 slice 功能和参数都一致,不过第二个参数不允许传负数
o split() 根据所传参数的字符作为分隔将原字符切割为长度若干的一个数组
o substr() 通过起始下标和截取数量来截取一段字符串
o toLowerCase() 转换字符串为小写
o toUpperCase() 转换字符串为大写

38.箭头函数与普通函数的区别

• 外形不同:箭头函数使用箭头定义,普通函数中没有。
• 箭头函数全都是匿名函数:普通函数可以有匿名函数,也可以有具名函数
• 箭头函数不能用于构造函数:普通函数可以用于构造函数,以此创建对象实例。
• 箭头函数中 this 的指向不同:在普通函数中,this 总是指向调用它的对象,如
果用作构造函数,它指向创建的对象实例。
• 箭头函数不具有 arguments 对象:每一个普通函数调用后都具有一个
arguments 对象,用来存储实际传递的参数。但是箭头函数并没有此对象。
• 其他区别:箭头函数不具有 prototype 原型对象。箭头函数不具有 super。
箭头函数不具有 new.target。

39.什么是 js 内存泄露?

• 内存泄漏(Memory Leak)是指程序中已动态分配的堆内存由于某种原因程序未
释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等
严重后果。
• 避免内存泄漏:
o 避免误建全局变量:在 JS 中使用未定义的变量,会在全局对象中定义一个
新变量。在浏览器中,全局变量是 window
o 注意定时器或回调函数的使用:使用定时器不可避免,但尽量少使用,尽量
在使用完定时器后,使用 clearInterval 或者 clearTimeout。

40.你如何对网站的文件和资源进行优化?

• 利用浏览器缓存你的 js 和 CSS 文件
• 把你的 .js 库文件地址替换成 CDN 的地址
• 精简和优化 js 和 CSS
• 使用 css sprites 合并图片(精灵图)
• 优化网站图片
• 文件合并(相当于去重,把所用到的 css 样式或者 js 可以封装成一个公共类)
目的是为了减少 http 的请求

41.请简述 ajax 的执行过程以及常见的 HTTP 状态码

(1).创建 XMLHttpRequest 对象42
let http=new XMLHttpRequest();
(2).设置请求参数
//http.open(“post 还是 get”,“发送给谁”,“是否异步”);
http.open(“get”, “ajax.txt”,true);
(3).发送请求
http.send();
(4).设置回调函数
http.onreadystatechange=function(){ if(http.status200 &&
http.readyState
4){
//http.responseText request 从后端接收的数据
(5).接收响应:http.responseText 或者 http.responseXML
console.log(http.responseText);
}}
• 常见的 http 状态码
o 2 开头的基本都是代表成功
200 OK 正常返回数据
o 3 开头的一般也是成功了,只不过中间做了一些额外处理
301 Moved Permanently 永久性转移/重定向,一般应用于网站域名更换,
访问老域名,永久都跳转到新的域名上
302 Move Temporarily 临时转移
304 Not Modified 读取的是缓存中的数据,这个是客户端和服务器端共建的
协商缓存(把不经常更新,请求过的资源文件做缓存,后期在访问这些资源
直接走缓存数据,除非服务器端更新了此资源,或者客户端强制清缓存刷新

307 Temporary Redirect 临时重定向,一般应用于服务器的负载均衡
o 4 开头的都是失败:失败的原因一般都是客户端(前端)的问题
400 Bad Request 请求参数错误
401 Unauthorized 无权限访问
404 Not Found 地址错误
405 Method Not Allowed 当前请求的方式服务器不支持
o 5 开头的都是失败:失败的原因一般都是服务器(后端)问题
500 Internal Server Error 未知服务器错误
503 Service Unavailable 服务器超负荷

42.预加载和懒加载的区别,预加载在什么时间加载合适

• 预加载:提前加载图片,当用户需要查看时可直接从本地缓存中渲染。预加载是
牺牲服务器前端性能,换取更好的用户体验,这样可以使用户的操作得到最快的
反映。
• 懒加载也叫延迟加载:按照一定的条件或者需求等到满足条件的时候再加载对应
的资源。懒加载页面加载速度快、可以减轻服务器的压力、节约了流量,用户体
验好。
• 预加载使用场景:在网页全部加载之前,对一些主要内容进行加载,以提供给用
户更好的体验,减少等待的时间。否则,如果一个页面的内容过于庞大,没有使
用预加载技术的页面就会长时间的展现为一片空白,直到所有内容加载完毕。

43.Jquery 选择器有哪些

• 基础选择器
o id 选择器KaTeX parse error: Expected 'EOF', got '#' at position 3: ('#̲brother').css('…(‘a’).css({‘color’:‘green’,‘font-size’:‘24px’});
o 类选择器: ( ′ . l i 3 ′ ) . c s s ( ′ b a c k g r o u n d ′ , ′ y e l l o w ′ ) ; o 通 配 符 选 择 器 : c o n s o l e . l o g ( ('.li3').css('background','yellow'); o 通配符选择器:console.log( (.li3).css(background,yellow);o:console.log((’’)); ( ′ ′ ) . h t m l ( ′ ′ ) ; / / 清 空 整 个 界 面 的 d o m 元 素 • 层 级 选 择 器 o 后 代 选 择 器 : ('').html(''); // 清空整个界面的 dom 元素 • 层级选择器 o 后代选择器: ().html();//domo(’#box p’).css(‘color’,‘red’);
o 子代选择器:$(’#box>p’).css(‘color’,‘green’);
o 毗邻选择器,匹配所有的紧接着选中元素的兄弟:
$(’#father+p’).css(‘font-size’,‘30px’);
o 兄弟选择器 $(’#father~p’).css(‘background’,‘gray’);
• 过滤选择器
o 获取第一个 $(‘li:first’).css(‘background’,‘gray’);
o 获取最后一个 $(‘li:last’).css(‘background’,‘yellow’);
o 获取奇数 $(‘li:odd’).css(‘color’,‘red’);
o 获取偶数 $(‘li:even’).css(‘color’,‘green’);
o 选中索引值为 1 $(‘li:eq(1)’).css(‘font-size’,‘32px’);
o 大于索引值 1 $(‘li:gt(1)’).css(‘font-size’,‘60px’);
o 小于索引值 1 $(‘li:lt(1)’).css(‘font-size’,‘10px’);
• 属性选择器
o $(‘li[id]’).css(‘color’,‘red’);
o $(‘li[class=what]’).css(‘font-size’,‘30px’);
o $(‘li[class!=what]’).css(‘font-size’,‘50px’);
o $(‘input[name^=username]’).css(‘background’,‘gray’);
o ( ′ i n p u t [ n a m e ('input[name (input[name=222]’).css(‘background’,‘green’);
o $(‘button[class*=danger]’).css(‘background’,‘orange’);
o 解释:
6. 标签名【属性名】,查找所有含有 id 属性的该标签名的元素
7. 匹配给定的属性是 what 值【attr=value】匹配给定的属性是某个特定
值的元素
8. 没有 class 也会发生变化,[attr!=value]匹配所有不包含有特定的属
性,或者属性不等于特定值的元素
9. 匹配给定的属性是以某些值开始的元素 ^
10. 匹配给定的属性是以某些值结尾的元素 $
11. 匹配给定的属性是以包含某些值的元素 *
• 筛选选择器
o $(‘span’).eq(1).css(‘color’,‘red’); o $(‘span’).first().css(‘font-size’,‘28px’);
o ( ′ s p a n ′ ) . l a s t ( ) . c s s ( ′ c o l o r ′ , ′ g r e e n y e l l o w ′ ) ; c o n s o l e . l o g ( ('span').last().css('color','greenyellow'); console.log( (span).last().css(color,greenyellow);console.log((‘span’).parent());
o $(‘span’).parent(’.p1’).css({‘width’:‘300px’,height:‘400px’,‘backgro und’:‘red’});
o $(’.list’).siblings(‘li’).css(‘color’,‘red’); o
( ′ d i v ′ ) . f i n d ( ′ b u t t o n ′ ) . c s s ( ′ b a c k g r o u n d ′ , ′ g r a y ′ ) ; 44 o 解 释 : 12. 获 取 第 n 个 元 素 数 值 从 0 开 始 . e q ( ) 13. 获 取 第 一 个 元 素 . f i r s t ( ) 14. 获 取 最 后 一 个 元 素 . l a s t ( ) 15. 获 取 父 元 素 . p a r e n t ( ) 16. 选 择 所 有 的 兄 弟 元 素 . s i b l i n g s ( ) 17. 查 找 所 有 的 后 代 元 素 . f i n d ( ) o j Q u e r y 的 筛 选 器 的 分 类 o 过 滤 筛 选 器 如 : ('div').find('button').css('background','gray'); 44 o 解释: 12. 获取第 n 个元素数值从 0 开始 .eq() 13. 获取第一个元素 .first() 14. 获取最后一个元素 .last() 15. 获取父元素 .parent() 16. 选择所有的兄弟元素 .siblings() 17. 查找所有的后代元素 .find() o jQuery 的筛选器的分类 o 过滤筛选器如: (div).find(button).css(background,gray);44o12.n0.eq()13..first()14..last()15..parent()16..siblings17..find()ojQueryo(“li”).eq(2) $(“li”).first() $(“ul li”).hasclass(“test”)
o 查找筛选器如:查找子标签: $(“div”).children(".test")
$(“div”).find(".test")
o 向下查找兄弟标签: $(".test").next() $(".test").nextAll()
$(".test").nextUntil()
o 向上查找兄弟标签: $(“div”).prev() $(“div”).prevAll()
$(“div”).prevUntil()
o 查找所有兄弟标签: $(“div”).siblings()
o 查找父标签: $(".test").parent() $(".test").parents()
$(".test").parentUntil()

44.Jquery 插入节点的方法

• before(): 在指定节点的前面添加要添加的节点
• insertBefore(): 把要插入节点插入到指定节点的前面
• after (): 在指定节点的后面添加要添加的节点
• insertAfter (): 把要插入的节点插入到指定节点的后面
• prepend (): 在指定父级里面的最前面添加指定节点
• prependTo (): 把指定节点添加到指定父级里面的最前面
• append (): 在指定父级里面的最后面添加指定节点 • appendTo (): 把指定节点添
加到指定父级里面的最后面

45.Js 的函数节流和函数防抖的区别

• 区别:
o 函数节流是指一定时间内 js 方法只跑一次。比如人的眨眼睛,就是一定时
间内眨一次。这是函数节流最形象的解释。函数防抖是指频繁触发的情况
下,只有足够的空闲时间,才执行代码一次。比如生活中的坐公交,就是一
定时间内,如果有人陆续刷卡上车,司机就不会开车。只有别人没刷卡了,
司机才开车。
o 函数防抖: 防抖就是指触发事件后在 n 秒内函数只能执行一次,如果在 n
秒内又触发了事件,则会重新计算函数执行时间。
let box = document.getElementById(‘box’);
let timer = 0 box.onclick = function () {
clearTimeout(timer)
timer = setTimeout(() => {
console.log(1)
}, 1000)}
• 应用场景:
o 函数防抖的应用场景,最常见的就是用户注册时候的手机号码验证和邮箱验
证了。只有等用户输入完毕后,前端才需要检查格式是否正确,如果不正
确,再弹出提示语。
o 函数节流:节流就是指连续触发事件但是在 n 秒中只执行一次函数。
let box = document.getElementById(‘box’);
let timer = 0;
box.onclick = function () {
if (!timer) { timer = setTimeout(() => {
timer = 0;
console.log(1)
}, 1000) }}
o 函数节流应用的实际场景,多数在监听页面元素滚动事件的时候会用到。因
为滚动事件,是一个高频触发的事件。
46.Get 和 post 不同
• get 请求参数是在 URL 中存在的,post 请求的参数是在请求主体中的
• post 的安全性要好于 get 请求
• get 请求会造成一次浏览器浏览记录,而 post 请求不会有浏览记录
• get 请求有长度限制,post 没有长度限制

47.什么是 csrf 攻击

• CSRF 攻击:中文名称:跨站请求伪造,可以理解为攻击者盗用了你的身份,以你的
名义发送恶意请求,比如:以你名义发送邮件、发消息、购买商品,虚拟货币转账
等。
• 防御手段:
o 验证请求来源地址;
o 关键操作添加验证码;
o 在请求地址添加 token 并验证。

48.Js 数据类型的分类

• 基本数据类型:
o 数值类型(number)包含数字
o 字符串类型(string)由单双引号包住的字符串内容会原样输出
o 布尔类型(boolean)只会输出 true ,false
o undefined 数值定义但未初始化
o null 空
o Symbol 表示独一无二的值(ES6 新增)
• 引用类型:
o object ,Array(数组),Date(日期),Functiion(函数),Regexp(正则)
• 检测变量数值类型
o typeof 后面加变量名,typeof 本身是字符串类型,变量的数据类型取决于
变量里保存的数据。
console.log(
typeof 123, //“number”
typeof ‘dsfsf’, //“string”
typeof false, //“boolean”
typeof [1,2,3], //“object”
typeof {a:1,b:2,c:3}, //“object”
typeof function(){console.log(‘aaa’);}, //“function”
typeof undefined, //“undefined”
typeof null, //“object”
typeof new Date(), //“object”
typeof /1{5,20} / , / / " o b j e c t " t y p e o f n e w E r r o r ( ) / / " o b j e c t " ) ; o i n s t a n c e o f i n s t a n c e o f 运 算 符 需 要 指 定 一 个 构 造 函 数 , 或 者 说 指 定 一 个 特 定 的 类 型 , 它 用 来 判 断 这 个 构 造 函 数 的 原 型 是 否 在 给 定 对 象 的 原 型 链 上 c o n s o l e . l o g ( 123 i n s t a n c e o f N u m b e r , / / f a l s e ′ d s f s f ′ i n s t a n c e o f S t r i n g , / / f a l s e f a l s e i n s t a n c e o f B o o l e a n , / / f a l s e [ 1 , 2 , 3 ] i n s t a n c e o f A r r a y , / / t r u e a : 1 , b : 2 , c : 3 i n s t a n c e o f O b j e c t , / / t r u e f u n c t i o n ( ) c o n s o l e . l o g ( ′ a a a ′ ) ; i n s t a n c e o f F u n c t i o n , / / t r u e u n d e f i n e d i n s t a n c e o f O b j e c t , / / f a l s e n u l l i n s t a n c e o f O b j e c t , / / f a l s e n e w D a t e ( ) i n s t a n c e o f D a t e , / / t r u e / [ a − z A − Z ] 5 , 20 /, //"object" typeof new Error() //"object" ); o instanceof instanceof 运算符需要指定一个构造函数,或者说指定一 个特定的类型,它用来判断这个构造函数的原型是否在给定对象的 原型链上 console.log( 123 instanceof Number, //false 'dsfsf' instanceof String, //false false instanceof Boolean, //false [1,2,3] instanceof Array, //true {a:1,b:2,c:3} instanceof Object, //true function(){console.log('aaa');} instanceof Function, //true undefined instanceof Object, //false null instanceof Object, //false new Date() instanceof Date, //true /^[a-zA-Z]{5,20} /,//"object"typeofnewError()//"object");oinstanceofinstanceofconsole.log(123instanceofNumber,//falsedsfsfinstanceofString,//falsefalseinstanceofBoolean,//false[1,2,3]instanceofArray,//truea:1,b:2,c:3instanceofObject,//truefunction()console.log(aaa);instanceofFunction,//trueundefinedinstanceofObject,//falsenullinstanceofObject,//falsenewDate()instanceofDate,//true/[azAZ]5,20/ instanceof RegExp, //true
new Error() instanceof Error //true
)
Number,String,Boolean 没有检测出他们的类型,但是如果使用下面
的写法则可以检测出来:
var num = new Number(123);
var str = new String(‘dsfsf’);
var boolean = new Boolean(false);
还需要注意 null 和 undefined 都返回了 false,这是因为它们的类型
就是自己本身,并不是 Object 创建出来它们,所以返回了 false。
o toString() 为了每个对象都能通过 Object.prototype.toString() 来检测,需要
以 Function.prototype.call() 或者 Function.prototype.apply() 的形式来调
用,传递要检查的对象作为第一个参数,称为 thisArg
var toString = Object.prototype.toString;
toString.call(123); //"[object Number]"
toString.call(‘abcdef’); //"[object String]"
toString.call(true); //"[object Boolean]"
toString.call([1, 2, 3, 4]); //"[object Array]“47
toString.call({name:‘wenzi’, age:25}); //”[object Object]"
toString.call(function(){ console.log(‘this is function’); }); //"[object Function]"
toString.call(undefined); //"[object Undefined]"
toString.call(null); //"[object Null]"
toString.call(new Date()); //"[object Date]"
toString.call(/2{5,20}$/); //"[object RegExp]"
toString.call(new Error()); //"[object Error]"

49.Js 中手写一个深拷贝

• 乞丐版:
var newObj = JSON.parse( JSON.stringify( someObj ) );
• 面试够用版:
function deepCopy(obj){
//判断是否是简单数据类型,
if(typeof obj == “object”){
//复杂数据类型
var result = obj.constructor == Array ? [] : {};
for(let i in obj){
result[i] = typeof obj[i] == “object” ? deepCopy(obj[i]) : obj[i];
}
}else {
//简单数据类型直接 == 赋值
var result = obj;
}
return result;
}

50.什么时候用深拷贝 /浅拷贝

• 浅拷贝是什么:浅拷贝就是增加了一个指针指向已存在的内存
(JavaScript 并没有指针的概念,这里只是用于辅助说明),浅拷贝只是拷贝了
内存地址,子类的属性指向的是父类属性的内存地址,当子类的属性修改后,父
类的属性也随之被修改。
• 深拷贝是什么:深拷贝就是增加一个指针,并申请一个新的内存,并且让这个新
增加的指针指向这个新的内存地址使用深拷贝,在释放内存的时候就不会像浅拷
贝一样出现释放同一段内存的错误,当我们需要复制原对象但又不能修改原对象
的时候,深拷贝就是一个,也是唯一的选择。
• 什么时候用浅拷贝:从服务器 fetch 到数据之后我将其存放在 store 中,通过
props 传递给界面,然后我需要对这堆数据进行修改,那涉及到的修改就一定有
保存和取消,所以我们需要将这堆数据拷贝到其它地方。
• 什么时候用深拷贝:当你想使用某个对象的值,在修改时不想修改原对象,那么
可以用深拷贝弄一个新的内存对象。像 es6 的新增方法都是深拷贝,所以推荐
使用 es6 语法。48

51.如何遍历一个多维数组

• 第一种
var arr = [
[1, 2, 3, 4],
[2, 4, 6, 8],
[6, 4, 9, 0]
]
if (arr.length != 0)
{ //判断数组长度是否为 0 for (var i = 0; i < arr.length; i++)
{ //循环最外面的数组 for (var j = 0; j < arr[i].length; j++)
{ //循环里面的数组 document.write(arr[i][j]); document.write(’
’)
}}}
• 第二种
var arr = [1,2,3,[4,5,[6,7,8,[9,10]]]];
Array.prototype.eachall = function(fn) { try{
//声明一个计数器
this.i || (this.i = 0)
//判断数组存在且传的值是一个函数
if (this.length>0 && fn.constructor==Function) {
//循环
while(this.i<this.length){ var e = this[this.i];
//判断当前值是不是数组如果是数组进行递归否则执行回调函数
if (e && e.constructor == Array) {
e.eachall(fn);
} else{
fn.call(e,e);
}; this.i++;
}
//变量回收
this.i=null;
};
}catch(err){ console.log(“have error:”+err);
}};
arr.eachall(function(item){ console.log(item);
});

52.axios 的特性

• 从浏览器中创建 XMLHttpRequests
• node.js 创建 http 请求
• 支持 Promise API
• 拦截请求和响应
• 转换请求数据和响应数据
• 取消请求49
• 自动换成 json
• axios 中的发送字段的参数是 data 跟 params 两个
o 两者的区别在于 params 是跟请求地址一起发送的,data 的作为一个请求
体进行发送;params 一般适用于 get 请求;data 一般适用于 post put 请

53.在地址栏上输入一个 url,到这个页面呈现出来,中间会发生

什么?
• 检查缓存
• DNS 解析
• TCP 连接
• 发送 HTTP 请求
• 服务器处理请求并返回 HTTP 报文
• 浏览器解析渲染页面
• 连接结束
o 首先在浏览器地址栏中输入 url
o 浏览器先查看浏览器缓存-系统缓存-路由器缓存,如果缓存中有,直接显示
页面内容;如果没有,跳到第三步;
o 域名解析,获取相应的 IP 地址
o 浏览器向服务器发送 tcp 连接,与浏览器建立三次握手
o 握手成功后,建立 http 请求
o 服务器收到请求,将数据返回至浏览器
o 浏览器收到 http 响应
o 读取页面内容,浏览器渲染,解析 html 源码

54.异步操作的解决方案

• 回调函数 callback:被作为实参传入另一函数,并在该外部函数内被调用,用以
来完成某些任务的函数。如 setTimeOut,ajax 请求,readFile 等。
• 事件发布订阅:当一个任务执行完成后,会发布一个事件,当这个事件有一个或
多个‘订阅者’的时候,会接收到这个事件的发布,执行相应的任务,这种模式叫
发布订阅模式。如 node 的 events,dom 的事件绑定
• Promise:Promise 是 es6 提出的异步编程的一种解决方案。
o Promise 对象有三种状态:
pending: 初始状态,既不是成功,也不是失败状态。
fulfilled: 意味着操作成功完成。
rejected: 意味着操作失败。
o promise 的状态只能从 pending 变成 fulfilled,和 pending 变成
rejected,状态一旦改变,就不会再改变,且只有异步操作的结果才能改变
promise 的状态。

55.map 和 foreach 的区别

• 相同点:
o 都是循环遍历数组中的每一项50
o forEach 和 map 方法里每次执行匿名函数都支持 3 个参数,参数分别是
item(当前每一项)、index(索引值)、arr(原数组) o 匿名函数中的 this
都是指向 window o 只能遍历数组
• 不同点:
o forEach()没有返回值,map() 有返回值,可以 return 出来
o 不管是 forEach 还是 map 在 IE6-8 下都不兼容(不兼容的情况下在
Array.prototype 上没有这两个方法)

56.TCP 和 UDP 的区别

• 基于连接与无连接;
• 对系统资源的要求(TCP 较多,UDP 少);
• UDP 程序结构较简单;
• 流模式与数据报模式;
• TCP 保证数据正确性,UDP 可能丢包,TCP 保证数据顺序,UDP 不保证。

56.BOM 和 DOM 的区别

• 概念:
o BOM 是浏览器对象模型,提供了独立于内容而与浏览器窗口进行交互的对
象。
o DOM 是文档对象模型,DOM 和文档有关,这里的文档指的是网页,也就
是 HTML 文档
• 标准:
o BOM 没有相关标准:由于没有标准,不同的浏览器实现同一功能,可以需
要不同的实现方式 o DOM 是 W3C 的标准
• 根本对象:
o BOM 的最根本对象是 window
o DOM 最根本对象是 document(实际上是 window.document)

57.git(复杂)

• ssh-keygen -t rsa -C “xxxxx@xxxxx.com” 生成 SSH 密钥
• git init 初始化仓库
• git status 查看仓库状态
• git add <文件名> 将工作区的某一个文件提交到缓冲区
• git add -A 将工作区的所有被修改过的和新添的和删除的操作全部提交到缓冲区
• git commit -m “注释” 将缓冲区内的文件提交到版本库
• git diff <文件名> 对比文件
• git commit -am “注释” 将工作区中所有被追踪并且有过修改的文件一次性提交
到版本库
• git log 查看提交记录
• git reflog 查看提交记录(包含所有回滚)
• git reset --hard <版本号> 回到过去/回到未来
• git push 将本地版本库中的文件状态推送到远程库中
• git pull 将远程库的状态更新到本地库中
• git clone 将远程库拉取到本地51

58.什么是 Node.js

Nodejs 是一个基于 Chrome JavaScript 运行时建立的平台,用于方便地搭建响应速
度快、易于扩展的网络应用。Node 使用事件驱动,非阻塞 I/O 模型而得以轻量和
高效,非常适合在分布式设备上运行数据密集型的实时应用。52

VUE

1.Vue 的核心是什么

数据驱动和组件化

2.请简述你对 vue 的理解

• 定义:vue 是一套构建用户界面的渐进式的自底向上增量开发 MVVM 框架,
Vue 的核心库只关注视图层,它不仅易于上手,还便于与第三方库或既有项目
整合。通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。
• 优点:轻量级、高效率、上手快、简单易学、文档全面而简洁
• 目的:解决数据绑定问题;Vue.js 主要的目的是为了开发大型单页面应用;支持
组件化,也就是可以把页面封装成为若干个组件,把组件进行拼装,这样是让页
面的复用性达到最高
• 核心思想:数据驱动、组件化
• 优势:简洁:HTML 模板 + Vue 实例 + JSON 数据;轻量:17kb,性能好;设
计思想:视图与数据分离,无需操作 DOM;社区:大量的中文资料和开源案例

3.请简述 vue 的单向数据流

• 数据从父级组件传递给子组件,只能单向绑定。子组件内部不能直接修改从父级
传递过来的数据。所有的 prop 都使得其父子 prop 之间形成了一个单向下行
绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。每次父级
组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不
应该在一个子组件内部改变 prop。

4.Vue 常用的修饰符有哪些

• 按键修饰符 .up,.down,.ctrl,.enter,.space 等等
语法:@click.修饰符=‘fn()’ o 事件修饰符
prevent 修饰符:阻止事件的默认行为(submit 提交表单)
stop 修饰符:阻止事件冒泡
capture 修饰符:与事件冒泡的方向相反,事件捕获由外到内
self:只会触发自己范围内的事件,不包含子元素
once:只会触发一次
注意:修饰符可以串联使用

5.v-text 与{{}}区别

• v-text 是操作网页元素中的纯文本内容,{{}}是它的另外一种写法, v-text 与{{}}
等价,{{}}叫模板插值,v-text 叫指令,有一点区别就是,在渲染的数据比较多
的时候,可能会把大括号显示出来,俗称屏幕闪动。
• 解决屏幕闪动的方法:
o 使用 v-text 渲染数据;
o 使用{{}}语法渲染数据,但是同时使用 v-cloak 指令(用来保持在元素上直
到关联实例结束时候进行编译),v-cloak 并不需要添加到每个标签,只要53
在 el 挂载的标签上添加就可以,并且为[v-cloak]添加 css 样式为
display:none;

6.v-on 可以绑定多个方法吗

可以绑定多个方法,中间用逗号隔开

7.Vue 循环的 key 作用

• vue 中循环需加 :key=“唯一标识” ,唯一标识可以指 item 里面 id、 index
等,因为 vue 组件高度复用增加 key 可以标识组件的唯一性,为了更好地区别
各个组件,key 的作用主要是为了高效的更新虚拟 DOM
• 为遍历数组或元素中的唯一标识,增加或删减元素时,通过这个唯一标识 key
判断是否是之前的元素,vue 会直接对已有的标签进行复用,不会整个的将所有
的标签全部重新删除和创建,只会重新渲染数据,然后再创建新的元素直到数据
渲染完为止

8.什么是计算属性

首先它是一种属性,其次它有“计算”这个特殊性质。每次取得它的值的时候,它不像
普通属性那样直接返回结果,而是经过一系列的计算之后再返回结果。同时只要在
它的当中引用了 data 中的某个属性,当这个属性发生变化时,计算属性会自动重新
执行。

9.Vue 单页面的优缺点

• 优点:
用户体验好,快,内容的改变不需要重新加载整个页面,对服务器压力较小。
前后端分离,比如 vue 项目
完全的前端组件化,前端开发不再以页面为单位,更多地采用组件化的思想,代
码结构和组织方式更加规范化,便于修改和调整;
• 缺点:
不支持低版本浏览器
首次加载页面的时候需要加载大量的静态资源,这个加载时间相对比较长。
不利于 SEO(搜索引擎)优化,单页页面,数据在前端渲染,就意味着没有
SEO。
页面导航不可用,如果一定要导航需要自行实现前进、后退。(由于是单页面不
能用浏览器的前进后退功能,所以需要自己建立堆栈管理)

10.Vuex 是什么?怎么使用?在那种场景下使用

• Vuex 是一个专为 Vue.js 应用程序开发中管理的一个模式。通过创建一个集中
的数据存储,方便程序中的所有组件进行访问。
• 使用:
在 store 下的 index.js 中 Vue.use(Vuex)
创建 store 实例
javascript
export default new Vuex.Store({
state: {},//存放数据54
mutations: {},//修改数据的值
actions: {},//执行异步操作请求数据
modules: {},//让每一个模块拥有自己的 state、mutation、action、getters, 使得
结构非常清晰,方便管理。
getters:{}//计算属性
})
• vuex 只能用于单个页面中不同组件(例如兄弟组件)的数据流通。

11.Vue 中路由跳转方式(声明式/编程式)

• 使用 this.$router 全局路由的 push()方法进行路由跳转–称之为编程式跳转;
• 使用 router-link 进行跳转路由–称之为声明式跳转

12.跨域的解决方式

• 方法 1.后端解决跨域 CORS(跨域资源共享)(在 server.js 中添加)
app.use("/", (req, res, next) => {
res.header(‘Access-Control-Allow-Origin’, ‘*’);
res.header(‘Access-Control-Allow-Headers’,
‘Content-Type,Content-Length, Authorization, Accept, X-Requested-With ,
yourHeaderFeild’);
res.header(‘Access-Control-Allow-Methods’, ‘PUT, POST, GET,
DELETE,OPTIONS’);
next()
})
• 方法 2.使用 JQuery 提供的 jsonp
o 网页中添加一个 script 元素,向服务器请求 json 数据,这种做法不受同源
策略的限制,服务器接收到请求后,把数据放在一个指定名字的回调函数里传递
回来
methods: {
getData () {
var self = this
$.ajax({
url: ‘http://f.apiplus.cn/bj11x5.json’,
type: ‘GET’,
dataType: ‘JSONP’,
success: function (res) {
self.data = res.data.slice(0, 3)
self.opencode = res.data[0].opencode.split(’,’)
}})}}
• 方法 3.proxyTable 解决跨域(项目使用 vue-cli 脚手架搭建)
在 vue.config.js 中中添写如下代码
proxy: {
‘/api’: {
target: ‘http://localhost:3000/’, //对应自己的接口
changeOrigin: true,55
ws: true,
pathRewrite: {
‘^/api’: ‘’
}}}

13.Vue 的生命周期请简述

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

14.Vue 生命周期的作用

生命周期中有多个事件钩子,让我们在控制整个 Vue 实例的过程时更容易完成指定
逻辑。每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置
数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在
这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自
己的代码的机会。(ps:生命周期钩子就是生命周期函数)例如,如果要通过某些插
件操作 DOM 节点,如想在页面渲染完后弹出广告窗,那我们最早可在 mounted
中进行。

15.DOM 渲染在哪个生命周期阶段内完成

DOM 渲染在 mounted 中就已经完成了,原因:在 created 的时候,视图中的
html 并没有渲染出来,所以此时如果直接去操作 html 的 dom 节点,一定找不到
相关的元素,而在 mounted 中,由于此时 html 已经渲染出来了,所以可以直接操
作 dom 节点。

16.Vue 路由的实现

hash 模式和 history 模式

17.Vue 路由模式 hash 和 history,简单讲一下

• hash 模式:hash 模式 url 里面永远带着#号,我们在开发当中默认使用这个模

• history 模式:history 模式没有#号,是个正常的 url 适合推广宣传。
• 区别
o url 显示
o hash:有#,很 low
o history:无#,好看
o 回车刷新
o hash:可以加载到 hash 值对应页面
o history:一般就是 404 刷新掉了
o 支持版本
hash:支持低版本浏览器和 IE 浏览器
history:HTML5 新推出的 API56

18.Vue 路由传参的两种方式,params 和 query 方式与区别

• params 方式
o 匹配参数(在路由规则中)
o 动态路径参数
o 使用动态路由匹配中的动态路径参数来进行路由配置
o 注意:动态路径参数以冒号:开头
{ path: ‘/info:aa’,name: ‘Info’,component: Info} //在 router 下的 index.js
中,aa 表示随意绑定的参数
o 发送数据(绑定参数)
o 声明式
index
o 编程式(推荐)
this.KaTeX parse error: Expected '}', got 'EOF' at end of input: …路由传入参数) {{this.route.params.id}} //在接收页面添加,id 指的是在路由规则里绑定的参数
• query 方式
o 路由参数不需要添加内容
o 发送数据(绑定参数)
o 声明式
index
//通过 name 引用路由
index(推荐)
//通过 path 引用路由
index
• 编程式
this.KaTeX parse error: Expected 'EOF', got '&' at position 27: …("/home?id=参数 1&̲name=参数 2"); //…router.push({name:‘tema’,query:{id:‘参数 1’,name:‘参数 2’}});
//通过 path 引用路由
this.KaTeX parse error: Expected '}', got 'EOF' at end of input: …路由传入参数) {{this.route.query.id}} //在接收页面添加,id 指的是在路由规则里绑定的参数
• prams 和 query 方式与区别
o 用法上的:query 可以用 name 也可以用 path 来引入, params 要用
name 来引入,接收参数都是类似的,分别是 this. r o u t e . q u e r y . n a m e 和 t h i s . route.query.name 和 this. route.query.namethis.route.params.name。57
o url 展示上:params 类似于 post,query 更加类似于我们 ajax 中 get 传
参,说的再简单一点,前者在浏览器地址栏中不显示参数,后者显示,所以
params 传值相对安全一些。

19.Vue 数据绑定的几种方式

• 普通文本绑定:双大括号法/插值表达式 {{}}或者使用 v-text 指令绑定,以文本的形
式输出
• 解释 HTML 标签的绑定:使用 v-html 绑定
• 将数据绑定到标签的属性上:使用 v-bind :属性名=“变量”来绑定

20.Vue 注册一个全局组件

• 全局组件
o 作用域:全局范围内均可使用
o 建议:组件名(字母全小写且必须包含一个连字符)
o 语法
Vue.component(‘name’,{
template:’


})
o 位置:创建实例前定义全局组件
template 的设置
template:‘html 代码’
template:’#template1’ 引用 template 内容
o 数据的定义:
data:function(){
return {a:1,b:2}
}
o 函数的定义:
methods:{
o 函数名:function(){}

21.Vue 的路由钩子函数/路由守卫有哪些

• 全局前置守卫
o 当一个导航触发时,全局前置守卫(在进入组件之前)按照创建顺序调用。
o vue-router 提供的 router.beforeEach((to,from,next)=>{})可以方便地
实现全局前置导航守卫
to:即将要进入的目标路由对象
from:当前导航正要离开的路由
next:下一步执行
router.beforeEach((to,from,next)=>{
//根据用户的登录状态限制用户是否能跳转到首页面
if(to.path=="/login"||to.path=="/register"){
next()
} else {
alert(“当前为付费页面请登录后访问!”)58
next("/login")
}})
• 全局后置钩子
o 当一个导航触发时,全局后置钩子(在进入组件之后)调用。
o vue-router 提供的 router.afterEach((to,from)=>{})实现全局后置守卫
o to:即将要进入的目标路由对象
o from:当前导航正要离开的路由
router.afterEach((to,from)=>{
console.log(“我是全局后置钩子”);
})
• 路由独享的守卫
o 与全局前置守卫相比路由独享守卫只是对当前路由进行单一控制参数和全局
前置守卫相同
o 在路由配置上直接定义 beforeEnter 进行路由独享守卫定义
{
path:’/shop’,
name:‘Shop’,
component:Shop,
beforeEnter:(to,from,next)=>{
//判断是否登录过
alert(“当前页面是 vip 页面!请登录”)
next("/login")
}}
• 组件内的守卫(只对当前组件生效)
o beforeRouteEnter 在进入组件前调用(不常用)
o 在组件中使用 beforeRouteEnter(to,from,next){}来进行进入组建前的钩子
o beforeRouteLeave 离开路由之前(常用)
o 在组件中使用 beforeRouteLeave(to,from,next){}来进行离开组件的钩子
beforeRouteLeave(to,from,next){
if(confirm(“你确定要离开吗”)){
next()
}else{
//不进行下一步(也就是不从当前路由离开)
next(false)
}}

22.Vue 中如何进行动态路由设置?有哪些方式?怎么获取传递

过来的数据?
• params 方式
o 匹配参数(在路由规则中)
o 动态路径参数
o 使用动态路由匹配中的动态路径参数来进行路由配置
o 注意:动态路径参数以冒号:开头59
{ path: ‘/info:aa’,name: ‘Info’,component: Info} //在 router 下的 index.js
中,aa 表 o 示随意绑定的参数
o 发送数据(绑定参数)
o 声明式
index
o 编程式(推荐)
this.KaTeX parse error: Expected '}', got 'EOF' at end of input: …路由传入参数) {{this.route.params.id}} //在接收页面添加,id 指的是在路由规则里绑定的参

• query 方式
o 路由参数不需要添加内容
o 发送数据(绑定参数)
o 声明式
index
//通过 name 引用路由
index(推荐)
//通过 path 引用路由
index
• 编程式
this.KaTeX parse error: Expected 'EOF', got '&' at position 27: …("/home?id=参数 1&̲name=参数 2"); //…router.push({name:‘tema’,query:{id:‘参数 1’,name:‘参数 2’}});
//通过 path 引用路由
this.KaTeX parse error: Expected '}', got 'EOF' at end of input: …路由传入参数) {{this.route.query.id}} //在接收页面添加,id 指的是在路由规则里绑定的参数

23.Elementui 中的常用组件有哪些?请简述你经常使用的并且他

们的属性有哪些?
• Container 布局容器:用于布局的容器组件,方便快速搭建页面的基本结构
o <el‐container>:外层容器。当子元素中包含 或 <el‐footer>
时,全部子元素会垂直上下排列,否则会水平左右排列
o <el‐header>:顶栏容器
o <el‐aside>:侧边栏容器
o <el‐main>:主要区域容器
o <el‐footer>:底栏容器60
• Dropdown 下拉菜单:将动作或菜单折叠到下拉菜单中
o :下拉按钮
o 下拉菜单
o 下拉项
o divided 分隔
• NavMenu 导航菜单:为网站提供导航功能的菜单
o :导航菜单
o :导航按钮
o 标题和名称 - <i class="el-icon-menu">图标 -
<span slot="title">导航二</span>导航标题
o 导航项
• Table 表格:用于展示多条结构类似的数据,可对数据进行排序、筛选、对比或
其他自定义操作
o :表格\数据绑定对象\样式
o :表格行\数据绑定对象属性\表

o align=“center”:居中
o slot-scope:作用域插槽,可以获取表格数据
o cope:代表表格数据,可以通过 scope.row 来获取表格当前行数据,scope
不是固定写法
o <el-button type=“primary” size=“mini”
o @click=“handleUpdate(scope.row)”>按钮\类型\大小\事件绑定
• Form 表单
o :表单/绑定数据模板/绑定校验
o 表单项\显示内容\数据模板
属性绑定
o 表单输入框/数据绑定
o :下拉
框/数据绑定/提示
o :下拉项/数据项
o ref 绑定校验信息
o prop 对应 rules 中对应的校验规则字段名

24.Vue-cli 中如何自定义指令

• 义指令的钩子函数
o bind:绑定指令到元素上,只执行一次
o inserted:绑定了指令的元素插入到页面中展示时调用,基本上都是操作这
个钩子函数
o update:所有组件节点更新时调用
o componentUpdated:指令所在组件的节点及其子节点全部更新完成后调用
o unbind:解除指令和元素的绑定,只执行一次
//directives:{
//自定义指令的名字:{
//自定义指令钩子函数(el){
//操作逻辑
//}
//}
//}

<template>
<div class="about">
<h1 v-aa>自定义指令</h1>
</div>
</template>
<script>
export default {
directives:{
"aa":{
// el 指向当前绑定的那个元素
inserted(el){
el.style.color="pink"
}}}}
</script>
25.Vue 中指令有哪些

• v-model 指令主要是用于表单上数据的双向绑定
• v-show 指令控制切换一个元素的显示和隐藏
• v-on 指令为 HTML 元素绑定事件监听
• v-for 指令遍历 data 中的数据,并在页面进行数据展示
• v-bind 指令绑定 HTML 元素的属性
• v-if 指令判断是否加载固定的内容
• v-else 指令必须配合 v-if 使用否则无效,当 v-if 条件不成立的时候执行
• v-else-if 指令当有一项成立时执行
• v-text 指令操作网页元素中的纯文本内容
• v-html 指令输出真正的 HTML
• v-once 指令当数据改变时,插值处的内容不会更新(会影响到该节点上的所有
属性)

26.Vue 如何定义一个过滤器

• 全局过滤器
o 位置:创建实例之前
o 语法
Vue.filter(‘过滤器名称’,function(val){//val 表示需要处理的值
return val + 4; //返回处理后的数据
})
• 局部过滤器
o 只能在当前 vue 注册内容中使用
o 位置:在 vue 实例中与 el 属性 data 属性同级定义62
o 语法
filters:{
“过滤器名字”:function(val){
return 输出内容
}}
• 过滤器的调用方法
o {{msg | 过滤器名称 }}
o 注意事项
o 定义全局过滤器,必须放在 vue 实例化前面
o 在没有冲突的前提下,过滤器可以串联

27.对 vue 中 keep-alive 的理解

• 我们不停的切换两个标签页的内容时候,会发现选择好的内容,切换路由之后会
恢复初始化,也就是说之前的状态丢失。原因是每次切换路由的时候,Vue 都
创建了一个新的组件实例。解决这个问题,我们可以用一个 元素
将其路由出口包裹起来。在切换过程中将状态保留在内存中,防止重复渲染
DOM,减少加载时间及性能消耗,提高用户体验性。
• keep-alive 属性
include(包含的组件缓存)



o exclude(排除的组件不缓存,优先级大于 include) o keep-alive 的钩子函数
(位置:和 data,methods 同级)
o activated 类型:func 触发时机:keep-alive 组件激活时使用;
export default {
data(){
return{
text:“demoa”
}},
activated() {
console.log(“进入到被 keepalive 管理的组件”);
},
deactivated() {
console.log(“离开了被 keepalive 管理的组件”);
}}
o deactivated 类型:func 触发时机:keep-alive 组件停用时调用;
o 这两个生命周期函数一定是要在使用了 keep-alive 组件之上。

28.如何让组件中的 css 在当前组件生效

为组件的 style 设置 scoped 属性,表示仅对当前组件设置样式63

29.Vue 生命周期一共几个阶段

• 它可以总共分为 8 个阶段:创建前/后,载入前/后,更新前/后,销毁前/销毁
后。
o beforeCreate:在 new 一个 vue 实例后,只有一些默认的生命周
期钩子和默认事件,其他的东西都还没创建。在 beforeCreate 生命
周期执行的时候,data 和 methods 中的数据都还没有初始化。不
能在这个阶段使用 data 中的数据和 methods 中的方法。
o created:data 和 methods 都已被初始化好了,如果要调用
methods 中的方法,或者操作 data 中的数据,最早可以在这个阶
段中操作。
o beforeMount:执行到这个钩子的时候,在内存中已经编译好了模板
了,但是还没有挂载到页面中,此时,页面还是旧的。
o mounted:执行到这个钩子的时候,就表示 Vue 实例已经初始化完
成了。此时组件脱离了创建阶段,进入到了运行阶段。如果我们想
要通过插件操作页面上的 DOM 节点,最早可以在这个阶段中进
行。
o beforeUpdate:当执行这个钩子时,页面中的显示的数据还是旧
的,data 中的数据是更新后的,页面还没有和最新的数据保持同
步。
o updated:页面显示的数据和 data 中的数据已经保持同步了,都是
最新的。
o beforeDestory:Vue 实例从运行阶段进入到了销毁阶段,这个时候
所有的 data 和 methods ,指令,过滤器 …… 都是处于可用状
态。还没有真正被销毁。
o destroyed:这个时候所有的 data 和 methods ,指令,过滤
器 ……都是处于不可用状态。组件已经被销毁了。

30.Mvvm 与 mvc 的区别

• MVVM 分为三部分:分别是 M(Model,模型层),V(View,视图
层),VM(ViewModel,V 与 M 连接的桥梁,也可以看作为控制器
MVC 的 C 层)
o M:模型层,主要负责业务数据相关
o V:视图层,负责视图相关,细分下来就是 html+css 层
o VM:V 与 M 沟通的桥梁,负责监听 M 或者 V 的修改,是实现
MVVM 双向绑定的要点;因此开发者只需关注业务逻辑,不需要手
动操作 DOM,不需要关注数据状态的同步问题,复杂的数据状态维
护完全由 MVVM 来统一管理。
• MVC 封装与业务无关的重复代码,形成框架,是模型(model)-视图
(view)-控制器(controller)的缩写。
o 模型(Model)数据的储存和处理,再传递给视图层相应或者展示64
o 视图(View)前端的数据展示
o 控制器(Controller)对数据的接收和触发事件的接收和传递
• MVC 思想:一种将数据层与视图层进行分离的设计思想
• MVVM 思想:MVVM 的一个重要特性,双向绑定,意思就是当 M 层数
据进行修改时,VM 层会监测到变化,并且通知 V 层进行相应的修改,
反之相同 mvc 和 mvvm 都是一种设计思想。主要就是 mvc 中
Controller 演变成 mvvm 中的 viewModel。mvvm 主要解决了 mvc 中
大量的 DOM 操作使页面渲染性能降低,加载速度变慢,影响用户体
验。

31.Vue 组件中的 data 为什么是函数

组件中的 data 写成一个函数,数据以函数返回值形式定义,这样每复用一
次组件,就会返回一份新的 data,类似于给每个组件实例创建一个私有的
数据空间,让各个组件实例维护各自的数据。而单纯的写成对象形式,就使
得所有组件实例共用了一份 data,就会造成一个变了全都会变的结果。

32.Vue 双向绑定的原理

• 双向绑定原理:vue 数据双向绑定是通过数据劫持结合发布者-订阅者模
式的方式来实现的
O 数据劫持:当我们访问或设置对象的属性的时候,都会触发
Object.defineProperty()函数来拦截(劫持),然后再返回(get)或
设置(set)对象的属性的值,并且当数据发生改变的时候做出反应
O 发布者-订阅者模式:其定义对象间一种一对多的依赖关系,当一个
对象的状态发生改变时,所有依赖它的对象都将得到通知

33.Vue 中组件怎么传值

• 父组件向子组件传值(正向传值)
父组件通过 props 向子组件传值,props 是你可以在组件上注册的一些自定义
特性。当一个值传递给一个 props 特性的时候,它就变成了那个组件实例的一
个属性。一个组件默认可以拥有任意数量的 props,任何值都可以传递给任何
props。
• 子组件向父组件传值(逆向传值)
O 子组件通过触发事件给父组件的方式进行传值,调用内部的
e m i t 方 法 并 传 入 事 件 的 名 字 , 来 向 父 级 组 件 触 发 一 个 事 件 O 首 先 要 有 事 件 触 发 一 个 函 数 ( 子 ) O 函 数 抛 出 自 定 义 事 件 , 携 带 着 子 组 件 的 数 据 ( 子 ) O 子 组 件 被 调 用 的 时 候 , 使 用 v − o n 事 件 调 用 父 组 件 的 一 个 函 数 , 但 是 父 组 件 函 数 不 加 ( ) ( 父 ) O 父 组 件 函 数 有 一 个 形 参 v a l , 用 来 接 收 子 组 件 抛 出 的 数 据 ( 父 ) o 兄 弟 组 件 传 值 O 创 建 一 个 事 件 总 线 , 例 如 d e m o 中 的 e v e n t B u s , 用 它 作 为 通 信 桥 梁 65 O 在 需 要 传 值 的 组 件 中 用 b u s . emit 方法并传入事件的名字,来向父级组件触发一个事件 O 首先要有事件触发一个函数(子) O 函数抛出自定义事件,携带着子组件的数据(子) O 子组件被调用的时候,使用 v-on 事件调用父组件的一个函数,但是父组件 函数不加()(父) O 父组件函数有一个形参 val,用来接收子组件抛出的数据(父) o 兄弟组件传值 O 创建一个事件总线,例如 demo 中的 eventBus,用它作为通信桥梁65 O 在需要传值的组件中用 bus. emitOOO使vonOvaloO线demoeventBus65Obus.emit 触发一个自定义事件,并传递参数(emit
前加美元符)
O 在需要接收数据的组件中用 bus.$on 监听自定义事件,并在回调函数中处
理传递过来的参数

34.Bootstrap 的原理

• 通过定义容器大小,平分 12 份(也有平分成 24 份或 32 份,但 12 份是最常
见的),再调整内外边距,最后结合媒体查询,就制作出了强大的响应式网格系
统。Bootstrap 框架中的网格系统就是将容器平分成 12 份

35.Vue 兄弟组件传值

• 传统方法:在需要传值的兄弟组件之上创建一个父组件,A 逆向给父组件,父
组件再正向给 B 组件
• 中央事件总线:在 src 下创建一个文件夹用来存放 xxx.js 文件,在其中只创建
一个新的 vue 实例,以后它就承担起了组件之间通信的桥梁了,也就是中央事
件总线。
O 创建一个事件总线,例如 demo 中的 eventBus,用它作为通信桥梁
O 在需要传值的组件中用 bus.emit 触发一个自定义事件,并传递参数(emit
前加美元符)
O 在需要接收数据的组件中用 bus.$on 监听自定义事件,并在回调函数中处
理传递过来的参数

36.如果一个组件在多个项目中使用怎么办

• 方案一:npm 发布引用
公共组件编写完成后,将其发布到 npm。发布流程如下:在注
http://www.npmjs.com 册一个账号进入 common 的控制台,输入命令 npm
login,按照提示输入刚注册的账号密码输入命令 npm publish 即可需要用该组
件的项目通过 npm install 命令将公共组件以 node_module 的方式引入。另
外,每次改动代码再次发布时,需要修改 package.json 文件中的版本号,不然
发布不成功。
• 方案二:npm link
首先进入公共包,在控制台输入 npm link 这会创建一个软连接,并保存到目录
C:\Users\Administrator\AppData\Roaming\npm\node_mo dules 下面。然后进入
使用该公共组件的项目,在控制台输入 npm link common
• 方案三:npm 本地 file 引用(推荐)
进入使用该公共项目的文件夹,在控制台输入命令:npm install …/common/ 其
中…/common/是 common 的相对路径,这里也可以输入绝对路径这样就将
common 这个工程以 node_module 的方式引入到需要使用的项目中了。可以
正常使用公共项目在 index.js 中导出的组件了。命令执行完后,package.json
里会多一条记录

37.槽口请简述

• 它是一种内容分发机制,用来混合父组件的内容与子组件自己的模板(给组件设
置一个开口,让他在调用的时候可以在里面插入数据。66
• 使用:数量相同、内容不同的时候组件使用 props,数量不同、内容也不相同的
时候使用 slot。

38.Watch 请简述

watch 可以监听模型数据,当模型数据改变的时候就会触发。watch 初始化
的时候不会运行,只有数据被改变之后才会运行。当需要在数据变化时执行
异步或开销较大的操作时,watch 这个方式是最有用的。

39.Vantui 请简述下

Vant 是一个轻量、可靠的移动端 Vue 组件库,通过 Vant,可以快速搭建出
风格统一的页面,提升开发效率。作为移动端组件库, Vant 一直将轻量化作
为核心开发理念。为了平衡日益丰富的功能和轻量化之间的矛盾关系,Vant
内部使用了很多的优化方式,包括支持组件按需加载、公共模块复用、组件
编译流程优化等。Vant 不只是提供基础的 UI 组件,为了方便开发者快速构
建移动商城,Vant 增加了许多移动商城内常用的业务组件。

40.计算属性与 watch 区别

当 watch 监听的值发生改变就会被调用,watch 可以在数据变化时做一些异步处理
或者开销大的操作;计算属性是计算依赖的值,当依赖的值发生改变才会触发。

41.mvvm 框架是什么?它和其它框架(jquery)的区别是什么?

哪些场景适合?
• 定义:MVVM 分为三部分:分别是 M(Model,模型层),V(View,视图
层),VM(ViewModel,V 与 M 连接的桥梁,也可以看作为控制器 MVC 的 C
层)M:模型层,主要负责业务数据相关,V:视图层,负责视图相关,细分下
来就是 html+css 层,VM:V 与 M 沟通的桥梁,负责监听 M 或者 V 的修
改,是实现 MVVM 双向绑定的要点;因此开发者只需关注业务逻辑,不需要手
动操作 DOM,不需要关注数据状态的同步问题,复杂的数据状态维护完全由
MVVM 来统一管理。
• 区别:vue 数据驱动,通过数据来显示视图层而不是节点操作。
• 场景:数据操作比较多的场景,更加便捷

42.Vue 首屏加载慢的原因,怎么解决的,白屏时间怎么检测,怎么解决白屏问题

• 加载慢的原因:因为路由的项目在第一次加载的时候会默认把所有的组件页面都进行渲染,如果页面多的话,加载太多,造成用户在进入项目的时候等待时间过久,出现白屏。
• 检测白屏:
• 解决:白屏时间指的是浏览器开始显示内容的时间。因此我们只需要知道是浏览器开始显示内容的时间点,即页面白屏结束时间点即可获取到页面的白屏时间。我们通常认为浏览器开始渲染 <body>标签或者解析完 <head> 标签的时刻就是页面白屏结束的时间点。因此白屏时间则可以这样计算出:67
O 可使用 Performance API 时
O 白屏时间 = firstPaint -
performance.timing.navigationStart;
O 不可使用 Performance API 时
O 白屏时间 = firstPaint - pageStartTime;
• 路由懒加载
ES 中的 import(推荐)
{
path: ‘/’,
name: ‘Home’,
//路由懒加载
component: () => import (’…/views/Home.vue’)
}
vue 异步组件懒加载-- resolve:主要是使用了
Promise.resolve()的异步机制,用 require 代替了 import, 实现按需加载
• gzip 压缩:方法一:使用 Nginx 反向代理,配置 nginx.conf 文件;方法二:
使用 node 压缩,需要使用 compression 库;
• 使用 webpack 的 externals 属性把不需要打包的库文件分离出去,减少打包后
文件的大小
• 使用 vue 的服务端渲染(ssr) ssr 优点是 seo 优化,以及加快首屏加载

43.Vue 双数据绑定过程中,这边儿数据改变了怎么通知另一边改变

使用 Object.defineProperty()来定义属性的 set 函数,属性被赋值的时候,修改Input 的 value 值,然后监听 input 的 keyup 事件,修改对象的属性值,即可实现这样的一个简单的数据双向绑定。

44.Vuex 流程

• 在 vue 组件里面,通过 this.$store.dispatch 来触发 actions 执行异步操作获取
数据。
• 然后再通过 store.commit 来触发 mutations 来修改数据。
• mutations 接收到 commit 的请求,就会自动修改 state(数据中心里面的数据
状态)里面的数据。
• 最后由 store 触发每一个调用它的组件进行更新

45.Vuex 怎么请求异步数据

• 在 store 文件中引入 import axios from “axios”
• 通过事件触发 active
<button @click=“fun()”>点我发送请求
export default {
methods: {
fun(){
this.$store.dispatch(“ajaxdemo”)68
}},}
• 创建 actions 并进行异步请求,并且调用 Mutations 修改 state 数据
mutations: {
uparr(state, payload) {
state.arr = payload
}},
actions: {
ajaxdemo(store) {
axios({
url:“http://api.artgoer.cn:8084/artgoer/api/v1/user/324380/v3/topic/top
icHomeByLabel?pageIndex=1&token=b544cd63-6d42-46fe-a96c-3cf96b
ae3113&topicId=62187”,
method: “get”
}).then((ok) => {
console.log(ok);
store.commit(“uparr”, ok.data.data.commentList)

46.Vuex 中 action 如何提交给 mutation 的

vuex 的 acions 创建一个方法进行异步操作,他的形参就是 store 对象,把请求来
的数据通过 commit()传递给 mutations
actions: {
axioslink(store) {
demoapi.demo().then((ok) => {
console.log(ok.data.data.commentList);
// 把请求来的数据给 mutations 进行 state 的修改
store.commit(“uparr”, ok.data.data.commentList)
})}}

47.Route 与 router 区别

• $router 是 VueRouter 的一个对象,router 的实例对象,这个对象是一个全局
的对象,他包含了所有的路由包含了许多关键的对象和属性。举例:history 对

• $route 是一个跳转的路由对象,每一个路由都会有一个 route 对象,是一个局
部的对象,可以获取对应的 name,path,params,query 等

48.vuex 有哪几种状态和属性

有五种,分别是 State , Getter , Mutation , Action , Module (就是 mapAction)

49.vuex 的 State 特性是?

• state 就是存放数据的地方,类似一个仓库 , 特性就是当 mutation 修改了
state 的数据的时候,他会动态的去修改所有的调用这个变量的所有组件里面的
值(若是 store 中的数据发生改变,依赖这个数据的组件也会发生更新)
• state:vuex 中的数据源 state,我们需要保存的数据就保存在这里(用来存
储数据)
O 使用:

  1. 可以使用KaTeX parse error: Expected '}', got 'EOF' at end of input: …e.xx 调用 {{this.store.state.name}}
  2. 使用数据的组件中使用计算属性调用 this.KaTeX parse error: Expected '}', got 'EOF' at end of input: …){ return this.store.state.obj
    }}
    O state 里面存放的数据是响应式的,Vue 组件从 store 中读取数据,若是
    store 中的数据发生改变,依赖这个数据的组件也会发生更新
    O 它通过 mapState 把全局的 state 和 getters 映射到当前组件的 computed
    计算属性中
50.vuex 的 Getter 特性是?

• getters:相当于之前组件中学习的计算属性,getters 属性主要是对于 state 中数
据的一种过滤
O 使用场景:在项目开发中,有时候希望对 state 中的某个属性在多个组件中
展示出不同状态
O 与使用 state 相同在组件中的计算属性当中使用 this.$store.getters.xxx 来
进行调用
O 语法

getters: {
nameone(state) {
return state.name.toUpperCase()
},
nametwo(state) {
return state.name.substr(0, 2)
}}
<p>{{this.$store.getters.nameone}}</p>
<p>{{this.$store.getters.nametwo}}</p>
51.vuex 的 Mutation 特性是?

• mutations:里面装着一些改变数据方法的集合,就是把处理数据逻辑方法全部放
在 mutations 里面,当触发事件的时候想改变 state 数据的时候使用
mutations(在 vuex 中如果想进行数据的修改,必须在 mutations 中进行操
作)
O 语法
mutations: {
upone(state) { //创建一个方法,且必须有一个形参,对应要修改的那个
数据 state
state.name = “haha”
}}
O 不能直接调用一个 mutations 中的处理函数要使用 this.KaTeX parse error: Expected '}', got 'EOF' at end of input: …ommit()函数 this.store.commit(“upone”)
}}
O 之前的只是一个简单的修改 state 中的属性,在实际项目中往往会有值传递
给 mutations,给 store.commit 传一个附加参数,他就叫做 mutation 的载
荷,一般使用 payload
mutations: {
uptwo(state, payload) {
state.name = payload
}}
methods:{ funb(){
// this. s t o r e . c o m m i t ( " u p t w o " , 把 要 传 递 给 m u t a t i o n s 的 数 据 放 到 这 里 ) t h i s . store.commit("uptwo",把要传递给 mutations 的数据放到这里) this. store.commit("uptwo",mutations)this.store.commit(“uptwo”,this.inputval)
}}
O 如果要传多个参数,可以传递一个对象
this.$store.commit(‘add’,{‘name’:‘lxg’,‘num’:20…})

52.vuex 的 actions 特性是

actions:进行异步操作(异步请求)
语法

actions: {
axioslink(store) {
demoapi.demo().then((ok) => {
console.log(ok.data.data.commentList);
// 把请求来的数据给 mutations 进行 state 的修改
store.commit("uparr", ok.data.data.commentList)
})}},
methods:{ func(){
//调用 actions 来进行异步请求
this.$store.dispatch("axioslink")
}
} mutations: { uparr(state, payload) { state.arr = payload
}}
53.Vuex 是什么?怎么使用?在那种场景下使用

• Vuex 是一个专为 Vue.js 应用程序开发中管理的一个模式。通过创建一个集中
的数据存储,方便程序中的所有组件进行访问。
• 使用:
在 store 下的 index.js 中 Vue.use(Vuex)
创建 store 实例
javascript71
export default new Vuex.Store({
state: {},
mutations: {},
actions: {},
modules: {}
})
• vuex 只能用于单个页面中不同组件(例如兄弟组件)的数据流通。

54.vuex 的优势

• 解决了非父子组件的消息传递(将数据存放在 state 中)
o 减少了 AJAX 请求次数,有些情景可以直接从内存中的 state 获取
• 双向绑定,使用 commit 修改一处状态后,所有引用的地方自动更新,不需要
传值

55.Vue 路由懒加载(按需加载路由)

• 懒加载简单来说就是延迟加载或按需加载,即在需要的时候进行加载。为给客户
更好的客户体验,首屏组件加载速度更快,解决白屏问题,当构建的项目比较大
的时候,懒加载可以分割代码块,提高页面的初始加载效率。
• 使用
component
O vue 异步组件懒加载:主要是使用了 Promise.resolve()的异步机制,用
require 代替了 import,实现按需加载:
resolve=>(require([“引用的组件路径”],
O ES 中的 import(推荐):const HelloWorld = ()=>import(’
需要加载的模块地址’)

56.v-for 与 v-if 优先级

首先不要把 v-if 与 v-for 用在同一个元素上,原因:v-for 比 v-if 优先,如果每一
次都需要遍历整个数组,将会影响速度,尤其是当之需要渲染很小一部分的时候,vfor 比 v-if 具有更高的优先级

57.为什么要对 element-ui 进行二次封装

• element-ui 组件的部分样式不满足当前项目的需求 element-ui 组件的样式是固
定的,比如我们常用的那些组件, table,button,icon,tab 等等。当我们需
要的样式和 element 组件有偏差的时候,我们可以通过针对 element 组件进行
二次封装,然后通过 Vue.component()方法,定义到全局, 来解决我们当前的
项目需求
• element-ui 组件出现问题的时候,我们有中间键支持,不至于整个项目崩塌。
其实这种现象是常有发生的,比如组件由最开始的开源的,突然收费了(虽然我
相信 ele 团队不会的)。或者 element 组件库的开发团队停止了维护。组件的
二次封装都是有意义的。我们可以手写一个类似的组件,或者引入其它组件,使
我们的项目,能够正常使用。综上所述,如果我们基于 element 做的项目,因
为 element 出现了问题,组件的二次封装,可以有效的防止项目崩塌。72

58.为什么修改了 data 中的数据,但是视图没有更新?

• vue 的 data 里边声明或者已经赋值过的对象或者数组(数组里边的值是对象)
时,向对象中添加新的属性,如果更新此属性的值,是不会更新视图的。根据官
方文档:定义如果在实例创建之后添加新的属性到实例上,它不会触发视图更
新。原因:当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,
Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部
转为 gettertter。
• 受现代 JavaScript 的限制 (以及废弃 Object.observe),Vue 不能检测到对象属
性的添加或删除。由于 Vue 会在初始化实例时对属性执行 gettertter 转化过
程,所以属性必须在 data 对象上存在才能让 Vue 转换它,这样才能让它是响
应的。解决方案:可以使用$set()方法,既可以新增属性,又可以触发视图更新

59.什么是 Vue.nextTick 以及它的应用场景

为了在数据变化之后等待 Vue 完成更新 DOM 可以在数据变化之后立即使用
Vue.nextTick(callback)。这样回调函数在 DOM 更新完成后就会调用。在下次 DOM
更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后
的 DOM。
在 Vue 生命周期的 created()钩子函数进行 DOM 操作一定要放到 Vue.nextTick()的
回调函数中。 created()钩子函数执行的时候,DOM 其实并未进行任何渲染。所以
此处一定要将 DOM 操作的 js 代码放进 Vue.nextTick()的回调函数中。在数据变化
后要执行的某个操作,而这个操作需要使用随数据改变而改变的 DOM 结构的时
候,这个操作都应该放进 Vue.nextTick()的回调函数中

60.Vue 项目如何性能优化

• 懒加载
路由懒加载就是按需加载,不会让项目刚开始运行速度就很慢,能大大的优化用
户体验图片懒加载

<img v-lazy="1.jpg">

• 代码优化
O 封装组件和函数,提高代码复用率
O 减少本地存储的使用
O 减少 watch 使用:watch 监听大量状态时会让浏览器出现卡顿
O 使用 v-if 代替 v-show :用户体验优化
O 添加 loading:当用户需要等待时间较长时,必须添加等待 loading
O 路由逻辑
O 样式统一
O 滚动组件的使用

61.v-show 和 v-if 的区别

• 相同点:v-show 和 v-if 都能控制元素的显示和隐藏
• 实现本质方法不同
O v-show 本质就是通过设置 css 中的 display 设置为 none,控制隐藏
O v-if 是动态的向 DOM 树内添加或者删除 DOM 元素73
• 性能
O v-if 有更高的切换消耗(安全性高)
O v-show 有更高的初始化的渲染消耗(对安全性无要求选择)
• 总结:如果要频繁切换某节点时,使用 v-show(无论 true 或者 false 初始都
会进行渲染,此后通过 css 来控制显示隐藏,因此切换开销比较小,初始开销
较大),如果不需要频繁切换某节点时,使用 v-if(因为懒加载,初始为 false
时,不会渲染,但是因为它是通过添加和删除 dom 元素来控制显示和隐藏的,
因此初始渲染开销较小,切换开销比较大)

React

1.请简述你对 react 的理解

• 定义:React 起源于 Facebook;React 是一个用于构建用户界面的 javascript
库。React 拥有较高的性能,代码逻辑非常简单,越来越多的人已开始关注和使
用它
• 特点
O 声明式设计 −React 采用声明范式,可以轻松描述应用。(开发者只需要声
明显示内容,react 就会自动完成)
O 高效 −React 通过对 DOM 的模拟,最大限度地减少与 DOM 的交互。
O 灵活 −React 可以与已知的库或框架很好地配合组件 − 通过 React 构建
组件,使得代码更加容易得到复用,能够很好的应用在大项目的开发中。
(把页面的功能拆分成小模块–每个小模块就是组件)
O 单向数据流 -React 是单向数据流,数据主要从父节点传递到子节点(通过
props)。如果顶层(父级)的某个 props 改变了,React 会重渲染所有的
子节点
• 核心:React 的核心就是组件:组件的设计目的是提高代码复用率,降低测试难
度和代码的复杂程度
• 优点
O 它提高了应用的性能
O 可以方便地在客户端和服务器端使用
O 由于 JSX,代码的可读性很好
O React 很容易与 Meteor,Angular 等其他框架集成
O 使用 React,编写 UI 测试用例变得非常容易
• React 推荐在 React 中使用 JSX 来描述用户界面。当遇到<>,JSX 就当 HTML
解析,遇到{}就当 JavaScript 解析
State 与 props 区别
state:
O state 就是状态,它只是用来控制这个组件本身自己的状态,我们可以用 s
tate 来完成对行为的控制、数据的更新、界面的渲染,由于组件不能修改传
入的 props,所以需要记录自身的数据变化
O 要想修改 state 中的数据,可以使用 setState(),setState() 是异步的会自动
触发 render 函数的重新渲染
props:
O props 是组件对外的接口,使用 props 就可以从外部向组件内部进行数据
传递完成父组件传值给子组件
O props 对于使用它的组件来说,是只读的。一旦赋值不能修改。也就是说
props 的值是不可变的,只能在渲染的时候传入,无法动态赋值。75

3.组件之间的数据传递

• 正向传值–使用 props
父组件发送数据在子组件中使用 this.props.xxx 来接收数据,如果父级的某个
props 改变了,React 会重渲染所有的子节点
• 逆向传值—函数传值
O 子组件通过事件调用函数传递
O 在子组件中使用 this.props.调用的函数名绑定发送数据
O 在父组件中进行函数传递
O 父组件中必须要有一个形参用来接收子组件发送过来的数据
• 同级传值—pubsub-js 在第一个要传值的组件中进行数据抛出 PubSub.publish("
事件名",“数据”)
O 在第二个要接收数据的组件中接收 PubSub.subscribe(“监听的事件”,(事件,数
据)=>{})
• 跨组件传值—context
O context 上下文对象,无需为每一层组件手动添加 props,就能在组件数间
进行数据传递的方法
O 使用 createContext()方法提供了两个对象 - Provider 对象生产者---->用来
生产数据 - Consumer 对象消费者---->用来使用数据

4.Vue 与 react 区别

• 相似之处
O 他们都是 JavaScript 的框架,专注于创造前端的数据应用。
不同于早期的 JavaScript 框架“功能齐全”,Reat 与 Vue 只有框架的骨架,
其他的功能如路由、状态管理等是框架分离的组件。
O 都使用了虚拟 DOM,Virtual DOM 是一个映射真实 DOM 的 JavaScript
对象,如果需要改变任何元素的状态,那么是先在 Virtual DOM 上进行改
变,而不是直接改变真实的 DOM。当有变化产生时,一个新的 Virtual
DOM 对象会被创建并计算新旧 Virtual DOM 之间的差别,之后这些差别会
应用在真实的 DOM 上。
O 组件化 React 与 Vue 都鼓励组件化应用
O Props React 和 Vue 都有’props’的概念,props 在组件中是一个特殊的属
性,允许父组件往子组件传送数据。
O 构建工具 React 和 Vue 都有自己的构建工具,你可以使用它快速搭建开发
环境。
• 区别
O 数据
O vue:双向数据绑定和单向数据流。双向数据绑定: DOM 元素绑定的
data 值,当发生改变后,vue 的响应式机制会自动监听 data 的变化重新
渲染。单向数据流:当父组件给子组件传递数据的时候,子组件只可以读取
而不能修改数据。可以用 watch 监听数据的更改,再赋给父组件的变量。
O react:单向数据流。DOM 元素依赖于 state,但改变 state 不会改变渲染
好的 DOM,通过 setState() 才能重新渲染。父组件传值到子组件,如果顶
级的 props 变了,会重新渲染所有的子组件。76
O 虚拟 DOM
O vue:计算出虚拟 DOM 的差异,在渲染的过程中跟踪每个组件的依赖关
系,不会重新渲染整个组件树
O react:当应用的状态改变时,重新渲染全部子组件,可以通过 s
houldComponentUpdate 生命周期进行优化
O 模板和 jsx:
O vue:具有单文件组件,可以把 html、css、js 写在一个 vue 文件里----
MVVM 框架
O react:依赖于 jsx,在 JavaScript 中创建 DOM—视图层框架

5.请简述虚拟 dom 与 diff 算法

• 虚拟 dom:虚拟 dom 相当于在 js 和真实 dom 中间加了一个缓存。基于
React 进行开发时所有的 DOM 构造都是通过虚拟 DOM 进行,每当数据变化
时,React 都首先重新构建整个 DOM 树(减少页面更新次数),然后 React 将
当前整个 DOM 树和上一次的 DOM 树进行对比(DOM Diff 算法-最小化页面重
绘),得到 DOM 结构的区别,然后仅仅将需要变化的部分进行实际的浏览器
DOM 更新
• diff 算法:diff 算法是调和的具体实现,将 Virtual(虚拟)DOM 树转换成
actual(真实)DOM 树的最少操作的过程称为调和,diff 算法的作用计算出虚拟
DOM 中真正变化的部分,并只针对该部分进行原生 DOM 操作,而非重新渲
染整个页面

6.你对组件的理解

React 的核心就是组件:组件的设计目的是提高代码复用率,降低测试难度和代码的
复杂程度。
o 提高代码复用率:组件将数据和逻辑进行封装。
o 降低测试难度:组件高内聚低耦合(各个元素高集成度低关联性),很容易对单
个组件进行测试。
o 代码的复杂程度:直观的语法,可以极大提高可读性。

7.调用 setState 之后发生了什么?

在代码中调用 setState 函数之后,React 会将传入的参数对象与组件当前的状态合
并,然后触发所谓的调和过程(Reconciliation)。经过调和过程,React 会以相对高效
的方式根据新的状态构建 React 元素树并且着手重新渲染整个 UI 界面。在 React
得到元素树之后,React 会自动计算出新的树与老树的节点偏差,然后根据差异对界
面进行最小化重渲染。在差异计算算法中,React 能够相对精确地知道哪些位置发生
了改变以及应该如何改变,这就保证了按需更新,而不是全部重新渲染。

8.react 生命周期函数

• React 生命周期分为三种状态:挂载阶段、更新阶段、卸载阶段
o 始化阶段:
o getDefaultProps:获取实例的默认属性
o getInitialState:获取每个实例的初始化状态
o componentWillMount: 组件即将被装载、渲染到页面上77
o render:组件在这里生成虚拟的 DOM 节点
o componentDidMount:组件真正在被装载之后
• 运行中状态:
o omponentWillReceiveProps:组件将要接收到属性的时候调用
o shouldComponentUpdate:组件接受到新属性或者新状态的时候(可以返回 f
alse,接收数据后不更新,阻止 render 调用,后面的函数不会被继续执行
了)
o componentWillUpdate:组件即将更新不能修改属性和状态 o render:组件重
新描绘
o componentDidUpdate:组件已经更新
• 销毁阶段:
o componentWillUnmount:组件即将销毁

9.为什么虚拟 dom 会提高性能?(必考)

• 虚拟 dom 相当于在 js 和真实 dom 中间加了一个缓存,利用 dom 的 diff 算
法避免了没有必要的 dom 操作,从而提高性能。
• 用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的
DOM 树,插到文档当中,当状态变更的时候,重新构造一棵新的对象树。然后
用新的树和旧的树进行比较,记录两棵树差异把 2 所记录的差异应用到步骤 1
所构建的真正的 DOM 树上,视图就更新了。

10.shouldComponentUpdate 是做什么的

判定组件是否要更新 html 主要用于性能优化(部分更新)唯一用于控制组件重新渲染
的生命周期,由于在 react 中,setState 以后, state 发生变化,组件会进入重新
渲染的流程,在这里 return false 可以阻止组件的更新

11.react diff 原理

• 把树形结构按照层级分解,只比较同级元素。
• 给列表结构的每个单元添加唯一的 key 属性,方便比较。
• React 只会匹配相同 class 的 component(这里面的 class 指的是组件的名字)
• 合并操作,调用 component 的 setstate 方法的时候, React 将其标记为 dirty
到每一个事件循环结束, React 检查所有标记 dirty 的 component 重新绘制
• 选择性子树渲染。开发人员可以重写 shouldComponentUpdate 提高 diff 的性
能。

12.何为受控组件

React 负责渲染表单的组件,同时仍然控制用户后续输入时所发生的变化,值是来自
于 state 控制的输入表单元素称为“受控组件”

13.(组件的)状态(state)和属性(props)之间有何不同

• State 是一种数据结构,用于组件挂载时所需数据的默认值。State 可能会随着
时间的推移而发生突变,但多数时候为用户事件行为的结果。
• Props(properties 的简写)则是组件的配置。props 由父组件传递给子组件,并且
就子组件而言,props 是不可变的(immutable)。组件不能改变自身的 props,
但是可以把其子组件的 props 放在一起(统一管理)。Props 也不仅仅是数据-回
调函数也可以通过 props 传递。

14.调用 super(props) 的目的是什么

super 调用父类的构造方法,此时组件才有自己的 this,在组件的全局中都可以使用
this 关键字,否则如果只是 constructor 而不执行 super() 那么以后的 this 都是错
的,super()继承父组件的 this

15.React 中构建组件的方式

• 函数组件/无状态组件

<script type="text/babel">

// 函数名使用大驼峰命名规范

function MyCom(){
return (
<div>
<h1>我是一个 react 无状态组件</h1>
</div>
)}
ReactDOM.render(<MyCom/>,document.getElementById("demodiv"))
</script>

• class 类组件
一个组件类必须要实现一个 render 方法。这个方法必须要返回一个 jsx 元素。
必须要用一个外层的 jsx 元素把所有的内容包裹起来,返回并列的多个元素需
要有个父元素包裹

<script type="text/babel">
class MyCom extends React.Component{
render(){
return (
<div>
<h1>我是一个 react 类组件</h1>
</div>
)}}
class Fu extends React.Component{
render(){
return (
<div>
<MyCom/>
<MyCom/>
<MyCom/>
</div>
)}}
ReactDOM.render(<Fu/>,document.getElementById("demodiv")
)
</script>
16.什么是高阶组件 HOC

• 参数是组件同时返回值也是组件
• 作用:封装可以在组件中高度复用的代码
• 高阶组件 HOC 接收 props
o 如果组件是被高阶组件导出的那么在正向传值的时候需要在高阶组件中进行
传递
• 反向继承
o 作用:渲染劫持,按照条件选择性的给用户输出想要的内容
o super.render()是调用父类的 render()渲染

17.什么是 Hook

• 作用:让无状态组件可以使用状态和 react 的其他特性
• useState() React 提供最基础、最常用的 Hook,主要用来定义和管理本地状态
• useRef() 获取 DOM 节点
o seEffect() 无状态组件使用生命周期
• useReducer() 防止 state 里面的数据操作太复杂,减少 state 的数据操作复杂

18.无状态组件的特点

• 组件不会被实例化,整体渲染性能得到提升
• 因为组件被精简成一个 render 方法的函数来实现的,无状态组件就不会在有组
件实例化的过程,无实例化过程也就不需要分配多余的内存,从而性能得到一定
的提升。
• 组件不能访问 this 对象
• 无状态组件由于没有实例化过程,所以无法访问组件 this 中的对象,若想访问
this 就不能使用这种形式来创建组件
o 件无法访问生命周期的方法

19.三种请求方式的区别(ajax、axios、fetch)

• 传统 Ajax 指的是 XMLHttpRequest(XHR),最早出现的发送后端请求技术,隶
属于原始 js 中,核心使用 XMLHttpRequest 对象,多个请求之间如果有先后关
系的话,就会出现回调地狱。JQuery ajax 是对原生 XHR 的封装
• axios 是一个基于 Promise ,本质上也是对原生 XHR 的封装,只不过它是
Promise 的实现版本,符合最新的 ES 规范,
• fetch 不是 ajax 的进一步封装,而是原生 js,没有使用 XMLHttpRequest 对
象。

20.什么是 React 状态提升

• 定义:多个组件需要反映相同的变化数据,提升到它们最近的父组件上,在父组
件上改变这个状态然后通过 props 分发给子组件
• 使用场景:两个子组件需要利用到对方的状态的话,那么这个时候我们就需要使
用到状态提升80

21.什么是 Webpack

WebPack 可以看做是模块打包机:它做的事情是,分析你的项目结构,找到
JavaScript 模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript
等),并将其转换和打包为合适的格式供浏览器使用。

22.Webpack 的组成

webpack 分成四个部分,其中最核心的就是入口(entry)和出口(output),当然在入口
和出口配置的同时我们还需要一些加载器(Loaders)和插件(plugin),这就是我们所谓
的 webpack 配置文件。这个配置文件我们习惯把其命名为 webpack.config.js ,还
有 webpackfile.js

23.Webpack 打包原理

webpack 是把项目当作一个整体,通过给定的一个主文件, webpack 将从这个主
文件开始找到你项目当中的所有依赖的文件,使用 loaders 来处理它们,最后打包
成一个或多个浏览器可识别的 js 文件

24.webpack 的工作过程

• 解析配置参数,合并从(npm install 类似的命令)和 webpack.config.js 文件的配置
信息,输出最终的配置信息;
o 册配置中的插件,做出对应的反应;
• 解析配置文件中的 entry 入口文件,并找出每个文件依赖的文件,递归下去;
• 在递归每个文件的过程中,根据文件类型和配置文件中的 loader 找出对应的
loader 对文件进行转换;
• 递归结束后得到每个文件最终的结果,根据 entry 配置生成代码;

25.什么是 TypeScript

• TypeScript 是一种由微软开发的自由和开源的编程语言。它是 JavaScript 的一个
超集,而且本质上 TypeScript 扩展了 JavaScript 的语法解决 JavaScript 的“痛
点”:弱类型和没有命名空间,导致很难模块化
• 优点:开源、简单、兼容性好
• 与 js 相比的优势
o TypeScript 工具使重构更变的容易、快捷。
o TypeScript 引入了 JavaScript 中没有的“类”概念。
o TypeScript 中引入了模块的概念,可以把声明、数据、函数和类封装在模块
中类型安全功能能在编码期间检测错误,这为开发人员创建了一个更高效的
编码和调试过程。

26.React 中 Keys 的作用是什么

Keys 可以在 DOM 中的某些元素被增加或删除的时候帮助 React 识别哪些元素发生
了变化。因此要给数组中的每一个元素赋予一个确定的标识。一个元素的 key 最好
是这个元素在列表中拥有的一个独一无二的字符串81

27.React 事件处理中如何修改 this 指向?

• 通过 bind 方法进行原地绑定,从而改变 this 指向
funa(){
this.setState({
text:“我变了 1”
})}
方式 1:通过 bind 方法进行原地绑定,
从而改变 this 指向
• 通过创建箭头函数
funb=()=>{
this.setState({
text:“我变了 2”
})}
方式 2:通过创建箭头函数
• 在 constructor 中提前对事件进行绑定
func(){
this.setState({
text:“我变了 3”})}
方式 3:在 constructor 中提前对事件进行绑定

• 将事件调用的写法改为箭头函数的形式
fund(){
this.setState({
text:“我变了 4”})}
<button onClick={(e)=>{this.funb(“参数 1”,“参数 2”,e)}}>通过箭头函数传递

28.React 如何实现组件传值

• 正向传值–使用 props(父发送数据,子接收数据)
• 逆向传值—函数传值
o 子组件通过事件调用函数传递
o 在子组件中使用 this.props.调用的函数名绑定发送数据
o 在父组件中进行函数传递
o 同级传值—pubsub-js
o 在第一个要传值的组件中进行数据抛出 PubSub.publish(" 事件名",“数据”)
o 在第二个要接收数据的组件中接收 PubSub.subscribe(“监听的事件”,(事件,数
据)=>{})
• 跨组件传值—context
o 在 src 下创建文件夹与.jsx 文件用来容纳 context 对象
o 创建内容并且引用 createContext 对象
o 在根组件 index.js 中使用
o 创建 Provider 生产者与 Consumer 消费者对象并且创建数据
o 在需要的组件中进行使


  1. a-zA-Z ↩︎

  2. a-zA-Z ↩︎

  • 3
    点赞
  • 0
    评论
  • 6
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值