前端面试题套路–终极版(Vue、JavaScript)_盂希_前端开发者

前言

面试题是永远都准备不完的!!!!!

 

前端常见的一些问题

1.前端性能优化手段?

1. 尽可能使用雪碧图

2. 使用字体图标代替图片

3. 对htmlcssjs 文件进行压缩

4. 模块按需加载

5. 资源懒加载与资源预加载

6. 避免使用层级较深的选择器及减少DOM深度

1. 尽可能使用雪碧图

2. 使用字体图标代替图片

3. 对htmlcssjs 文件进行压缩

4. 模块按需加载

5. 资源懒加载与资源预加载

6. 避免使用层级较深的选择器及减少DOM深度


2.单页面应用和多页面应用的区别及优缺点?

单页面的概念: 单页面应用(SPA),其实就是指只有一个主页面的应用,类似前端现在的三大框架,React.vue,angular 浏览器一开始要加载所有必须的html,js css。所有的页面内容都包含在这个所谓的主页面中。

单页面的原理:利用js感知到URL的变化,通过这一点,可以用js动态的将当前的页面内容清除掉,然后将下一个页面的内容挂载到当前的页面上。页面每次切换跳转时,并不需要做html文件的请求,这样就节约了很多http发送延迟,我们在切换页面的时候速度很快。

单页面的优点:

1. 加载速度快,用户体验好,内容的改变不需要重新加载整个页面,基于这一点SPA对服务器压力较小。

2. 前后端分离

3. 页面视觉效果良好

1. 加载速度快,用户体验好,内容的改变不需要重新加载整个页面,基于这一点SPA对服务器压力较小。

2. 前后端分离

3. 页面视觉效果良好

单页面的缺点:

1. 不利于SEO(搜索引擎优化)

2. 页面初次加载时比较慢

3. 页面复杂度提高很多

1. 不利于SEO(搜索引擎优化)

2. 页面初次加载时比较慢

3. 页面复杂度提高很多

多页面的概念: 多页面(MPA),就是指一个应用中有多个页面,页面跳转时是整个页面都刷新,每次都请求一个新的页面。

多页面的优点:首屏加载时间快,SEO效果好

多页面的缺点:页面切换慢,每次切换页面都需要选择性的重新加载公共资源


3. var,let,const的区别?

var:var的作用域是函数作用域,在一个函数内利用var声明一个变量,则这个函数只在这个函数内有效,存在变量提升。

let :作用域是块级作用域 不存在变量提升,不允许重复定义。

const :一般用来声明常量,且声明的常量是不允许被改变的,声明的时候就赋值,不存在变量提升,不允许重复定义。

var:var的作用域是函数作用域,在一个函数内利用var声明一个变量,则这个函数只在这个函数内有效,存在变量提升。

let :作用域是块级作用域 不存在变量提升,不允许重复定义。

const :一般用来声明常量,且声明的常量是不允许被改变的,声明的时候就赋值,不存在变量提升,不允许重复定义。


4. 箭头函数和普通函数的区别?

箭头函数:

1. this指向:箭头函数指向 定义时所在的作用域中的this指向

2. 箭头函数作为匿名函数,是不能作为构造函数的,不能使用new

3. 箭头函数不能换行

1. this指向:箭头函数指向 定义时所在的作用域中的this指向

2. 箭头函数作为匿名函数,是不能作为构造函数的,不能使用new

3. 箭头函数不能换行

普通函数:

1. this指向:谁调用就指向谁

1. this指向:谁调用就指向谁


5. 流式布局和响应式布局?

流式布局: 使用非固定像素来定义网页内容,也就是百分比布局,通过盒子的宽度设置成百分比来根据屏幕的宽度来进 行伸缩,不受固定像素的限制,内容向两侧填充。

响应式布局: 利用CSS3 中的 Media Query(媒介查询),通过查询 screen 的宽度来指定某个宽度区间的网页布局。

流式布局: 使用非固定像素来定义网页内容,也就是百分比布局,通过盒子的宽度设置成百分比来根据屏幕的宽度来进 行伸缩,不受固定像素的限制,内容向两侧填充。

响应式布局: 利用CSS3 中的 Media Query(媒介查询),通过查询 screen 的宽度来指定某个宽度区间的网页布局。


6. css优先级算法?

!important>内联>ID选择器>class选择器>元素选择器>通配符选择器>继承>浏览器默认属性

!important>内联>ID选择器>class选择器>元素选择器>通配符选择器>继承>浏览器默认属性


7. null和undefined的区别?

undefined:类型只有一个,即undefined,当声明变量还未被初始化时就是undefined

null:类型也只有一个值,即null。null用来表示尚未存在的对象,常用来表示函数企图返回一个不存在的对象

undefined:类型只有一个,即undefined,当声明变量还未被初始化时就是undefined

null:类型也只有一个值,即null。null用来表示尚未存在的对象,常用来表示函数企图返回一个不存在的对象


8. http和https的区别?

https:是以安全为目标的HTTP通道,简单讲是HTTP的安全版本,通过SSL加密。

http:超文本传输协议。是一个客服端和服务器端请求和应答的标准(tcp),使浏览器更加高效,使网络传输减少。

https:是以安全为目标的HTTP通道,简单讲是HTTP的安全版本,通过SSL加密。

http:超文本传输协议。是一个客服端和服务器端请求和应答的标准(tcp),使浏览器更加高效,使网络传输减少。


9. ajax的理解?

ajax的原理:原理:相当于在用户和服务器之间加一个中间层(ajax引擎),使用户操作与服务器响应异步化。

ajax的优点:在不刷新整个页面的前提下与服务器通信维护数据。不会导致页面的重载可以把前端服务器的任务转接到客服端来处理,减轻服务器负担,节省宽带。

ajax的劣势:不支持back。对搜索引擎的支持比较弱;不容易调试 怎么解决呢?通过location.hash值来解决Ajax过程中导致的浏览器前进后退按键失效,解决以前被人常遇到的重复加载的问题。主要比较前后的hash值,看其是否相等,在判断是否触发ajax。

ajax的原理:原理:相当于在用户和服务器之间加一个中间层(ajax引擎),使用户操作与服务器响应异步化。

ajax的优点:在不刷新整个页面的前提下与服务器通信维护数据。不会导致页面的重载可以把前端服务器的任务转接到客服端来处理,减轻服务器负担,节省宽带。

