一、HTML篇1.语义话的目的是什么?答:用正确的标签做正确的事。
提高代码的可读性,页面内容结构化,便于开发人员的代码编写,同时提高的用户体验;有利于SEO,便于搜索引擎爬虫爬取有效信息。
存储的大小cookie4kb左右session5M
易用性cookie需自己封装session可以接受原生接口
关于storage使用的方式可以查看storage传值
二、CSS篇1.css有哪些基本的选择器,执行先后顺序?类选择器(class)、标签选择器、ID选择器!important>内联样式(非选择器)>ID选择器>类选择器>标签选择器>通配符选择器(*)
4.常用的块与行属性内标签有哪些?有什么特征块标签:div、h1~h6、ul、li、table、p、br、form。特征:独占一行,换行显示,可以设置宽高,可以嵌套块和行行标签:span、a、img、textarea、select、option、input。特征:只有在行内显示,内容撑开宽、高,不可以设置宽、高(img、input、textarea等除外)。
5.清除浮动父级div定义overflow:hidden(如果父级元素有定位元素超出父级,超出部分会隐藏,)给浮动元素父级增加标签(由于新增标签会造成不必要的渲染,不建议使用)伪元素清除浮动:给浮动元素父级增加.clearfix::after(content:‘’;display:table;clear:both;)(不会新增标签,不会有其他影响,)6.CSS3新特征圆角(border-radius)阴影(box-shadow)文字特效(text-shadow)线性渐变(gradient)变换(transform)更多的CSS选择器更多背景设置(background)色彩模式(rgba)伪元素(::selection)媒体查询(@media)多栏布局(column)图片边框(border-image)7.介绍一下盒模型答:
盒模型由内容(content)、内边距(padding)、边框(border)、外边距(margin)组成。盒模型分为IE盒模型和W3C标准盒模型。W3C标准盒模型又叫content-box,元素宽度/高度由border+padding+content组成。(属性width,height只包含内容content,不包含border和padding)IE盒模型又叫border-box,元素宽度/高度由content组成。(属性width,height包含border和padding,指的是content+padding+border。)PS:盒模型这个东西需要多理解。。。
8.CSS中有哪些长度单位?绝对长度单位:px百分比:%相对父元素字体大小单位:em相对于根元素字体大小的单位:rem相对于视口*宽度的百分比(100vw即视窗宽度的100%):vw相对于视口*高度的百分比(100vh即视窗高度的100%):vh9.display:none和visibility:hidden的区别display:none:隐藏元素,在文档布局中不在给它分配空间(从文档中移除),会引起回流(重排)。visibility:hidden:隐藏元素,但是在文档布局中仍保留原来的空间(还在文档中),不会引起回流(重绘)。
10.用CSS实现长宽为浏览器窗口一半的正方形已知父元素宽高用%width:50%;padding-top:50%;background-color:red;用vwwidth:50vw;height:50vh;background-color:red;11.用CSS实现高度为0.5像素的线条这个可以用伪类来实现
.line::before{display:block;content:"";height:1px;left:-50%;position:absolute;background-color:#333333;width:200%;//设置为插入元素的两倍宽高-webkit-transform:scale(0.5);transform:scale(0.5);box-sizing:border-box;}12.用CSS实现三角形向上
width:0;height:0;border-left:30pxsolidtransparent;border-right:30pxsolidtransparent;border-bottom:30pxsolidred;13.伪类和伪元素的区别伪类
伪元素
区别
伪类只能使用“:”,伪元素既可以使用“:”,也可以使用“::”伪元素其实相当于伪造了一个元素,伪类没有伪造元素,例如first-child只是给子元素添加样式而已。(本质区别就是是否抽象创造了新元素)13.重绘和重排是什么?如何避免?重排:当DOM的变化影响了元素的几何信息(元素的的位置和尺寸大小),浏览器需要重新计算元素的几何属性,将其安放在界面中的正确位置,这个过程叫做重排。重绘:当一个元素的外观发生改变,但没有改变布局,重新把元素外观绘制出来的过程,所以重绘跳过了创建布局树和分层的阶段。
重排需要重新计算布局树,重绘不需要,重排必定发生重绘,但是涉及到重绘不一定要重排。涉及到重排对性能的消耗更多一些。
触发重排的方法:页面初始渲染、添加/删除可见的DOM元素、改变元素位置、改变元素尺寸、改变元素内容、改变元素字体大小、改变浏览器窗口尺寸、设置style属性的值等。避免重排的方式:样式集中改变、使用absolute或fixed脱离文档流。
三、JS篇1.ES6新特性?新增块级作用域let定义变量和const定义常量变量的解构赋值模板字符串(‘${}’)默认参数(key=value)箭头函数(=>)扩展运算符(…)模块(import/export)类(class/extends)PromiseProxySymbol了解关于es6的更多知识可以看阮一峰——ES6入门教程2.闭包的理解理解:主要是为了设计私有的方法和变量。优点:可以避免全局变量造成污染。缺点:闭包会常驻内存,增加内存使用量,使用不当会造成内存泄漏。特征:(1)函数嵌套函数。(2)在函数内部可以引用外部的参数和变量。(3)参数和变量不会以垃圾回收机制回收。
3.call()、apply()、bind()的区别详情请看call()、apply()、bind()重新定义this的区别
4.原型,原型链主要是还是实现继承与扩展对象。每个函数对象都有一个prototype属性,这个属性就是函数的原型对象。原型链是JavaScript实现继承的重要方式,原型链的形成是真正是靠__proto__而非prototype。
所有的引用类型(包括数组,对象,函数)都有隐性原型属性(proto),值也是一个普通的对象。所有的引用类型的proto属性值都指向构造函数的prototype属性值。构造函数new出来一个对象,而每个对象都有一个constructor属性,该属性指向创建该实例的构造函数。实例对象通过__proto__或者object.getPrototype的方法获取原型。原型链其实就是有限的实例对象和原型之间组成有限链,就是用来实现共享属性和继承的。
后退/刷新:GET无害,POST数据会被重新提交。书签:GET产生的URL地址可以被收藏为书签,而POST不可以。数据:GET一般是用来获取数据,POST提交数据。数据类型:GET只允许ASCII字符,POST无限制。数据大小:GET大小有限制(一般来说1024字节),POST理论上来说没有大小限制。安全性:GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。可见性:GET参数通过URL传递对所有人可见,POST数据不可见。历史保留:GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。9.forEach和map的区别forEach没有返回值,map返回新的数组。map创建新数组,forEach不修改原数组。
10.JS基本数据类型的比较
11.对象的继承常见的:
原型链继承借用构造函数继承原型链+借用构造函数的组合继承(使用call或applay方法)ES6中class的继承(class可以通过extends关键字实现继承)12.简述一下你理解的面向对象面向对象是基于万物皆对象这个哲学观点.把一个对象抽象成类,具体上就是把一个对象的静态特征和动态特征抽象成属性和方法,也就是把一类事物的算法和数据结构封装在一个类之中,程序就是多个对象和互相之间的通信组成的。
面向对象具有封装性,继承性,多态性。
封装:隐蔽了对象内部不需要暴露的细节,使得内部细节的变动跟外界脱离,只依靠接口进行通信.封装性降低了编程的复杂性。继承:使得新建一个类变得容易,一个类从派生类那里获得其非私有的方法和公用属性的繁琐工作交给了编译器。多态:继承和实现接口和运行时的类型绑定机制所产生的多态,使得不同的类所产生的对象能够对相同的消息作出不同的反应,极大地提高了代码的通用性.。
13.==和===的区别相同点:都是判定两个值是否相等不同点:==只比较值不比较类型,而===会判断类型
14.数组有哪些方法详细可以看数组一些常用的方法
15.普通的数组去重(笔试一般都会有)在不涉及去重对象、NaN等情况下。
IndexOf()双重for循环es6的[…newSet()]filter()sort()面试随便写一两种就行、项目直接用newSet()(方便)注:如果有多维数组如[1,[2],[3,[2,3,4,5]]]先扁平化再去重,用Array.flat(Infinity)实现扁平化。
16.Promise含义:异步编程的一种解决方案,用来解决回调地狱。三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)(Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。)
resolved函数作用:将Promise对象的状态从“未完成”变为“成功”(即从pending变为resolved)。reject函数的作用:将Promise对象的状态从“未完成”变为“失败”(即从pending变为rejected)。
Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。then:Promise实例添加状态改变时的回调函数。可以接受两个回调函数作为参数。第一个回调函数是Promise对象的状态变为resolved时调用,第二个回调函数是Promise对象的状态变为rejected时调用。
缺点:无法取消Promise,一旦新建它就会立即执行,无法中途取消。如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。
更多详情请看Promise对象
21.排序方式冒泡排序:比较所有相邻元素,如果第一个比第二个大,则交换它们。选择排序:找到数组中的最小值,选中它并将其放置在第一位。插入排序:从第二个数开始往前比,比它大就往后排。归并排序:把数组劈成两半,再递归地对数组进行“分”操作,直到分成一个个单独的数。快速排序:从数组中任意选择一个基准,所有比基准小的元素放到基准前面,比基准大的元素放到基准的后面。22.数组操作方法会改变原数组会改变:push(),pop(),shift(),unshift(),splice(),sort(),reverse()。不变:concat(),split(),slice()。
24.如何判断一个对象是否存在?直接!XXX这样会报错,因为没有定义
建议使用typeof运算符,判断XXX是否有定义。
4.如何解决跨域什么是跨域?浏览器从一个域名的网页去请求另一个域名的资源时,域名、端口、协议任一不同,都是跨域常见的:1、JSONP跨域原理:利用script标签可以跨域请求资源,将回调函数作为参数拼接在url中。后端收到请求,调用该回调函数,并将数据作为参数返回去,注意设置响应头返回文档类型,应该设置成javascript。2、跨域资源共享(CORS)目前最常用的一种解决办法,通过设置后端允许跨域实现。3、nginx反向代理跨域限制的时候浏览器不能跨域访问服务器,node中间件和nginx反向代理,都是让请求发给代理服务器,静态页面面和代理服务器是同源的,然后代理服务器再向后端服务器发请求,服务器和服务器之间不存在同源限制。4、WebSocket协议跨域5、proxy前端配置一个代理服务器(proxy)代替浏览器去发送请求:因为服务器与服务器之间是可以通信的不受同源策略的影响。详细可看九种常见的前端跨域解决办法
5.网页从输入url到页面加载发生了什么DNS解析TCP连接发送HTTP请求服务器处理请求并返回HTTP报文浏览器解析并渲染页面————>1.解析文档构建dom树。2.构建渲染树。3.布局与绘制渲染树。连接结束6.HTTP传输过程含义:从建立连接到断开连接一共七个步骤,就是三次招手四次挥手
TCP建立连接浏览器发送请求命令浏览器发送请求头服务器应答服务器回应信息服务器发送数据断开TCP连接7.浏览器如何渲染页面的?浏览器解析html源码,将HTML转换成dom树,将CSS样式转换成stylesheet(CSS规则树),浏览器会将CSS规则树附着在DOM树上,并结合两者生成渲染树(RenderTree)生成布局(flow),浏览器通过解析计算出每一个渲染树节点的位置和大小,在屏幕上画出渲染树的所有节点合成绘制生成页面。8.对MVC和MVVM的理解M:model(数据模型),V:view(视图),C:controller(逻辑处理),VM:(连接model和view)MVC:单向通信。必须通过controller来承上启下。MVVM:数据双向绑定,数据改变视图,视图改变数据。
9.深拷贝,浅拷贝浅拷贝:创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。
深拷贝:将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象。
总而言之,浅拷贝改动拷贝的数组原数组也会变(慎用!项目中很多地方共用的数组都会变)。深拷贝修改新数组不会改到原数组。实现方法浅拷贝:
Object.assign()函数库lodash的_.clone方法es6的展开运算符…Array.prototype.concat()Array.prototype.slice()letarr=[{name:"uzi"}]1.letarr1=Object.assign({},arr);arr1[0].name="xiaoming"2.letarr2=_.clone(arr);arr2[0].name="mlxg"3.letarr3=[...arr]arr3[0].name="xiaohu"4.letarr4=arr.concat()arr4[0].name="zitai"5.letarr5=arr.slice();arr5[0].name="clearLove"console.log(arr[0].name==arr[1].name==arr[2].name==……);//truearr[0].name="clearLove"深拷贝:
节流:高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率。应用场景:window对象的resize、scroll事件拖拽时候的mousemove射击游戏中的mousedown、keydown事件文字输入、自动完成的keyup事件
vue中使用详情可以看vue中使用防抖和节流
11.性能优化举例:
babel将es6、es7、es8等语法转换成浏览器可识别的es5或es3语法。
13.git和svn的区别SVN是集中式版本控制系统,版本库是集中放在中央服务器的,首先要从中央服务器哪里得到最新的版本,干完活后,需要把自己做完的活推送到中央服务器。集中式版本控制系统是必须联网才能工作(如果在局域网还可以,带宽够大,速度够快,如果在互联网下,如果网速慢的话,就纳闷了)
Git是分布式版本控制系统,没有中央服务器的,每个人的电脑就是一个完整的版本库,这样,工作的时候就不需要联网了,因为版本都是在自己的电脑上。自己在电脑上改了文件A,其他人也在电脑上改了文件A,这时,只需把各自的修改推送给对方,就可以互相看到对方的修改了。
14.webSocketwebSocket:可以让服务器主动向客户端发送消息,适合开发聊天室,多人游戏等协作应用。
WebSocket协议是基于TCP的一种新的网络协议。在WebSocketAPI中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
ES6模块语法是JavaScript模块的标准写法,坚持使用这种写法,取代Node.js的CommonJS语法。使用import取代require()。
//CommonJS的写法constmoduleA=require('moduleA');constfunc1=moduleA.func1;constfunc2=moduleA.func2;//ES6的写法import{func1,func2}from'moduleA';使用export取代module.exports。
//commonJS的写法varReact=require('react');varBreadcrumbs=React.createClass({render(){return;}});module.exports=Breadcrumbs;
//ES6的写法importReactfrom'react';classBreadcrumbsextendsReact.Component{render(){return;}};exportdefaultBreadcrumbs;
16.事件循环(EventLoop)原因:JavaScript是单线程,所有任务需要排队,前一个任务结束,才会执行后一个任务。
所有任务可以分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)。同步任务:在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;异步任务:不进入主线程、而进入"任务队列"的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。
同步和异步任务分别进入不同的执行环境,先执行同步任务,把异步任务放入循环队列当中挂起,等待同步任务执行完,再执行队列中的异步任务。异步任务先执行微观任务,再执行宏观任务。一直这样循环,反复执行。
微任务:Promise.then、catch、finally、async/await。宏任务:整体代码Script、UI渲染、setTimeout、setInterval、Dom事件、ajax事件。
详情可看JavaScript运行机制详解:再谈EventLoop
17.什么是单页面应用(SPA)一个系统只加载一次资源,之后的操作交互、数据交互是通过路由、ajax来进行,页面并没有刷新。在一个页面上集成多种功能,甚至整个系统就只有一个页面,所有的业务功能都是它的子模块,通过特定的方式挂接到主界面上。优点:
前后端分离良好的交互体验——用户不用刷新页面,页面显示流畅减轻服务器压力——服务器只出数据共用一套后端代码——多个客户端可共用一套后端代码加载速度快,内容的改变不需要重新加载整个页面,对服务器压力小缺点:
SEO难度高——数据渲染在前端进行页面初次加载比较慢,页面复杂提高很多多页面:一个应用多个页面,页面跳转时整个页面都刷新,每次都请求一个新的页面有点:SEO效果好缺点:页面切换慢,每次切换页面需要选择性的重新加载公共资源
详情可以参考构建单页Web应用
18.什么叫优雅降级和渐进增强?渐进增强(ProgressiveEnhancement):一开始就针对低版本浏览器进行构建页面,完成基本的功能,然后再针对高级浏览器进行效果、交互、追加功能达到更好的体验。优雅降级(GracefulDegradation):一开始就构建站点的完整功能,然后针对浏览器测试和修复。
在传统软件开发中,经常会提到向上兼容和向下兼容的概念。渐进增强相当于向上兼容,而优雅降级相当于向下兼容。向下兼容指的是高版本支持低版本的或者说后期开发的版本支持和兼容早期开发的版本,向上兼容的很少。大多数软件都是向下兼容的。
四、VUE篇1.数据双向绑定原理答:通过数据劫持结合发布—订阅模式,通过Object.defineProperty()为各个属性定义get、set方法,在数据发生改变时给订阅者发布消息,触发相应的事件回调。
2.vue生命周期概念:从创建、初始化数据、编译模板、挂载DOM、渲染-更新-渲染、卸载等一系列过程,称为为Vue实例的生命周期。
vue2.0
onBeforeMountonMountedonBeforeUpdateonUpdatedonBeforeUnmountonUnmounted
详情可看vue3.0官网生命周期钩子
3.组件之间如何传值一、Vue父子组件之间传值
子组件通过props来接受数据和通过$emit来触发父组件的自定义事件;二、兄弟组件之间的传值
建一个公共组件bus.js.。传递方通过事件触发bus.$emit。接收方通过在mounted(){}生命周期里触发bus.$on。三、可以通过VUEX来跨组件传参。
四、父孙传值$attrs(向下)$listeners(向上)
五、祖先和子孙传值provide/inject
六、获取父组件实例this.$parent详情可看vue之组件的传参方式
4.路由之间如何传参通过router-link路由导航跳转传递
params在地址栏中不显示参数,刷新页面,参数丢失,其余方法在地址栏中显示传递的参数,刷新页面,参数不丢失。
详情请看Vue-router之简单的路由传参三种方法
5.谈一谈VUEX原理:Vuex是专门为vue.js应用程序设计的状态管理工具。构成:
state:vuex的基本数据,用来存储变量,存放的数据是响应式的。mutations:提交更改数据,同步更新状态。actions:提交mutations,可异步操作。getters:是store的计算属性。modules:模块,每个模块里面有四个属性。关于VUEX如何使用可以看VUE的传值问题6.如何解决vuex页面刷新数据丢失问题?原因:因为vuex里的数据是保存在运行内存中的,当页面刷新时,页面会重新加载vue实例,vuex里面的数据就会被清空。解决方法:将vuex中的数据直接保存到浏览器缓存中。(一般是用sessionStorage)
7.computed和watch的区别?computed值有缓存、触发条件是依赖值发生更改、watch无缓存支持异步、监听数据变化
computed:是计算属性,依赖其它属性值,并且computed的值有缓存,只有它依赖的属性值发生改变,下一次获取computed的值时才会重新计算computed的值;watch:更多的是观察的作用,支持异步,类似于某些数据的监听回调,每当监听的数据变化时都会执行回调进行后续操作;
computed应用场景:需要进行数值计算,并且依赖于其它数据时,应该使用computed,因为可以利用computed的缓存特性,避免每次获取值时,都要重新计算;watch应用场景:需要在数据变化时执行异步或开销较大的操作时,应该使用watch,使用watch选项允许我们执行异步操作(访问一个API),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。
详情请看Vue的计算属性与methods、watch的区别
9.Route和router的区别route:是路由信息对象,包括“path,parms,hash,name“等路由信息参数。Router:是路由实例对象,包括了路由跳转方法,钩子函数等。10.v-show和v-if的区别v-if:组件的销毁和重建,更适合带有权限的操作,切换开大。如果开始条件为false则什么都不做,只有为true才会编译。v-show:css切换,隐藏显示更适合频繁切换。在任何情况下都会被编译,然后被缓存,而且dom元素会被保留。11.vue中数据变了但是视图不跟新怎么解决?原因:
数组数据变动:使用某些方法操作数组,变动数据时,有些方法无法被vue监测。Vue不能检测到对象属性的添加或删除。异步更新队列:数据第一次的获取到了,也渲染了,但是第二次之后数据只有在再一次渲染页面的时候更新,并不能实时更新。12.vue中data为什么是函数而不是对象?官网中有这么一段介绍,详情可以看组件的复用
意思就是,在Vue中组件是可以被复用的,而当data是一个函数的时候,每一个实例的data都是独立的,不会相互影响了。
更详细的解释==>
13.vue中父子组件传值,父组件异步请求,子组件不能实时更新怎么解决?(vue中数据不能实时更新怎么解决?)首先了解父子组件生命周期执行顺序==>加载渲染数据过程父组件beforeCreate-->父组件created-->父组件beforeMount-->子组件beforeCreate-->子组件created-->子组件beforeMount-->子组件mounted-->父组件mounted-->原因:因为生命周期只会执行一次,数据是要等到异步请求以后才能拿到,那么子组件的mounted钩子执行的时候,还没有拿到父组件传递过来的数据,但是又必须要打印出来结果,那这样的话,就只能去打印props中的默认值空字符串了,所以打印的结果是一个空字符串。解决办法:
使用v-if控制组件渲染的时机初始还没拿到后端接口的异步数据的时候,不让组件渲染,等拿到的时候再去渲染组件。使用v-if="变量"去控制,初始让这个变量为false,这样的话,子组件就不会去渲染,等拿到数据的时候,再让这个变量变成true,举例:data(){return{isTrue:false//初始为false};},monted(){this.$post.a.b.c.getData(res=>{if(res.result){this.isTrue=true}})}使用watch监听数据的变化举例:props:{tableData:{type:Array,default:[],},},watch:{tableData(val){console.log(val)}},使用VueX14.父子组件传参emit如何传多个参数?子组件:
submit(){this.$emit('g',1,2,3,4,5)}父组件
g(val1,val2,val3,val4,val5){console.log(val1,val2,val3,val4,val5)}15.Vue路由跳转方式router-link标签跳转this.$router.push()this.$router.replace()this.$router.go(n):(0:当前页,-1上一页,+1下一页,n代表整数)16.条件渲染v-if与v-for优先级
列表渲染指南
17.Vue中$nextTick作用与原理?异步渲染、获取DOM、Promise等。
Vue在更新DOM时是异步执行的,在修改数据后,视图不会立刻更新,而是等同一事件循环中的所有数据变化完成之后,再统一进行视图更新。所以修改完数据,立即在方法中获取DOM,获取的仍然是未修改的DOM。$nextTick的作用是:该方法中的代码会在当前渲染完成后执行,就解决了异步渲染获取不到更新后DOM的问题了。nextTick的原理:nextTick的原理:nextTick的原理:nextTick本质是返回一个Promise。
应用场景:
在created()里面想要获取操作Dom,把操作DOM的方法放在$nextTick中。在data()中的修改后,页面中无法获取data修改后的数据,使用$nextTick时,当data中的数据修改后,可以实时的渲染页面官网中是这么说的
18.Vue中for循环为什么加key?为了性能优化,因为vue是虚拟DOM,更新DOM时用diff算法对节点进行一一比对,比如有很多li元素,要在某个位置插入一个li元素,但没有给li上加key,那么在进行运算的时候,就会将所有li元素重新渲染一遍,但是如果有key,那么它就会按照key一一比对li元素,只需要创建新的li元素,插入即可,不需要对其他元素进行修改和重新渲染。key也不能是li元素的index,因为假设我们给数组前插入一个新元素,它的下标是0,那么和原来的第一个元素重复了,整个数组的key都发生了改变,这样就跟没有key的情况一样了。
五、REACT篇1.React的生命周期(版本17.0.2)概念:每个组件都包含“生命周期方法”,你可以重写这些方法,以便于在运行过程中特定的阶段执行这些方法。挂载:
constructor():在React组件挂载之前,会调用它的构造函数。(注:如果不初始化state或不进行方法绑定,则不需要为React组件实现构造函数。)render():class组件中唯一必须实现的方法。componentDidMount():在组件挂载后(插入DOM树中)立即调用。依赖于DOM节点的初始化应该放在这里。更新
render():class组件中唯一必须实现的方法。componentDidUpdate():在更新后会被立即调用。首次渲染不会执行此方法。卸载
componentWillUnmount():在组件卸载及销毁之前直接调用。在此方法中执行必要的清理操作,例如,清除timer,取消网络请求或清除在componentDidMount()中创建的订阅等。具体可用一张图来表示
详情可看官网组件的生命周期
2.React如何获取组件对应的DOM元素?ref:通过当前class组件实例的一些特定属性来直接获取子节点实例。注意:不能在函数组件上使用ref属性,因为他们没有实例。findDOMNode():findDOMNode是一个访问底层DOM节点的应急方案(escapehatch)。注意:在大多数情况下,不推荐使用该方法,因为它会破坏组件的抽象结构。严格模式下该方法已弃用。findDOMNode不能用于函数组件。详情请看官网:ReactDOM3.React中可以在render访问refs吗?为什么?答:不能,因为在render阶段refs还未生成。DOM的读取在pre-commit阶段,DOM的使用在commit阶段。
4.React中什么是受控组件和非控组件?渲染表单的React组件还控制着用户输入过程中表单发生的操作。被React以这种方式控制取值的表单输入元素就叫做“受控组件”。
受控组件更新state的流程:
可以通过初始state中设置表单的默认值
每当表单的值发生变化时,调用onChange事件处理器
事件处理器通过事件对象e拿到改变后的状态,并更新组件的state
一旦通过setState方法更新state,就会触发视图的重新渲染,完成表单组件的更新
对于受控组件来说,输入的值始终由React的state驱动。你也可以将value传递给其他UI元素,或者通过其他事件处理函数重置,但这意味着你需要编写更多的代码。详情看官网受控组件
非受控组件如果一个表单组件没有valueprops(单选和复选按钮对应的是checkedprops)时,就可以称为非受控组件。在非受控组件中,可以使用一个ref来从DOM获得表单值。而不是为每个状态更新编写一个事件处理程序。
官网解释:要编写一个非受控组件,而不是为每个状态更新都编写数据处理函数,你可以使用ref来从DOM节点中获取表单数据。
因为非受控组件将真实数据储存在DOM节点中,所以在使用非受控组件时,有时候反而更容易同时集成React和非React代码。如果你不介意代码美观性,并且希望快速编写代码,使用非受控组件往往可以减少你的代码量。否则,你应该使用受控组件。官网非受控组件
总结:页面中所有输入类的DOM如果是现用现取的称为非受控组件,而通过setState将输入的值维护到了state中,需要时再从state中取出,这里的数据就受到了state的控制,称为受控组件。
5.谈一谈React的状态提升?官网是这么解释的:
多个组件需要反映相同的变化数据,这时我们建议将共享状态提升到最近的共同父组件中去。
简单来说就是:将多个组件需要共享的状态提升到它们最近的父组件上,在父组件上改变这个状态然后通过props分发给子组件。对子组件操作,子组件不改变自己的状态。可看官网的温度计数器例子
6.为什么要使用虚拟DOM?(什么是VirtualDOM?)VirtualDOM算法用一张图片来表示
虚拟DOM那就是虚拟DOM概念出现的地方,并且其性能要比真实DOM好得多。虚拟DOM只是DOM的虚拟表示。每当我们的应用程序状态更改时,虚拟DOM就会更新,而不是真实DOM。
React如何使用虚拟DOM
在React中,每个UI块都是一个组件,每个组件都有一个状态。React遵循可观察的模式,并监听状态变化。当组件的状态改变时,React更新虚拟DOM树。虚拟DOM更新后,React然后将虚拟DOM的当前版本与虚拟DOM的先前版本进行比较。此过程称为“差异化”。
一旦React知道哪些虚拟DOM对象已更改,然后React就会在真实DOM中仅更新那些对象。与直接操作真实DOM相比,这使性能好得多。
原因:对于局部的小视图的更新,重新构造整棵DOM没问题;但是对于大型视图,如全局应用状态变更的时候,需要更新页面较多局部视图的时候,这样的做法不可取。VirtualDOM只是加了一些特别的步骤来避免了整棵DOM树变更。
简而言之就是:
频繁的DOM操作昂贵且性能沉重。虚拟DOM是真实DOM的虚拟表示。React使用虚拟DOM来增强其性能。JS和DOM之间的缓存。更深入可看深度剖析:如何实现一个VirtualDOM算法
六、其它篇1.开发中遇到的bug?项目中或者地图中遇到引入如图片不显示。解决办法:使用require动态引入图片。详细可看:设置content加载不出图标
合并多个对象并去重原因:普通去重不能去除对象。解决方法:可看数组中有对象去除
移动端1px问题原因:手机分辨率高,它的实际物理像素数更多了,不同手机屏幕分辨率不同,一般都差不多2倍左右,所以显得更粗。解决方法:可以参考第二篇CSS的11题。
移动端点击穿透问题原因:
后言为什么离职?多主观少客观参考:
我在上一家公司XX能力已经得到了充分的锻炼,现在想去一个更大的平台提升自己的技能,通过了解,贵公司也正好符合我的期待,所以想来挑战一下。
其实上一家公司的工作氛围特别好,大家互相帮助能学习成长很多,但因为贵公司XXX特别吸引我,而我也正好有进一步提升发展的打算,所以才决定来试一试。
面试结尾——面试官问:还有什么要问的?为了更好地胜任这个岗位,我还需要补充哪些前端技能?前端在公司的发展前景是怎样的?有什么晋升机制?在什么条件下,可以获得晋升机会?对于未来加入贵公司前端团队,你对我有什么期望?