1.行内元素有哪些?块级元素有哪些? 空(void)元素有那些?
CSS规范规定,每个元素都有display属性,确定该元素的类型,每个元素都有默认的display值,比如div默认display属性值为“block”,成为“块级”元素;span默认display属性值为“inline”,是“行内”元素。
行内元素有:span a b i img input select strong
块级元素有:div p h1-h6 ul table form ul ol li dl dt dd…
空元素(没有内容): <br> <hr> <img> <input> <link> <meta>
2.什么是盒子模型?
盒子模型是css3新特性。具有以下特性:
把所有的网页元素都看成一个盒子,它具有: content,padding,border,margin 四个属性,这就是盒子模型
盒子模型有两种形式:标准盒子模型,怪异盒子模型
两种模式可以利用box-sizing属性进行自行选择:
标准模式:box-sizing:content-box;
怪异模式:box-sizing:border-box;
两种模式的区别:
标准模式会被设置的padding撑开
而怪异模式则相当于将盒子的大小固定好,再将内容装入盒子,盒子的大小并不会被padding所撑开
3.简述一下src与href的区别?
src和href都是属于外部资源的引用,像一些图片,css文件,js文件,或者其他的web页面
他们的之间的主要关系可以用这样的一句话来概括:src用于替换这个元素,而href用于建立这个标签与外部资源的关系
href (Hypertext Reference) 表示超文本引用,href这个属性指定web资源的位置,从而定义当前元素(如锚点a)或当前文档(如链接)与目标锚点或目标资源之间的联系
src (Source)源这个属性是将资源嵌入到当前文档中元素所在的位置
当浏览器解析到src引用的js文件代码时,页面的加载和解析都会暂停直到浏览器拿到并执行完这个js文件。这就像是把js文件里的内容全部注入到这个script标签中,类似于img,img标签是一个空标签,它的内容就是由src这个属性定义,浏览器会暂停加载直到这个图片加载完成。这也是为什么要将js文件的加载放在body最后的原因(在前面)
4.什么是CSS Hack?
CSS hack是通过在CSS样式中加入一些特殊的符号,让不同的浏览器识别不同的符号(什么样的浏览器识别什么样的符号是有标准的,CSS hack就是让你记住这个标准),以达到应用不同的CSS样式的目的。
CSS属性Hack、CSS选择符Hack以及IE条件注释Hack, Hack主要针对IE浏览器。
1、属性级Hack:比如IE6能识别下划线“_
”和星号“*
”,IE7能识别星号“*
”,但不能识别下划线”_
”,而firefox两个都不能认识。
2、选择符级Hack:比如IE6能识别*html .class{}
,IE7能识别*+html .class{}
或者*:first-child+html .class{}
。
3、IE条件注释Hack:IE条件注释是微软IE5开始就提供的一种非标准逻辑语句。比如针对所有IE:<!-[if IE]><!-您的代码-><![endif]>
,针对IE6及以下版本:<!-[if it IE 7]><!-您的代码-><![endif]->
,这类Hack不仅对CSS生效,对写在判断语句里面的所有代码都会生效。
PS:条件注释只有在IE浏览器下才能执行,这个代码在非IE浏览下被当做注释视而不见。可以通过IE条件注释载入不同的CSS、JS、HTML和服务器代码等。
浏览器优先级别:
FF<IE7<IE6,CSS hack
书写顺序一般为FF IE7 IE6
注意: 不管是什么方法,书写的顺序都是firefox的写在前面,IE7的写在中间,IE6的写在最后面。补充:IE6能识别*
,但不能识别 !important
,IE7能识别 *
,也能识别!important
;FF不能识别 *
,但能识别!important
;下划线” _
“,IE6支持下划线,IE7和firefox均不支持下划线。
5.为什么不推荐使用CSS hack来解决兼容性问题 ?
CSS hack是因为现有浏览器对标准的解析不同,为了兼容各浏览器,所采用的一种补救方法。CSS hack是一种类似作弊的手段,以欺骗浏览器的方式达到兼容的目的,是用浏览器的兼容性差异来解决浏览器的兼容性问题。因此,在设计之初,写CSS hack需要遵循以下三条原则:
- 有效: 能够通过 Web 标准的验证
- 只针对太古老的/不再开发的/已被抛弃的浏览器, 而不是目前的主流浏览器
- 代码要丑陋。让人记住这是一个不得已而为之的 Hack, 时刻记住要想办法去掉它。现在很多hacks已经抛弃了最初的原则,而滥用hack会导致浏览器更新之后产生更多的兼容性问题。因此,并不推荐使用CSS hack来解决兼容性问题。
6.简述同步和异步的区别?
javascript是单线程的语言,所谓的单线程,就是从上至下,依次执行,当然这里的依次执行要抛开javascript的预解析机制。*
这样做的原因是因为javascript最初是为了操作DOM,运行在浏览器环境下的,而操作DOM的时候,不能是异步的,不然的话两个异步任务同时修改DOM结构的话,会导致浏览器不知道该执行哪一个。*
但是这样做也有缺点,当遇到一个响应时间特别长的任务时,容易导致页面加载错误或者浏览器未响应的情况。
同步就是所有的任务都处在同一队列中,不可以插队,一个任务执行完接着开始执行下一个,相对于浏览器而言,同步的效率过低,一些耗费时间比较长的任务应该用异步来执行。
异步就是将一个任务放入到异步队列中,当这个任务执行完成之后,再从异步队列中提取出来,插队到同步队列中,拿到异步任务的结果,可以提升代码执行的效率,不需要因为一个耗费时长的代码而一直等待。
7.px和em的区别?
px像素(Pixel)。相对长度单位。像素px是相对于显示器屏幕分辨率而言的。
em是相对长度单位。相对于当前对象内文本的字体尺寸,多理解父级设定font-size的尺寸。如当前对行内文本的字体尺寸未被人为设置,则相对于浏览器的默认字体尺寸。
任意浏览器的默认字体高都是16px。所有未经调整的浏览器都符合: 1em=16px。那么12px=0.75em,10px=0.625em。
为了简化font-size的换算,需要在css中的body选择器中声明Font-size=62.5%,这就使em值变为 16px*62.5%=10px, 这样12px=1.2em, 10px=1em, 也就是说只需要将你的原来的px数值除以10,然后换上em作为单位就行了。
注:在body里面注明 font-size:62.5%;
1.之后可以将em当px使用,x10就好,当然前提是父级标签里面没设定font-size,
2.一旦父级元素有设定字体大小, em前面数值x就相当于父级元素字体乘以x%
3.相对最临近父级元素,且可以一直往下叠加.
8.什么叫优雅降级和渐进增强?
优雅降级:Web站点在所有新式浏览器中都能正常工作,如果用户使用的是老式浏览器,则代码会检查以确认它们是否能正常工作。由于IE独特的盒模型布局问题,针对不同版本的IE的hack实践过优雅降级了,为那些无法支持功能的浏览器增加候选方案,使之在旧式浏览器上以某种形式降级体验却不至于完全失效.
渐进增强:从被所有浏览器支持的基本功能开始,逐步地添加那些只有新式浏览器才支持的功能,向页面增加无害于基础浏览器的额外样式和功能的。当浏览器支持时,它们会自动地呈现出来并发挥作用。
9.浏览器的内核分别是什么?
- IE: trident内核
- Firefox:gecko内核
- Safari: webkit内核
- Opera: 以前是presto内核,Opera现已改用Google - Chrome的Blink内核
- Chrome: Blink(基于webkit,Google与Opera Software共同开发)
10.http 状态码,以及常见的状态码?
HTTP状态码表示客户端HTTP请求的返回结果、标记服务器端的处理是否正常或者是出现的错误,能够根据返回的状态码判断请求是否得到正确的处理很重要,状态码由3位数字和原因短语组成。
状态码分类表:
1xx Informational(信息性状态码) 接受的请求正在处理
2xx Success(成功状态码) 请求正常处理完毕
3xx Redirection(重定向) 需要进行附加操作以完成请求
4xx Client error(客户端错误) 客户端请求出错,服务器无法处理请求
5xx Server Error(服务器错误) 服务器处理请求出错
各类别常见状态码:
2xx (3种)
200 OK:表示从客户端发送给服务器的请求被正常处理并返回;
204 No Content:表示客户端发送给客户端的请求得到了成功处理,但在返回的响应报文中不含实体的主体部分(没有资源可以返回);
206 Patial Content:表示客户端进行了范围请求,并且服务器成功执行了这部分的GET请求,响应报文中包含由Content-Range指定范围的实体内容。
3xx (5种)
301 Moved Permanently:永久性重定向,表示请求的资源被分配了新的URL,之后应使用更改的URL;
302 Found:临时性重定向,表示请求的资源被分配了新的URL,希望本次访问使用新的URL;
301与302的区别:前者是永久移动,后者是临时移动(之后可能还会更改URL)
303 See Other:表示请求的资源被分配了新的URL,应使用GET方法定向获取请求的资源;
302与303的区别:后者明确表示客户端应当采用GET方式获取资源
304 Not Modified:表示客户端发送附带条件(是指采用GET方法的请求报文中包含if-Match、If-Modified-Since、If-None-Match、If-Range、If-Unmodified-Since中任一首部)的请求时,服务器端允许访问资源,但是请求为满足条件的情况下返回改状态码;
307 Temporary Redirect:临时重定向,与303有着相同的含义,307会遵照浏览器标准不会从POST变成GET;(不同浏览器可能会出现不同的情况);
4xx (4种)
400 Bad Request:表示请求报文中存在语法错误;
401 Unauthorized:未经许可,需要通过HTTP认证;
403 Forbidden:服务器拒绝该次访问(访问权限出现问题)
404 Not Found:表示服务器上无法找到请求的资源,除此之外,也可以在服务器拒绝请求但不想给拒绝原因时使用;
5xx (2种)
500 Inter Server Error:表示服务器在执行请求时发生了错误,也有可能是web应用存在的bug或某些临时的错误时;
503 Server Unavailable:表示服务器暂时处于超负载或正在进行停机维护,无法处理请求;
11.请描述一下cookies,sessionStorage和localStorage的区别?
特性 | Cookie | localStorage | sessionStorage |
---|---|---|---|
特性 | 一般由服务器生成,可设置失效时间。如果在浏览器端生成Cookie,默认是关闭浏览器后失效 | 除非被清除,否则永久保存 | 仅在当前会话下有效,关闭页面或浏览器后被清除 |
存放数据大小 | 4K左右 | 一般为5MB | |
与服务器端通信 | 每次都会携带在HTTP头中,如果使用cookie保存过多数据会带来性能问题 | 仅在客户端(即浏览器)中保存,不参与和服务器的通信 | |
易用性 | 需要程序员自己封装,源生的Cookie接口不友好 | 源生接口可以接受,亦可再次封装来对Object和Array有更好的支持 |
12.怎样添加、移除、移动、复制、创建和查找节点?
createDocumentFragment() //创建一个DOM片段
createElement() //创建一个具体的元素
createTextNode() //创建一个文本节点
2)添加、移除、替换、插入
appendChild() //添加
removeChild() //移除
replaceChild() //替换
insertBefore() //插入
3)查找
getElementsByTagName() //通过标签名称
getElementsByName() //通过元素的Name属性的值
getElementById() //通过元素Id,唯一性
13.Javascript中callee和caller的作用?
- caller是返回一个对函数的引用,该函数调用了当前函数;
- callee是返回正在被执行的function函数,也就是所指定的function对象的正文
14.数组快速排序?
var quickSort = function(arr) {
if (arr.length <= 1) { return arr; }
var pivotIndex = Math.floor(arr.length / 2);
var pivot = arr.splice(pivotIndex, 1)[0];
var left = [];
var right = [];
for (var i = 0; i < arr.length; i++){
if (arr[i] < pivot) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}
return quickSort(left).concat([pivot], quickSort(right));//递归算法
};
15.一次完整的HTTP事务是怎样的一个过程?
域名解析 --> 发起TCP的3次握手 --> 建立TCP连接后发起http请求 --> 服务器响应http请求,浏览器得到html代码 --> 浏览器解析html代码,并请求html代码中的资源(如js、css、图片等) --> 浏览器对页面进行渲染呈现给用户
16.什么是React 路由?
现代前端大多数都是SPA(单页面程序),也就是只有一个HTML页面的应用程序,因为它的用户体验更好,对服务器压力更小,所以更受欢迎,为了有效的使用单个页面来管理原来多页面的功能,前端路由应运而生。
前端 路由的功能:让用户从一个视图(页面)导航到另一个视图(页面)
前端路由是一套映射规则,在React中,是URL路径与组件的对应关系
使用React路由简单来说,就是配置路径和组件
17.为什么React Router v4中使用 switch 关键字 ?
有标签,则其中的在路径相同的情况下,只匹配第一个,这个可以避免重复匹配;为了更好地匹配规则,轻易不要舍弃 。
Switch匹配到第一个路由就不会继续匹配了,
如果不加Route 里不加 exact,那么凡是Link里面 to 的路径包含了/( /about, /topic 都包含了 / ,当点击about或者topic的Link的时候,path=’/'的路由都会匹配到,Switch匹配到了一个就停止向下匹配,那么就会被匹配到,于是Switch就不继续匹配下去。
如果没有Switch也没有exact,不管点击哪个链接都会有path=’/的页面’。
有Switch没有exact:不管点击哪个链接都只会出来path=’/'的页面(也就是Main页面)。
18.列出 React Router 的优点?
1.风格: 与React融为一体,专为react量身打造,编码风格与react保持一致,例如路由的配置可以通过component来实现
2.简单: 不需要手工维护路由state,使代码变得简单
3.强大: 强大的路由管理机制,体现在如下方面
4.路由配置: 可以通过组件、配置对象来进行路由的配置
5.路由切换: 可以通过<Link> Redirect进行路由的切换
6.路由加载: 可以同步记载,也可以异步加载,这样就可以实现按需加载
7.使用方式: 不仅可以在浏览器端的使用,而且可以在服务器端的使用
缺点:API不太稳定,在升级版本的时候需要进行代码变动。
19.为什么需要 React 中的路由?
react-router-dom这个包,给我们声明了很多的组件,我们可以直接导入这些组件去使用,就可以完成我们想要的路由相关的功能
原理:实现URL与UI界面的同步。其中在react-router中,URL对应Location对象,
而UI是由react components来决定的,这样就转变成location与components之间的同步问题。
20.React Router与常规路由有何不同?
前端的路由和后端的路由在实现技术上不一样,但是原理都是一样的。在 HTML5 的 history
API 出现之前,前端的路由都是通过 hash
来实现的,hash
能兼容低版本的浏览器。如果我们把上面例子中提到的 3 个页面用 hash
来实现的话,它的 URI 规则中需要带上 #
。
用户可能都察觉不到该访问地址是 Web 服务实现的路由还是前端实现的路由。
从性能和用户体验的层面来比较的话,后端路由每次访问一个新页面的时候都要向服务器发送请求,然后服务器再响应请求,这个过程肯定会有延迟。而前端路由在访问一个新页面的时候仅仅是变换了一下路径而已,没有了网络延迟,对于用户体验来说会有相当大的提升。
21.知道hoc和render props吗,它们有什么作用?有什么弊端?
1.学习 HOC 我们只需要记住以下 2 点定义:
创建一个函数, 该函数接收一个组件作为输入除了组件, 还可以传递其他的参数
基于该组件返回了一个不同的组件.
HOC 的优点:不会影响内层组件的状态, 降低了耦合度
2.render props
功能: 将一个组件内的 state 作为 props 传递给调用者, 调用者可以动态的决定如何渲染.
-
接收一个外部传递进来的 props 属性
-
将内部的 state 作为参数传递给调用组件的 props 属性方法.
缺点:
-
无法在 return 语句外访问数据
-
它不允许在 return 语句之外使用它的数据. 比如上面的例子, 不能在 useEffect 钩子或组件中的任何其他地方使用 x 和 y 值, 只能在 return 语句中访问.
嵌套:
-
它很容易导致嵌套地狱.
22.useState中的第二个参数更新状态和class中的this.setState区别?
二者参数对比:
setState( updater [,callback] ) :
updater:object/function - 用于更新数据
callback:function - 用于获取更新后最新的 state 值
useState(initState):
const [ state , setState ] = useState(initState)
state:状态
setState(updater) :修改状态的方法
updater:object/function - 用于更新数据
initState:状态的初始值
setState()使用注意事项
setState()
构造函数是唯一建议给 this.state 赋值的地方
不建议直接修改 state 的值,因为这样不会重新渲染组件
自动进行浅合并(只会合并第1层)
由于 setState() 异步更新的缘故,依赖 state 旧值更新 state 的时候建议采用传入函数的方式
- setState() 的异步问题
- setState() 在绝大多数情况下都是异步操作,更新 state 后无法直接获取最新的 state 值
useState()使用注意事项
- useState()
- 可以自定义命名
- 可以使用多个useState()
- 不具备自动浅合并的效果
- useState() 中类似setState() 异步的问题
- 调用 setState() 后组件不会立刻更新,无法立刻获取到最新的 state 值
为什么叫做 useState 而不是 createState ?
const [ state , setState ] = useState( initVal )
因为 create 的描述不准确,state 只有在组件首次渲染时才会被创建并赋予初始值 initVal。当函数组件更新时,虽然会重新执行函数组件中的每一行代码,但是 useState 底层做了特殊的处理,使得每次更新不会使用 initVal 来创建新的 state ,而是返回给我们当前的 state
setState 方式会 重新渲染组件
this.state的方式会改变值,但不会重新渲染组件(这就是为什么你改变了值,但是页面没有响应你)
在使用时。可以先使用this.state.的方式来赋值。在最后一次赋值使用setState的方式。这样组件之渲染一次达到赋值的效果。
在render()中。也就是在页面初始化阶段一定不能用state。否则会造成不断的重新渲染组件。导致崩掉。
1、二者更新数据时,第一个参数都可以传入函数
this.setState((state, props) => ({ //setState()
counter: state.counter + props.increment
}));
setCount(count => count + 1); //useState()
2、setState()可以在第2个参数传入回调, useState()没有第2个参数
this.setState(
{count: this.state.count + 1},
() => console.log(this.state.count) //可以通过第2个回调函数获取最新的state值
);
PS:函数式组件中可以通过 useEffect() 来获取最新的 state
3、setState() 自动具备浅合并功能,useState()更新引用需要手动浅合并