ajax的劣势:不支持back。对搜索引擎的支持比较弱;不容易调试 怎么解决呢?通过location.hash值来解决Ajax过程中导致的浏览器前进后退按键失效,解决以前被人常遇到的重复加载的问题。主要比较前后的hash值,看其是否相等,在判断是否触发ajax。


10. Html5新增哪些新特性?移出了哪些元素 ?

H5新增特性:

1. 用于绘画的canvas元素

2. 用于媒介回放的video和audio元素

3. 对本地离线存储的更好的支持(本地存储)

4.新增标签: header    footer   article  nav   section

5.新增表单控件:calender  date  time   email   url  search

1. 用于绘画的canvas元素

2. 用于媒介回放的video和audio元素

3. 对本地离线存储的更好的支持(本地存储)

4.新增标签: header    footer   article  nav   section

5.新增表单控件:calender  date  time   email   url  search

移除的元素:basefont   big   center  font  s  strike  tt  u


11.移动端点透问题,如何解决?

问题:点透问题出现的原因就是移动端click事件300ms延迟问题,当点击上层元素时,先触发touchstart事件,然后在300ms后会触发click事件,而此时上层元素已经消失,所以下边的元素会触发click事件,这就是点透问题。

解决方法:

1. 使用一个透明遮罩,屏蔽所有事件,然后400ms(对于IOS来说是个理想值)后自动屏蔽。

2. touchstart换成touchend,因为触发touchend需要200ms所以可以把触发时间这个原理问题解决掉。

3. zepto最新版已经修复了这个问题,或者使用fastclick等通用库。

4. 直接使用click,不考虑延迟。

5.下层避开click事件,如a链接改为span等标签,使用js跳转页面。

1. 使用一个透明遮罩,屏蔽所有事件,然后400ms(对于IOS来说是个理想值)后自动屏蔽。

2. touchstart换成touchend,因为触发touchend需要200ms所以可以把触发时间这个原理问题解决掉。

3. zepto最新版已经修复了这个问题,或者使用fastclick等通用库。

4. 直接使用click,不考虑延迟。

5.下层避开click事件,如a链接改为span等标签,使用js跳转页面。


12. rem em px的区别?

px:像素(Pixel)。绝对单位。像素 px 是相对于显示器屏幕分辨率而言的,是一个虚拟长度单位,

em:是相对长度单位,相对于当前对象内文本的字体尺寸。如当前对行内文本的字体尺寸未被人为设置, 则相对于浏览器的默认字体尺寸。它会继承父级元素的字体大小,因此并不是一个固定的值。

rem: 是 CSS3 新增的一个相对单位(root em,根 em),使用 rem 为元素设定字体大小时,仍然是相对大小, 但相对的只是 html 根元素。

px:像素(Pixel)。绝对单位。像素 px 是相对于显示器屏幕分辨率而言的,是一个虚拟长度单位,

em:是相对长度单位,相对于当前对象内文本的字体尺寸。如当前对行内文本的字体尺寸未被人为设置, 则相对于浏览器的默认字体尺寸。它会继承父级元素的字体大小,因此并不是一个固定的值。

rem: 是 CSS3 新增的一个相对单位(root em,根 em),使用 rem 为元素设定字体大小时,仍然是相对大小, 但相对的只是 html 根元素。


13. http常见状态码?

405:客户端请求的额方法被禁止

408:服务器等待客户端发送的请求时间过长,超时

200:服务器成功处理了请求

400:客户端发送了一个错误的请求

404:未找到资源

500:服务器内部出现错误

501:服务器遇到错误,使其无法对请求提供服务

405:客户端请求的额方法被禁止

408:服务器等待客户端发送的请求时间过长,超时

200:服务器成功处理了请求

400:客户端发送了一个错误的请求

404:未找到资源

500:服务器内部出现错误

501:服务器遇到错误,使其无法对请求提供服务


14.什么是同步,异步?

同步:由于js单线程,同步任务都在主线程上排队执行,前面任务没有执行完成,后面的任务会一直等待。

异步:不进入主线程,进入任务队列,等待主线程任务执行完成,开始执行。最基本的异步操作SetTimemot和SetInterval,等待主线程任务执行完,在开始执行里面的函数。

同步:由于js单线程,同步任务都在主线程上排队执行,前面任务没有执行完成,后面的任务会一直等待。

异步:不进入主线程,进入任务队列,等待主线程任务执行完成,开始执行。最基本的异步操作SetTimemot和SetInterval,等待主线程任务执行完,在开始执行里面的函数。


15. DOCTYPE的作用是什么?

<!DOCTYPE>位于文档的最顶部,它可以告诉浏览器按何种规范解析页面。

<!DOCTYPE>位于文档的最顶部,它可以告诉浏览器按何种规范解析页面。


16. 请描述一下cookies、sessionStorage和localStorage的区别?

sessionStorage:用于本地存储一个会话(session)中的数据,这些数据只有在同一个会话中的页面才能访问并且当会话结束后数据也随之销毁。因此sessionStorage不是一种持久化的本地存储,仅仅是会话级别的存储。

localStorage:用于持久化的本地存储,除非主动删除数据,否则数据是永远不会过期的。

Cookie:它的大小是受限的,并且每次你请求一个新的页面的时候Cookie都会被发送过去,这样无形中浪费了带宽,另外cookie还需要指定作用域,不可以跨域调用。WebStorage拥有setItem、getItem、removeItem、clear等方法,不像cookie需要前端开发者自己封装setCookie、getCookie。但是Cookie也是不可以或缺的:Cookie的作用是与服务器进行交互,作为HTTP规范的一部分而存在,而WebStorage仅仅是为了在本地“存储”数据而生。

sessionStorage:用于本地存储一个会话(session)中的数据,这些数据只有在同一个会话中的页面才能访问并且当会话结束后数据也随之销毁。因此sessionStorage不是一种持久化的本地存储,仅仅是会话级别的存储。

localStorage:用于持久化的本地存储,除非主动删除数据,否则数据是永远不会过期的。

Cookie:它的大小是受限的,并且每次你请求一个新的页面的时候Cookie都会被发送过去,这样无形中浪费了带宽,另外cookie还需要指定作用域,不可以跨域调用。WebStorage拥有setItem、getItem、removeItem、clear等方法,不像cookie需要前端开发者自己封装setCookie、getCookie。但是Cookie也是不可以或缺的:Cookie的作用是与服务器进行交互,作为HTTP规范的一部分而存在,而WebStorage仅仅是为了在本地“存储”数据而生。


17. 简述一下src与href的区别?

src用于替换当前元素,href用于在当前文档和引用资源之间确立联系。

src用于替换当前元素,href用于在当前文档和引用资源之间确立联系。


18. 一个页面上有大量的图片(大型电商网站),加载很慢,你有哪些方法优化这些图片的加载,给用户更好的体验。

1. 图片懒加载,在页面上的未可视区域可以添加一个滚动条事件,判断图片位置与浏览器顶端的距离与页面的距离,如果前者小于后者,优先加载。

2. 如果为幻灯片、相册等,可以使用图片预加载技术,将当前展示图片的前一张和后一张优先下载。

3. 如果图片为css图片,可以使用CSSsprite,SVGsprite,Iconfont、Base64等技术。

4. 如果图片过大,可以使用特殊编码的图片,加载时会先加载一张压缩的特别厉害的缩略图,以提高用户体验。

5. 如果图片展示区域小于图片的真实大小,则因在服务器端根据业务需要先行进行图片压缩,图片压缩后大小与展示一致。

1. 图片懒加载,在页面上的未可视区域可以添加一个滚动条事件,判断图片位置与浏览器顶端的距离与页面的距离,如果前者小于后者,优先加载。

2. 如果为幻灯片、相册等,可以使用图片预加载技术,将当前展示图片的前一张和后一张优先下载。

3. 如果图片为css图片,可以使用CSSsprite,SVGsprite,Iconfont、Base64等技术。

4. 如果图片过大,可以使用特殊编码的图片,加载时会先加载一张压缩的特别厉害的缩略图,以提高用户体验。

5. 如果图片展示区域小于图片的真实大小,则因在服务器端根据业务需要先行进行图片压缩,图片压缩后大小与展示一致。


19. 谈谈以前端角度出发,做好SEO需要考虑什么?

1. 了解搜索引擎如何抓取网页和如何索引网页,以及如何对搜索结果进行排序等。

2. Meta标签优化:主要包括主题(Title),网站描述(Description),和关键词(Keywords)。还有一些其它的隐藏文字比如Author(作者),Category(目录),Language(编码语种)等。

3. 如何选取关键词并在网页中放置关键词,关键词分析和选择是SEO最重要的工作之一。首先要给网站确定主关键词(一般在5个上下),然后针对这些关键词进行优化,包括关键词密度(Density),相关度(Relavancy),突出性(Prominency)等等。

4. 了解主要的搜索引擎,不同的搜索引擎对页面的抓取和索引、排序的规则都不一样。

5. 按点击付费的搜索引擎里面也大有优化和排名的学问,你得学会用最少的广告投入获得最多的点击。

6. 发外链。

7. 合理的标签使用。

1. 了解搜索引擎如何抓取网页和如何索引网页,以及如何对搜索结果进行排序等。

2. Meta标签优化:主要包括主题(Title),网站描述(Description),和关键词(Keywords)。还有一些其它的隐藏文字比如Author(作者),Category(目录),Language(编码语种)等。

3. 如何选取关键词并在网页中放置关键词,关键词分析和选择是SEO最重要的工作之一。首先要给网站确定主关键词(一般在5个上下),然后针对这些关键词进行优化,包括关键词密度(Density),相关度(Relavancy),突出性(Prominency)等等。

4. 了解主要的搜索引擎,不同的搜索引擎对页面的抓取和索引、排序的规则都不一样。

5. 按点击付费的搜索引擎里面也大有优化和排名的学问,你得学会用最少的广告投入获得最多的点击。

6. 发外链。

7. 合理的标签使用。


20. 有哪些方式可以对一个DOM设置它的css样式?

1. 外部样式表,引入一个外部css文件。

2. 内部样式表,将css代码放在<head>标签内部。

3. 内联样式,将css样式直接定义在HTML元素内部。

1. 外部样式表,引入一个外部css文件。

2. 内部样式表,将css代码放在<head>标签内部。

3. 内联样式,将css样式直接定义在HTML元素内部。


21. CSS中可以通过哪些属性定义,使得一个DOM元素不显示在浏览器可视范围内?

1. display:none;(隐藏后不占位置)

2. visibility:hidden;(隐藏后依然占位置)

3. overflow:hidden;

4. 设置宽高为0

1. display:none;(隐藏后不占位置)

2. visibility:hidden;(隐藏后依然占位置)

3. overflow:hidden;

4. 设置宽高为0


22. 行内元素和块级元素的具体区别是什么?行内元素的padding和margin可设置吗?

块级元素特性:总是独占一行,表现为另起一行开始,而且其后的元素也必须另起一行显示;宽度(width)、高度(height)、内边距(padding)和外边距(margin)都可控制;

行内元素特性:和相邻的行内元素在同一行;宽度(width)、高度(height)、内边距的top/bottom(padding-top/padding-bottom)和外边距的top/bottom(margin-top/margin-bottom)都不可改变(也就是padding和margin的left和right是可以设置的),就是里面文字或图片的大小。

行内块级元素:<input> 、<img> 、<button> 、<texterea> 、<label>

块级元素特性:总是独占一行,表现为另起一行开始,而且其后的元素也必须另起一行显示;宽度(width)、高度(height)、内边距(padding)和外边距(margin)都可控制;

行内元素特性:和相邻的行内元素在同一行;宽度(width)、高度(height)、内边距的top/bottom(padding-top/padding-bottom)和外边距的top/bottom(margin-top/margin-bottom)都不可改变(也就是padding和margin的left和right是可以设置的),就是里面文字或图片的大小。

行内块级元素:<input> 、<img> 、<button> 、<texterea> 、<label>


23. rgba()和opacity的透明效果有什么不同?

opacity作用于元素,以及元素内的所有内容的透明度。

rgba()只作用于元素的颜色或其背景色。(设置rgba透明的元素的子元素不会继承透明效果)

opacity作用于元素,以及元素内的所有内容的透明度。

rgba()只作用于元素的颜色或其背景色。(设置rgba透明的元素的子元素不会继承透明效果)

 
rgba和opacity的效果对比
 
 

rgba和opacity的效果对比

24. SASS、LESS是什么?大家为什么要使用它们?

它们是CSS预处理器。它是CSS上的一种抽象层。它们是一种特殊的语法/语言编译成CSS。

例如Less是一种动态样式语言. 将CSS赋予了动态语言的特性,如变量,继承,运算, 函数。LESS 既可以在客户端上运行 (支持IE 6+, Webkit, Firefox),也可以在服务端运行 (借助 node.js)。

为什么要使用它们?

1. 结构清晰,便于扩展。

2. 可以方便地屏蔽浏览器私有语法差异。这个不用多说,封装对浏览器语法差异的重复处理,减少无意义的机械劳动。

3. 可以轻松实现多重继承。

4. 完全兼容 CSS 代码,可以方便地应用到老项目中。LESS 只是在 CSS 语法上做了扩展,所以老的 CSS 代码也可以与 LESS 代码一同编译。

它们是CSS预处理器。它是CSS上的一种抽象层。它们是一种特殊的语法/语言编译成CSS。

例如Less是一种动态样式语言. 将CSS赋予了动态语言的特性,如变量,继承,运算, 函数。LESS 既可以在客户端上运行 (支持IE 6+, Webkit, Firefox),也可以在服务端运行 (借助 node.js)。

Less

为什么要使用它们?

1. 结构清晰,便于扩展。

2. 可以方便地屏蔽浏览器私有语法差异。这个不用多说,封装对浏览器语法差异的重复处理,减少无意义的机械劳动。

3. 可以轻松实现多重继承。

4. 完全兼容 CSS 代码,可以方便地应用到老项目中。LESS 只是在 CSS 语法上做了扩展,所以老的 CSS 代码也可以与 LESS 代码一同编译。


25. CSS中link和@import的区别是?

Link属于html标签,而@import是CSS中提供的。

在页面加载的时候,link会同时被加载,而@import引用的CSS会在页面加载完成后才会加载引用的CSS。

@import只有在ie5以上才可以被识别,而link是html标签,不存在浏览器兼容性问题。

Link引入样式的权重大于@import的引用(@import是将引用的样式导入到当前的页面中)

Link属于html标签,而@import是CSS中提供的。

在页面加载的时候,link会同时被加载,而@import引用的CSS会在页面加载完成后才会加载引用的CSS。

@import只有在ie5以上才可以被识别,而link是html标签,不存在浏览器兼容性问题。

Link引入样式的权重大于@import的引用(@import是将引用的样式导入到当前的页面中)


26. 为什么要初始化样式?

由于浏览器兼容的问题,不同的浏览器对标签的默认样式值不同,若不初始化会造成不同浏览器之间的显示差异。初始化CSS会对搜索引擎优化造成小影响。

由于浏览器兼容的问题,不同的浏览器对标签的默认样式值不同,若不初始化会造成不同浏览器之间的显示差异。初始化CSS会对搜索引擎优化造成小影响。


27. HTML与XHTML有什么区别?

1. 所有的标记都必须要有一个相应的结束标记

2. 所有标签的元素和属性的名字都必须使用小写

3. 所有的 XML 标记都必须合理嵌套

4. 所有的属性必须用引号 “” 括起来

5. 把所有 < 和 & 特殊符号用编码表示

6. 给所有属性赋一个值

7. 不要在注释内容中使用 “–“

8. 图片必须有说明文字

1. 所有的标记都必须要有一个相应的结束标记

2. 所有标签的元素和属性的名字都必须使用小写

3. 所有的 XML 标记都必须合理嵌套

4. 所有的属性必须用引号 “” 括起来

5. 把所有 < 和 & 特殊符号用编码表示

6. 给所有属性赋一个值

7. 不要在注释内容中使用 “–“

8. 图片必须有说明文字


28. 谈谈你对web标准及w3c的理解与认识。

        标签闭合,标签小写,不乱嵌套,提高搜索机器人搜索几率,使用外链css和js脚本,结构行为表现的分离,页面下载与加载速度更快,内容能被更多的用户和更广泛的设备访问,更少的代码和组件,容易维护,改版方便,不需要改变页面内容,提供打印版不需要复制页面内容,提高网站的易用性。

        标签闭合,标签小写,不乱嵌套,提高搜索机器人搜索几率,使用外链css和js脚本,结构行为表现的分离,页面下载与加载速度更快,内容能被更多的用户和更广泛的设备访问,更少的代码和组件,容易维护,改版方便,不需要改变页面内容,提供打印版不需要复制页面内容,提高网站的易用性。


29. 行内元素有哪些,块级元素有哪些,css的盒模型包括什么?

行内元素:span input b u i s select

块级元素:div p h1-h6 form ul

css盒模型:内容content + 内边距padding + 边框border + 外边距 margin

行内元素:span input b u i s select

块级元素:div p h1-h6 form ul

css盒模型:内容content + 内边距padding + 边框border + 外边距 margin


30. 列出display的值,说明它们的作用。position的值,relative和absolute的定位原点分别是?

display:

inline:按照行内元素样式显示

block:按照块级元素样式显示

inline-block:按照行内块级元素样式显示

none:隐藏元素

position:

static:静态定位,默认值,标准流中的元素都是静态定位

relation:相对定位,相对于原来的位置移动,依然占据着原来的位置

absolute:绝对定位,若元素没有父元素,或者父元素没有定位,则相对body定位,若父元素有定位(非static),则相对父元素定位,绝对定位的元素脱离标准流

fixed:固定定位,相对浏览器边框定位,固定定位的元素也脱离标准流

display:

inline:按照行内元素样式显示

block:按照块级元素样式显示

inline-block:按照行内块级元素样式显示

none:隐藏元素

position:

static:静态定位,默认值,标准流中的元素都是静态定位

relation:相对定位,相对于原来的位置移动,依然占据着原来的位置

absolute:绝对定位,若元素没有父元素,或者父元素没有定位,则相对body定位,若父元素有定位(非static),则相对父元素定位,绝对定位的元素脱离标准流

fixed:固定定位,相对浏览器边框定位,固定定位的元素也脱离标准流


31. 清除浮动有哪些方法?

1. 额外标签法(会增加标签,一般不用):在浮动的盒子之下再放一个标签,在这个标签中使用clear:both,以此来清除浮动。

2. 使用overflow:hidden属性:找到浮动盒子的父元素,给它添加overflow:hidden属性,即可清除浮动的影响。(一般也不用此方法清除浮动,因为溢出的元素会被隐藏)

3. 使用伪元素清楚浮动:

.clearfix:after{content:”;height:0;line-height:0;display: block;overflow: hidden;clear: both;}

1. 额外标签法(会增加标签,一般不用):在浮动的盒子之下再放一个标签,在这个标签中使用clear:both,以此来清除浮动。

2. 使用overflow:hidden属性:找到浮动盒子的父元素,给它添加overflow:hidden属性,即可清除浮动的影响。(一般也不用此方法清除浮动,因为溢出的元素会被隐藏)

3. 使用伪元素清楚浮动:

.clearfix:after{content:”;height:0;line-height:0;display: block;overflow: hidden;clear: both;}


Javascript方面:

1. 列举你知道的强制类型转换和隐式类型转换?

强制转换:parseInt()、parseFloat()、Number()、String()、.toString()、Boolean()

隐式转换:加(例外:不能是算式中,而需要加在变量前)减乘除及取余,!!

强制转换:parseInt()、parseFloat()、Number()、String()、.toString()、Boolean()

隐式转换:加(例外:不能是算式中,而需要加在变量前)减乘除及取余,!!


2.split() 、join() 的区别?

前者是切割成数组的形式,后者是将数组转换成字符串。

前者是切割成数组的形式,后者是将数组转换成字符串。


3. 数组方法pop() push() unshift() shift()?

push()尾部添加、pop()尾部删除、unshift()头部添加、shift()头部删除

push()尾部添加、pop()尾部删除、unshift()头部添加、shift()头部删除


4.call和apply的区别?

call:

语法:call(thisObj,Object1,Object2…)

定义:调用一个对象的一个方法,以另一个对象替换当前对象。

说明:call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。

apply:

语法:apply(thisObj,[argArray])

定义:应用某一对象的一个方法,用另一个对象替换当前对象。

说明:如果 argArray 不是一个有效的数组或者不是 arguments 对象,那么将导致一个 TypeError。

如果没有提供 argArray 和 thisObj 任何一个参数,那么 Global 对象将被用作 thisObj, 并且无法被传递任何参数。

call:

语法:call(thisObj,Object1,Object2…)

定义:调用一个对象的一个方法,以另一个对象替换当前对象。

说明:call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。

apply:

语法:apply(thisObj,[argArray])

定义:应用某一对象的一个方法,用另一个对象替换当前对象。

说明:如果 argArray 不是一个有效的数组或者不是 arguments 对象,那么将导致一个 TypeError。

如果没有提供 argArray 和 thisObj 任何一个参数,那么 Global 对象将被用作 thisObj, 并且无法被传递任何参数。


5.添加 删除 替换 插入到某个节点的方法?

obj.appendChid()  添加

obj.insertBefore()  插入

obj.replaceChild()  替换

obj.removeChild()  删除

obj.appendChid()  添加

obj.insertBefore()  插入

obj.replaceChild()  替换

obj.removeChild()  删除


6. javascript的本地对象,内置对象和宿主对象分别是什么?

本地对象为array、obj、regexp 等可以new实例化

内置对象为gload、Math 等不可以实例化的

宿主为浏览器自带的document、window 等

本地对象为array、obj、regexp 等可以new实例化

内置对象为gload、Math 等不可以实例化的

宿主为浏览器自带的document、window 等


7.window.onload和document.ready的区别?

1. window.onload是在dom文档树加载完和所有文件加载完之后执行一个函数document.ready原生中没有这个方法,jquery中有$().ready(function),在dom文档树加载完之后执行一个函数(注意,这里面的文档树加载完不代表全部文件加载完)。

2. $(document).ready要比window.onload先执行。

3. window.onload只能出来一次,$(document).ready可以出现多次。

1. window.onload是在dom文档树加载完和所有文件加载完之后执行一个函数document.ready原生中没有这个方法,jquery中有$().ready(function),在dom文档树加载完之后执行一个函数(注意,这里面的文档树加载完不代表全部文件加载完)。

2. $(document).ready要比window.onload先执行。

3. window.onload只能出来一次,$(document).ready可以出现多次。


8.”==”和”===”的不同?

前者只比较值,会自动转换类型。

后者比较值和类型。

前者只比较值,会自动转换类型。

后者比较值和类型。


9. javascript的同源策略?

一段脚本只能读取来自于同一来源的窗口和文档的属性,这里的同一来源指的是主机名、协议和端口号的组合。

一段脚本只能读取来自于同一来源的窗口和文档的属性,这里的同一来源指的是主机名、协议和端口号的组合。


10. JavaScript的数据类型都有哪些?

基本数据类型:String、boolean、Number、undefined、null

引用数据类型:Object(Array、Date、RegExp、Function)

基本数据类型:String、boolean、Number、undefined、null

引用数据类型:Object(Array、Date、RegExp、Function)


11. 如何判断某变量是否为数组数据类型?

方法一:判断其是否具有“数组性质”,如slice()方法。可自己给该变量定义slice方法,故有时会失效。

方法二:obj instanceof Array,在某些IE版本中不正确。

方法三:方法一二皆有漏洞,在ECMA Script5中定义了新方法Array.isArray(), 保证其兼容性。

方法一:判断其是否具有“数组性质”,如slice()方法。可自己给该变量定义slice方法,故有时会失效。

方法二:obj instanceof Array,在某些IE版本中不正确。

方法三:方法一二皆有漏洞,在ECMA Script5中定义了新方法Array.isArray(), 保证其兼容性。


12. 当一个DOM节点被点击时候,我们希望能够执行一个函数,应该怎么做?

直接在DOM里绑定事件:<div onclick=’test()’></div>

在JS里通过onclick绑定:xxx.onclick=test()

通过事件添加进行绑定:addEventListener(xxx,’click’,test())

直接在DOM里绑定事件:<div onclick=’test()’></div>

在JS里通过onclick绑定:xxx.onclick=test()

通过事件添加进行绑定:addEventListener(xxx,’click’,test())

13. Javascript的事件流模型都有什么?

“事件冒泡”:事件开始由最具体的元素接收,然后逐级向上传播。

“事件捕捉”:事件由最不具体的节点先接收,然后逐级向下,一直到最具体的。

“DOM事件流”:三个阶段:事件捕捉,目标阶段,事件冒泡。

“事件冒泡”:事件开始由最具体的元素接收,然后逐级向上传播。

“事件捕捉”:事件由最不具体的节点先接收,然后逐级向下,一直到最具体的。

“DOM事件流”:三个阶段:事件捕捉,目标阶段,事件冒泡。


14. var numberArray=[3,6,2,4,1,5];

实现对该数组的倒排,输出[5,1,4,2,6,3]

numberArray.reverse();

实现对该数组的降序排列,输出[6,5,4,3,2,1]

numberArray.sort(function(a,b){returnb-a})

实现对该数组的倒排,输出[5,1,4,2,6,3]

numberArray.reverse();

实现对该数组的降序排列,输出[6,5,4,3,2,1]

numberArray.sort(function(a,b){returnb-a})


15. 闭包,闭包的作用?

闭包就是能够读取其他函数内部变量的函数。闭包是将函数内部和函数外部连接起来的桥梁。

作用 可以读取函数内部的变量 让这些变量的值始终保持在内存中。

缺点 1.闭包的缺点就是会增大内存使用量,并且使用不当容易造成内存泄漏。

2.如果不是因为某些特殊任务而需要闭包,在没有必要的情况下,在其它函数中创建函数是不明智的,因为闭包对脚本性能具有负面影响,包括处理速度和内存消耗。

闭包就是能够读取其他函数内部变量的函数。闭包是将函数内部和函数外部连接起来的桥梁。

作用 可以读取函数内部的变量 让这些变量的值始终保持在内存中。

缺点 1.闭包的缺点就是会增大内存使用量,并且使用不当容易造成内存泄漏。

2.如果不是因为某些特殊任务而需要闭包,在没有必要的情况下,在其它函数中创建函数是不明智的,因为闭包对脚本性能具有负面影响,包括处理速度和内存消耗。


16. 作用域,作用域链?

作用域就是变量与函数的可访问范围。作用域分为 全局作用域(所声明的变量全局都可以访问),局部作用域(所声明的变量只在其内部可以访问)。

作用域链:当我们在一个函数内部访问当前作用域内不存在的变量时,就会逐层向外查找,如果一直找不到就会报错。当我们在局部作用域中,调用外部变量时,就产生了作用域链。

作用域就是变量与函数的可访问范围。作用域分为 全局作用域(所声明的变量全局都可以访问),局部作用域(所声明的变量只在其内部可以访问)。

作用域链:当我们在一个函数内部访问当前作用域内不存在的变量时,就会逐层向外查找,如果一直找不到就会报错。当我们在局部作用域中,调用外部变量时,就产生了作用域链。


17. 描述一次完整的http请求?

1.查询NDS(域名解析),获取域名对应的IP地址

查询浏览器缓存

2.浏览器与服务器建立tcp链接(三次握手)。

第一次握手:客户端发送一个请求连接,服务器端只能确认自己可以接受客户端发送的报文段。

第二次握手: 服务端向客户端发送一个链接,确认客户端收到自己发送的报文段。

第三次握手: 服务器端确认客户端收到了自己发送的报文段。

3.浏览器向服务器发送http请求(请求和传输数据)。

4.服务器接受到这个请求后,根据路经参数,经过后端的一些处理生成html代码返回给浏览器。

5.浏览器拿到完整的html页面代码开始解析和渲染,如果遇到外部的css或者js,图片一样的步骤。

6.浏览器根据拿到的资源对页面进行渲染,把一个完整的页面呈现出来。

1.查询NDS(域名解析),获取域名对应的IP地址

查询浏览器缓存

2.浏览器与服务器建立tcp链接(三次握手)。

第一次握手:客户端发送一个请求连接,服务器端只能确认自己可以接受客户端发送的报文段。

第二次握手: 服务端向客户端发送一个链接,确认客户端收到自己发送的报文段。

第三次握手: 服务器端确认客户端收到了自己发送的报文段。

3.浏览器向服务器发送http请求(请求和传输数据)。

4.服务器接受到这个请求后,根据路经参数,经过后端的一些处理生成html代码返回给浏览器。

5.浏览器拿到完整的html页面代码开始解析和渲染,如果遇到外部的css或者js,图片一样的步骤。

6.浏览器根据拿到的资源对页面进行渲染,把一个完整的页面呈现出来。


18. 浏览器是如何渲染页面的?

流程:解析html以及构建dom树 -> 构建render树 -> 布局render树 -> 绘制render树

1.构建DOM树: 渲染引擎解析HTML文档,首先将标签转换成DOM树中的DOM node(包括js生成的标签)生成内容树。

2.构建渲染树: 解析对应的css样式文件信息(包括js生成的样式和外部的css)。

3.布局渲染树:从根节点递归调用,计算每一个元素的大小,位置等。给出每个节点所在的屏幕的精准位置。

4.绘制渲染树:遍历渲染树,使用UI后端层来绘制每一个节点。

流程:解析html以及构建dom树 -> 构建render树 -> 布局render树 -> 绘制render树

1.构建DOM树: 渲染引擎解析HTML文档,首先将标签转换成DOM树中的DOM node(包括js生成的标签)生成内容树。

2.构建渲染树: 解析对应的css样式文件信息(包括js生成的样式和外部的css)。

3.布局渲染树:从根节点递归调用,计算每一个元素的大小,位置等。给出每个节点所在的屏幕的精准位置。

4.绘制渲染树:遍历渲染树,使用UI后端层来绘制每一个节点。

vue.js  方面:

1.vue的核心思想:

组件化开发和数据驱动。

组件化开发和数据驱动。

2.什么是vuex?有什么作用?

vuex是vue的状态管理工具。

作用:项目数据状态的集中管理,复杂组件的数据通信问题。

vuex是vue的状态管理工具。

作用:项目数据状态的集中管理,复杂组件的数据通信问题。

3.Vuex的核心属性:

State:存储数据状态的地方,但是不可以直接修改里面的数据。

Mutations: mutations定义的方法动态修改vuex的store中的状态或数据。

Actions:简单的说就是异步操作数据,view层通过store.dispatch来分发action。

Getters:类似vue的计算属性,主要用来过滤数据。

Modules:模块化管理   项目特别复杂的时候,可以让每一个模块拥有自己的state,mutation,action,getters,使得结构非常清晰,方便管理。

State:存储数据状态的地方,但是不可以直接修改里面的数据。

Mutations: mutations定义的方法动态修改vuex的store中的状态或数据。

Actions:简单的说就是异步操作数据,view层通过store.dispatch来分发action。

Getters:类似vue的计算属性,主要用来过滤数据。

Modules:模块化管理   项目特别复杂的时候,可以让每一个模块拥有自己的state,mutation,action,getters,使得结构非常清晰,方便管理。

4.vuex的工作流程?

vue组件里面,通过dispatch来触发actions提交修改数据的操作

然后再通过actions的commit来触发mutations来修改数据

Mutations接收到commit的请求,就会自动通过mutate来修改state里面的数据

最后由store触发每一个调用它的组建的更新。

在vue组件里面,通过dispatch来触发actions提交修改数据的操作

然后再通过actions的commit来触发mutations来修改数据

Mutations接收到commit的请求,就会自动通过mutate来修改state里面的数据

最后由store触发每一个调用它的组建的更新。

5.Vue的生命周期?

BeforeCreated(实例创建前):此时的vue实例还没有挂载元素$el,数据对象data也是undefined。

Created(实例创建完成):vue实例的数据对象data有了,但是$el还没有。

beforeMount(实例载入前):vue的实例的$el和data都初始化了,但还是挂载在之前的虚拟DOM节点上,data.message还没替换。

Mounted(实力载入完成):vue实例挂载完成,data.message成功渲染。

beforeUpdate(实例更新前):data发生变化前。

Updated(实例更新前):data发生变化后。

BeforeDestory(实例销毁前):在实例销毁之前调用,实例仍然可用。

Destory(实例销毁完成):所有的监听事件会被消除,所有的子实例也会被销毁。

BeforeCreated(实例创建前):此时的vue实例还没有挂载元素$el,数据对象data也是undefined。

Created(实例创建完成):vue实例的数据对象data有了,但是$el还没有。

beforeMount(实例载入前):vue的实例的$el和data都初始化了,但还是挂载在之前的虚拟DOM节点上,data.message还没替换。

Mounted(实力载入完成):vue实例挂载完成,data.message成功渲染。

beforeUpdate(实例更新前):data发生变化前。

Updated(实例更新前):data发生变化后。

BeforeDestory(实例销毁前):在实例销毁之前调用,实例仍然可用。

Destory(实例销毁完成):所有的监听事件会被消除,所有的子实例也会被销毁。

6.vue常用的指令?

V-model   v-html   v-text  v-for  v-show  v-if  v-on

V-model   v-html   v-text  v-for  v-show  v-if  v-on

7.V-if和v-show的区别?

V-if是通过添加和删除DOM节点来控制显示隐藏,v-show是通过操作css的display属性来控制显示隐藏;

V-if拥有更高的切换成本,v-show拥有更高的渲染成本。

频繁切换的时候使用v-show,不经常切换就使用v-if.

V-if是通过添加和删除DOM节点来控制显示隐藏,v-show是通过操作css的display属性来控制显示隐藏;

V-if拥有更高的切换成本,v-show拥有更高的渲染成本。

频繁切换的时候使用v-show,不经常切换就使用v-if.

8.V-for和v-if的优先级?

当它们处于同一节点,v-for的优先级比v-if更高,这意味着v-if将分别重复运行于每个v-for的循环中。

当它们处于同一节点,v-for的优先级比v-if更高,这意味着v-if将分别重复运行于每个v-for的循环中。

9.MVC   MVP   MVVM的区别?

MVC: MVC之间的数据通信都是单向的。View(视图层)发送指令到controller(控制层),完成业务逻辑后,要求Model(模型层)改变状态,匠心的数据发送到(view)视图层,用户得到反馈。

MVP:在MVP中,view和model之间没有任何通信关系,所有的通信和业务逻辑都放在presenter层中。View层发送指令到presenter层,presenter层处理业务逻辑,要求model层改变状态,完成状态修改之后,发送指令到presenter层,之后再通知view层做出改变。

MVVM: Model专门用来处理数据模型。View专门用来处理用户视图,ViewModel用来使view和model双向绑定,view的任何变化都会通知ViewModel,而model的任何变化也会通知ViewModel,无论哪一项发生改变,都会使对应的视图/数据模型同时发生改变。

MVC: MVC之间的数据通信都是单向的。View(视图层)发送指令到controller(控制层),完成业务逻辑后,要求Model(模型层)改变状态,匠心的数据发送到(view)视图层,用户得到反馈。

MVP:在MVP中,view和model之间没有任何通信关系,所有的通信和业务逻辑都放在presenter层中。View层发送指令到presenter层,presenter层处理业务逻辑,要求model层改变状态,完成状态修改之后,发送指令到presenter层,之后再通知view层做出改变。

MVVM: Model专门用来处理数据模型。View专门用来处理用户视图,ViewModel用来使view和model双向绑定,view的任何变化都会通知ViewModel,而model的任何变化也会通知ViewModel,无论哪一项发生改变,都会使对应的视图/数据模型同时发生改变。

11.什么是axios?

就是请求后台资源的模块,前台通过它获取后台数据,类似ajax交互。

就是请求后台资源的模块,前台通过它获取后台数据,类似ajax交互。

13.路由传参的方法?路由传参方法

路由传参方法

1. 字符串拼接 : 路由后面直接拼接要传递的参数,用this.$rote.params 接收。

2. path和query:path后面跟要跳转的路由,query后边跟要传递参数的对象 用 this.$route.query 接收。

3. name和params:name后面跟要跳转路由的名称,params后面跟传递参数的对象,用this.$route.params接收。

1. 字符串拼接 : 路由后面直接拼接要传递的参数,用this.$rote.params 接收。

2. path和query:path后面跟要跳转的路由,query后边跟要传递参数的对象 用 this.$route.query 接收。

3. name和params:name后面跟要跳转路由的名称,params后面跟传递参数的对象,用this.$route.params接收。

14.Vuex中actions和mutations的区别?

Mutations的更改是同步更改,用于用户执行直接数据更改,this.$store.commit(‘名’)触发。

Actions的更改是异步操作,用于需要与后端交互的数据更改,this.$store.dispath(“名”)触发。

注意:

1):定义actions方法创建一个更改函数时,这个函数必须携带一个context参数,用于触发mutations方法,context.commit(‘修改函数名’ , ’异步请求值’);

2):mutations第一个参数必须传入state,第二个参数是新值。

Mutations的更改是同步更改,用于用户执行直接数据更改,this.$store.commit(‘名’)触发。

Actions的更改是异步操作,用于需要与后端交互的数据更改,this.$store.dispath(“名”)触发。

注意:

1):定义actions方法创建一个更改函数时,这个函数必须携带一个context参数,用于触发mutations方法,context.commit(‘修改函数名’ , ’异步请求值’);

2):mutations第一个参数必须传入state,第二个参数是新值。

15.渐进式框架的理解?

主张最少,没有多做职责之外的事 我的理解就是 用什么就引入什么,没有硬性规定。

主张最少,没有多做职责之外的事 我的理解就是 用什么就引入什么,没有硬性规定。

项目介绍1

项目介绍:

项目背景:

商品分类怎么实现的;

单选多选全选怎么实现的:

加入购物车怎么实现的;

登录注册怎么实现;

登录流程:

        当我点击登录的时候,我先判断我输入的值是否符合规则,如果符合,就把参数拼接到接口上,然后请求,后台会返回一个token值,我把token放在本地存储中,在全局路由守卫中,当我要访问一个需要登录才可以进入的路由的时候,我就判断本地存储中有没有这个token值,如果有,就进入这个路由,如果没有,就返回登录页面登录。

        当我点击登录的时候,我先判断我输入的值是否符合规则,如果符合,就把参数拼接到接口上,然后请求,后台会返回一个token值,我把token放在本地存储中,在全局路由守卫中,当我要访问一个需要登录才可以进入的路由的时候,我就判断本地存储中有没有这个token值,如果有,就进入这个路由,如果没有,就返回登录页面登录。

Loading动画怎么实现:

        用axios拦截器实现loading动画效果 首先新建一个loading组件,里面写一些动画效果,然后在vuex里面写一个状态来控制我的loading动画组件的显示隐藏,然后在全局main.js中配置axios拦截器,分别定义一个请求拦截器和响应拦截器,在请求数据时执行请求拦截器,改变我vuex里面定义的状态,让loading动画显示,反之,数据请求到之后,隐藏loading动画即可。

        用axios拦截器实现loading动画效果 首先新建一个loading组件,里面写一些动画效果,然后在vuex里面写一个状态来控制我的loading动画组件的显示隐藏,然后在全局main.js中配置axios拦截器,分别定义一个请求拦截器和响应拦截器,在请求数据时执行请求拦截器,改变我vuex里面定义的状态,让loading动画显示,反之,数据请求到之后,隐藏loading动画即可。

图片懒加载怎么实现:

        我们先不给<img>设置src,把图片真正的URL放在另一个属性data-src中,在需要的时候也就是图片进入可视区域的之前,将URL取出放到src中。

        我们先不给<img>设置src,把图片真正的URL放在另一个属性data-src中,在需要的时候也就是图片进入可视区域的之前,将URL取出放到src中。

移动端的性能优化:

         首屏加载和按需加载,懒加载 资源预加载 图片压缩处理,使用base64内嵌图片 合理缓存dom对象 使用touchstart代替click(click 300毫秒的延迟) 利用transform:translateZ(0),开启硬件GUP加速 不滥用web字体,不滥用float(布局计算消耗性能),减少font-size声明 使用viewport固定屏幕渲染,加速页面渲染内容 尽量使用事件代理,避免直接事件绑定。

         首屏加载和按需加载,懒加载 资源预加载 图片压缩处理,使用base64内嵌图片 合理缓存dom对象 使用touchstart代替click(click 300毫秒的延迟) 利用transform:translateZ(0),开启硬件GUP加速 不滥用web字体,不滥用float(布局计算消耗性能),减少font-size声明 使用viewport固定屏幕渲染,加速页面渲染内容 尽量使用事件代理,避免直接事件绑定。

项目介绍2

项目介绍:

项目背景:

后台权限管理是怎么实现的:

       定义两张路由表,一张是静态路由表(无需权限的使用),另一张是权限路由表(和后台返回的权限进行匹配使用)。用户登录,判断登录是否成功,登录成功后判断是否获取用户权限列表,获取到后,将权限数据存储到Vuex中。用Vuex中的权限数据和定义好的需要访问权限的路由表进行比对。比对完后生成当前账户对应的权限路由表。通过addRouters方法动态添加路由规则,生成可访问的侧边栏菜单。

       定义两张路由表,一张是静态路由表(无需权限的使用),另一张是权限路由表(和后台返回的权限进行匹配使用)。用户登录,判断登录是否成功,登录成功后判断是否获取用户权限列表,获取到后,将权限数据存储到Vuex中。用Vuex中的权限数据和定义好的需要访问权限的路由表进行比对。比对完后生成当前账户对应的权限路由表。通过addRouters方法动态添加路由规则,生成可访问的侧边栏菜单。

跨域问题,怎么解决的:

jsonp跨域原理: jsonp是请求之后 后台会封装好的一段json,并且把数据放在一个callback回调函数中,并返回一个js文件,动态的引入这个文件,调用这个callback回调函数,进行数据访问。

反向代理跨域:客户端发送请求时不直接到服务器而是先到代理的中间层在这里将localhost:8080的这个域名装换为www.njc.com,再将请求发送到服务器这样在服务器端收到的请求就是使用的www.njc.com域名同理,当服务器返回数据的时候,也是先到代理的中间层将www.njc.com转换成localhos:8080;这样在客户端也是在相同域名下访问的了。  

 

本文引自:https://www.jianshu.com/p/7a30b701be42

jsonp跨域原理: jsonp是请求之后 后台会封装好的一段json,并且把数据放在一个callback回调函数中,并返回一个js文件,动态的引入这个文件,调用这个callback回调函数,进行数据访问。

反向代理跨域:客户端发送请求时不直接到服务器而是先到代理的中间层在这里将localhost:8080的这个域名装换为www.njc.com,再将请求发送到服务器这样在服务器端收到的请求就是使用的www.njc.com域名同理,当服务器返回数据的时候,也是先到代理的中间层将www.njc.com转换成localhos:8080;这样在客户端也是在相同域名下访问的了。  

 

本文引自:https://www.jianshu.com/p/7a30b701be42

https://www.jianshu.com/p/7a30b701be42

» 本文来自:前端开发者 » 《前端面试题套路–终极版(Vue、JavaScript)_盂希_前端开发者》
» 本文链接地址:https://www.rokub.com/73727.html
» 您也可以订阅本站:https://www.rokub.com
赞(0)
64K

评论 抢沙发

评论前必须登录!