一、HTML和CSS
1、css动画实现:
animation(动画):keyframes提供了更多的控制;可以指定播放次数或是无限循环;可以定义动画的中间状态
transition(过渡):需要事件来触发;是一次性的,不能重复发生;只能定义开始和结束状态,不能自定义中间状态;
transform(变形):元素的缩放、旋转、移动和倾斜
translate(移动):transform的移动属性
2、移动端自适应方案:
1)rem:相对于根元素的字体大小单位,em是相对于父级元素字体大小的单位,flexible
2)vw:postcss-px-to-viewport可以自动转换vw
3)媒体查询:处理特定状态
4)<meta content="width=device-width,initial-scal=1.0,maximum-scale=1.0,user-scalable=0;" name="viewpott" />
没有设置viewport会出现:网页被缩小,字体很丑,排版错乱;有了viewport能通过缩放让浏览器完全显示整个网页
3、垂直居中:line-height+text-align;absolute+transform;flex+aligin-items+justify-content;table-cell
4、flex都有哪些属性:flex-direction主轴方向、flex-wrap换行、justify-content主轴对其方式(flex-start/flex-end/center/space-between/space-around)、align-items交叉轴对齐方式、align-content多根轴线对齐方式
5、选择器优先级:!import>内联样式>id选择器>class选择器>tag选择器>*(通配符)>继承>默认
伪类选择器::link>:visited>:focus>:hover>:active fist-of-type、last-of-type、only-of-type、only-child、nth-child、:enable、:disable、:checked
6、link和import的区别:
1)link是html标签,不仅可以加载css,还可以定义rss、rel等属性,import是css导入样式的方法;
2)link标签引入的css同时加载,import引入的css在页面加载完毕之后加载
3)link可以使用js来动态引入,import不行
7、SVG和Canvas:svg是使用xml描述2d图形,canvas是通过js来绘制2d图形的
8、盒子模型:宽度=content+padding+border+margin
9、position的值有哪些?static(文档流)relative(相对定位)absolute(绝对定位:不为static的父级元素)fixed(固定定位:可视窗口)
10、绘制三角形的原理:把高度和宽度设置为0,然后设置边框样式
11、display有哪些参数?block(块显示)inline-block(行内)none(隐藏)inline(内联-行内)table(表格显示)list-item(项目列表)
12、行内元素和块级元素有啥区别?行内元素只有左右的margin和padding,不能设置宽和高,宽高取决于内部内容;块级元素允许设置宽高,padding、margin,但不允许左右存在其他元素
13、H5新特性?
1)语义化标签?常见语义化标签:h1-h6、p、header、title、footer、nav、section、article、table、ul、dt、strong;有利于不同设备解析(盲人阅读器),区分哪些优先阅读;有利于搜索引擎的抓取;有利于团队的开发维护;
2)新表单类型:input新增type:email、number、url、range、search、color、tel、date;新增属性:min、max、autofocus、multiple、required、pattern
3)视频和音频:<video><audio>
4)canvas绘图和svg矢量图形
14、h5网页怎么显示真实的1px边框和12px字体大小?
1)使用box-shodow来模拟边框:但是会有阴影颜色变浅
2)背景色渐变,一半有颜色一半设置透明
3)伪类+transform:用before或after做border,并transform的scale缩小一半
15、三栏布局实现方式:
1)float:left;float:right;margin-left,margin-right(main标签最后加载)
2)BFC:float:left;float:right;overflow:hidden(main标签最后加载)
3)外层设置display:table,width:100%;内部标签设置display:table-cell
4)绝对定位:左右设置absolute,中间的设置margin
16、BFC:块级格式上下文,是页面上一个独立的容器,容器中的子元素不会影响到外面元素;
二、JS
1、高阶函数:函数可以作为参数传递;函数可以作为返回值输出
2、闭包?:
函数执行作用域内的变量,被另一个作用域引用,造成该变量不能在函数执行后销毁,就形成了闭包
使用场景:原生的setTimeout传递的第一个函数无法带参数,可以利用闭包实现传参;回调、事件绑定;封装私有变量
3、作用域:执行上下文中声明的变量和声明的作用范围,分为块级作用域和函数作用域
4、isNAN、escape、 eval 、 parseFloat等js系统方法总结
5、js数据类型
基础数据类型:undefined、null、number、boolean、string
object(引用类型)中还包括:array、function、date、regExp、error、arguments对象
基础类型和引用类型的区别:一个存在堆内存,一个在栈内存;一个是值的引用,一个是地址
typeof 能检测除了null以外的数据类型,null时返回object,除了function能返回function以外,其他都返回object
Object.prototype.toString.call() 能检测所有类型
强制类型转换:
String()、Number()、Boolean()、parseInt()
一元加减操作符等同于Number();加法操作符如果一个字符串一个数字,会合成字符串;非与或;相等和不相等;全等和不全等;关系操作符
6、proxy理解:代理,new Proxy(target,handler)当代理对象中的某个值被访问或是更新就会触发相应的get和set方法
7、js继承方式:原型链继承、构造函数继承、组合继承
8、node的事件方法:emitter.addListener() emitter.emit() emitter.on() emitter.removeListener()
9、Promise:用于解决回调地狱,用于处理异步编程:new Promise().then().then().catch();
状态值:pending(等待中)fulfilled(已完成)rejected(已拒绝)
async/await也是基于promise实现的
generator:yield暂停代码,next()继续执行代码
三兄弟:promise.all()全部完成输出完成,一个拒绝直接输出拒绝; promise.race()一个完成或拒绝就输出结果;promise.allSettled()所有的完成或决绝的结果对应输出
promise和settimeout有什么区别 => this.$nexttick
settimeout还是最后,因为本质上讲settimeout反回的异步函数,是一个全新的任务队列,就必须等待之前的所有任务队列全部执行完毕才会执行,所以总体来讲,三个中settimeout性能最差,会导致2次浏览器重绘
console.log(1);
setTimeout(()=>{
console.log(2)
},100)
Promise.resolve().then(()=>{
console.log(3);
})
console.log(4)
10、函数防抖和节流:持续触发事件resize、scroll、mousemove避免频繁执行函数
防抖debounce:触发事件后在n秒内函数只能执行一次
节流throttle:连续触发事件但是n秒内只执行一次,停止触发事件还会再执行一次;时间戳版和定时器版
11、如何理解原型和原型链?构造函数是什么?
每个对象在创建的时候就会与之关联的另一个对象,这个对象就是原型,每一个对象都会从原型继承属性;原型链就是由相互关联的原型组成的链状结构;
每一个构造函数都有一个prototype指针指向他的原型,构造函数被实例化之后具有一个proto属性指向构造函数的原型
构造函数constructor本身就是一个函数,用于创建对象,使用new来生成实例(使用instanceof来确认实例与原型的继承关系)
12、this、apply、call、bind:改变this指向
this永远指向最后调用它的那个对象,匿名函数的this永远指向window,vue中的this指向Vue实例
改变this指向的方法:箭头函数:this始终指向函数定义时的this,而不是执行时;函数内部使用let _this = this;
apply和call类似,传入参数不同,apply是数组,call是参数列表;bind是创建一个新的函数,需要手动调用
13、this指向问题?在严格模式和非严格模式的区别?
1)全局作用域下的this:都指向window;
2)全局作用域下函数中的this:严格模式指向undefined,非严格模式指向window;箭头函数都指向window;
3)对象中的函数中的this:指向调用这个函数的对象
4)构造函数中的this:指向实例对象
5)事件处理中的this:指向触发事件的目标对象
13、es中新类型symbol:1)作为对象属性的唯一标识符,防止对象属性发生冲突,避免在属性名相等的时候发生属性覆盖:[Symbol('name')]: ''; Object.getOwnPropertySymbols(target);2)用来代替常量,const TYPE_1 = Symbol();3)定义类的私有属性/方法
14、js设计模式:
1)构造函数模式:用构造函数来生成对象
2)工厂模式:jquery中的$选择器就是工厂模式创建的
3)单例模式:一个类智能创建一个实例,比如vuex和redux中的store
4)代理模式:proxy对象拦截操作
5)观察者模式:vue响应式,eventEmitter
6)适配器模式:实现兼容性
7)装饰器模式:为对象添加新功能,不改变原有的结构和功能,将函数的核心功能和装饰功能区分开
8)迭代器模式:ES6中的Map、Set等,for...of
9)外观模式:封装一个统一的事件处理中心
10)状态模式:state、promise
11)命令模式:将请求封装成一个对象
15、深拷贝(对象):JSON.parse(JSON.stringify(obj));递归赋值,js里的变量永远是值传递,只有对象的引用才会有深拷贝问题
16、new:新生成一个对象;链接到原型;绑定this;返回return中的值
17、变量提升?函数声明可以被提升,赋值变量后的函数没有被提升
18、require和import的区别
require运行时加载,可以运用在代码任何地方;import编译时加载,效率更高,不一定要写在开头,具有提升效果;
require遵循commonjs,本质是赋值过程,输入时必须查找对象属性;import遵循es6,本质是解构过程;require实际是加载了整个模块,然后从模块中读取某个方法,而import是加载了需要的方法,其他的不加载
19、let、var、const
let/const块级作用域,暂存死区(不存在变量提升),不允许重复声明
const一旦声明必须赋值(也可以用symbol赋值),不能用null占位,声明后不能再修改,如果声明的是复合类型数据,可以修改其属性
20、js严格模式:
1)不允许给没有声明的变量赋值,不能对变量调用delete,不能使用标识符做变量名
2)不允许给只读对象属性赋值,不可配置属性不能使用delete,不可扩展的对象不能添加属性,属性名必须唯一
3)命名函数的参数必须唯一,函数参数与arguments独立,只能在脚本顶级和函数内部声明函数,if语句中不能声明
4)eval()在包含上下文中不再创建变量或函数
5)抑制this,严格模式下的this始终指向指定的值
21、柯里化:首先填充几个参数,再返回一个新的函数,为函数预置通用参数
const add = function add(x) {
return function (y) {
return x + y
}
}
const add1 = add(1)
add1(2) === 3
add1(20) === 21
22、数组操作:map、forEach、filter、some(或)、every(与)、join(连接字符串)、push/pop(末尾入)、unshift/shift(头部入)、sort/reverse(排序/翻转,改变原数组)、
contact(连接数组,不影响原数组)、slice(start,end)返回截断后的新数组,不改变原数组、splice(start,number,value)返回删除元素组成的数组,value为插入项,改变原数组
indexOf/lastIndexOf(查找数组项,放回对应下标)、reduce/reduceRight(求和)、flat(数组扁平化,多维数组-》一维数组)
数组乱序:arr.sort(()=>{return Math.random() - 0.5})
23、函数声明和函数表达式的区别?函数声明在js解析时可以函数提升,函数表达式只能在赋值之后才能使用
24、事件委托是什么?利用事件流的冒泡特性把子节点的事件绑定父节点上,然后回调里面使用事件对象进行区分;可以利用一个事件处理程序来完成某一类型的所有事件;减少内存消耗,减少dom操作
26、js加载位置:
三、VUE
- MVVM的理解:Model-View-ViewModel数据驱动视图:双向数据绑定 (MVC-Model-View-Controller)单向通信
- vue生命周期:beforeCreate、created(完成provide/inject和状态的初始化)、beforeUpdate、updated、beforeMount、mounted(将render函数转化为vnode,创建真实dom)、activated(被keep-alive包裹的组件,created和mounted不会被触发)、deactivated(离开当前激活的组件)、beforeDestory、destoryed
- vue双向绑定原理--js实现双向绑定:主要是通过object对象的defineProperty属性,重写data的setter和getter函数,在get函数中更改原数据,在set函数中更改视图
- 输入框内容变化,data数据变化,view=》model;data数据变化,显示文本变化,model=》view;相当于getter、setter
- vue组件间通讯:props/$emit;eventBus($on/$emit/$off);vuex;provide/inject(跨组件通信);slot插槽;ref;
- computed和watch:computed是计算属性,更多用于计算值的场景,在getter执行后会缓存;watch更多是观察作用,用于观察props $emit或本组件的值,当数据变化时执行后续操作,无缓存性,页面重新渲染时值不变化也会执行
- vue动态组件:<component :is= />
- vue动态路由实现:router.addRoutes() 路由传参:/:id query:{} params:{}
- keep-alive工作原理:用于保存组件的渲染状态,避免组件反复创建和渲染;通常用于动态组件和router,include定义缓存白名单,exclude定义缓存黑名单,max定义缓存组件上限
- vue-router钩子函数:beforeEach()全局前置守卫,进入路由之前调用;afterEach()全局后置守卫,进入路由之后调用;beforeResolve()全局解析守卫;
- vuex使用:组件通过dispatch一个action,action通过commit一个mutation,mutation来改变state,最后重新执行render生成新的vnode,刷新组件
- action和mutation的区别:mutation是同步函数,action是异步函数,mutation是修改state的唯一途径,action不进行状态的直接更改,而是通过commit触发mutation,可以同时提交多个mutation
- dom在哪个vue的生命周期渲染完成的?
- 如何解决修改数据页面不刷新的问题?为何出现该问题? this.$set,vue.js无法检测到对象属性的增加和修改,vue在初始化实例时将对象属性转化为getter/setter,所以属性必须在data对象上才能让vue.js转化它
- vue中的template如何理解?
- axios和ajax的区别
- ajax是针对MVC编程,不符合现在MVVM潮流;axios是promise的实现版本,符合es规范,提供了一些并发请求接口
- nextTick: 在下次dom更新循环结束之后再执行
四、React
1、react的优点:
1)遵循从上到下的单向响应数据流,减少重复代码;
2)使用虚拟DOM来更新真正的dom,减少DOM操作成本,提高效率;
3)JSX语法(对es支撑很友好)
2、react如何获取真正的dom:ReactDOM.findDOMNode()或this.$refs
3、react生命周期:
1)设置默认属性defaultProps;2)设置初始化状态state;3)componentWillMount()组件即将被渲染;4)render()组件渲染;
5)componentDidMount()组件渲染后触发,此时有了真正的Dom;6)componentWillReceiveProps()组件接受到属性;
7)shouldComponentUpdate()组件接收到新属性或状态改变时触发;8)componentWillUpdate()组件即将被更新;
9)componentDidUpdate()组件更新完成,页面产生新的dom;10)componentWillUnmount()组件销毁时触发;
4、react组件是通过什么去判断是否刷新的:通过判断state是否变化
5、bind函数的位置:写在render方法里会导致组件状态变更时重复触发bind函数的执行,严重影响性能;写在constructor中仅在组件初始化时调用,绑定自身作用域,缺点是每个事件都要绑定一次,写起来比较麻烦
6、虚拟dom:用js这种抽象化的方式来渲染dom树结构,实现了跨平台的能力;其核心是diff算法,减少了js操作真实dom所带来的性能消耗
7、diff算法:对比新老dom的变化,将变化的部分更新到视图中;遍历虚拟dom,对比节点的属性及子节点,只修改变化的地方,其他的保持不变;
8、key值:作用是给每个节点做唯一标识,使得diff算法能够正确识别节点并对其进行更新操作,可以更高效的更新虚拟dom;不推荐用index下标来表示key值,在数组中间追加元素时会导致后面的节点都重新渲染,最好使用id来作为唯一标识
9、react-router:BrowserRouter和HashRouter都会创建history对象,项目中有服务器的web请求我们就用的BrowserRouter
用<Switch>组件将多个<Route>包裹在一起用于渲染第一个路径匹配的route
标签渲染<Link to="/" >Home</Link> 重定向<Redirect to="/index" />
10、redux:react状态管理机制,将数据统一存储在store状态树中,组件通过调用dispatch方法触发一个action来更新store树,其他组件可以通过订阅store中的状态值来刷新视图
核心:provider:顶级组件来存放store,使得所有组件都可以在redux的控制下;connect:mapStateToProps将redux的值映射到props中,mapDispatchToProps将dispatch变成props直接使用
11、react组件通信:自上而下单向数据流,一层一层传递props,不需要props的就有context来实现数据共享,定义全局数据
1)props:利用props获取父组件方法直接调用
2)context:利用React.createContext()创建全局可以访问的值,使用provider和customer模式,在顶层的provider中传入value
3)eventEmitter:可以引入events包,通过注册事件和触发事件来实现通信new EventEmitter();addListener();removeListener();
4)路由传参:params:this.props.match.params.(刷新页面不会丢失)query:this.props.location.query.(刷新丢失,可传对象)
state:this.props.location.query.state.(Hash中刷新页面丢失,可传对象)search:this.props.location.search
5)onRef:通过props机制将组件的this实例当做参数传到父组件,父组件就可以操作子组件的方法和state
6)ref:通过ref属性获取整个子组件实例进行操作
7)redux
8)Mobx
9)flux
10)hooks:使用userReducer和context实现通讯,核心action,reducer,types
11)slot:将父组件的标签传递给子组件,子组件使用this.props.slot来获取内容
12、flux思想: 单向数据流
用户访问view;view发出用户的action;dispatcher收到action,要求store进行更新;store更新后,发出一个change事件;view收到change事件后更新页面
13、vue和react的虚拟dom有啥区别?
react和vue的虚拟dom都是一样的,都是用js对象来模拟真实dom,然后用虚拟dom的diff来最小化更新真实dom,唯一的区别是react采用的是自上而下的全量diff,vue采用的是局部订阅的模式
vue和react的区别:
1、虚拟dom不同:react采用的是自上而下的全量diff,vue采用的是局部订阅的模式
2、数据流:react是自上而下单向数据流,需要用setState方式去更新状态,vue双向数据绑定
3、模板渲染方式不同:react通过jsx来渲染,vue是使用html语法,通过指令v-if、v-for来渲染。在引入模板引入中,react中import的组件可以在render中直接使用,vue还需要在components中声明
4、react本身是严格的view层,MVC模式,vue是MVVM模式
五、浏览器和Http
1、cookie、sessionStorage、localStorage的区别
cookie常用于存储用户身份,登录状态等,http中自动携带,体积上限位4K,可自行设置过期时间
localStorage/sessionStorage:长久存储/窗口关闭删除,体积5M,不与服务端通信,两者只有存储期限不同,local除非手动清除否则永久保存,session页面关闭后被清除
2、各大浏览器内核:Trident(IE)、Webkit(Chrome/Safari)、Gecko(Mozilla/Firefox)、Presto()
3、web性能优化方向:
1)降低请求量(减少http请求次数,图片文件压缩,资源懒加载,按需加载,使用base64图片);
2)加快请求速度(并行加载,CDN分发);
3)缓存(离线数据缓存在localStorage中);
4)渲染(JS/CSS加载顺序优化,css放在最上面,js放在body的最下面);
5)事件节流,减少dom操作,避免回流
6)减少cookie使用,减少请求携带的大小
4、http和https的区别:https比http多了一层SSL协议,用于加密,http明文传输,无状态连接;https加密传输且身份认证,需要ca证书;http端口80,https端口443
5、301.302.303重定向
6、浏览器垃圾回收和内存泄漏:垃圾回收就是定期找出不继续使用的变量释放内存;
闭包导致父级中的变量无法被释放;定时器未正确关闭导致引用的外部变量无法被释放,事件监听没有被正确销毁;dom元素被删除时,内存中对dom的引用没有被清除;没有声明的变量无法回收
7、浏览器渲染页面流程:浏览器从请求到加载一个页面:DNS查询(域名解析:域名解析成ip地址)、TCP连接、HTTP请求响应、服务器响应、客户端渲染
客户端渲染的过程:处理html构建dom树;处理css构建css树;将dom树和css树合并渲染树;布局;绘制页面
8、浏览器事件流:
捕获(事件从window对象到document对象再到html标签一层层传到目标元素)、目标、冒泡(捕获的逆过程)
9、重绘和重排:重绘是重新绘制受影响的部分;重排是重新生成布局;重排一定会导致重绘;
触发重绘重排:dom节点的增删改;dom节点隐藏;dom节点的移动或添加动画;调整样式属性;用户调整窗口大小,滚动等操作
10、dom2事件绑定:可以添加多个处理函数,可以用addEventListener和removeEventListener来绑定和解绑事件
11、浏览器缓存:浏览器缓存基本是get方法
浏览器请求与缓存的关系流:是否有缓存、判断缓存是否过期、判断最后修改的时间
强制缓存:cache-control(no-cache不能缓存;public;private),expires
协商缓存:lastModified
12、websocket:实现客户端和远程服务端的全双工通信;http是应用层协议,封装解析传输的数据;socket不是协议,是对TCP的接口封装,是传输通道两端的接口;websocket是个持久化的协议,服务端可以主动push;new WebSocket(url); ws.onerror = fn; ws.onclose = fn; ws.onopen = fn; ws.onmessage = fn; ws.send()
13、http请求方式:GET获取资源;POST传输数据;PUT传输文件;DELETE删除资源;HEAD获得报文首部;OPTIONS询问支持的方法
15、get和post区别:get缓存、请求长度受限,会被历史保存记录;post安全、大数据、更多编码类型
16、浏览器安全:同源策略(要求域名协议端口都相同),XSS注入攻击(转义html、过滤script标签),跨域请求伪造csrf(增加用户登录授权)
17、跨浏览器、跨终端?浏览器兼容:css样式、事件触发,响应式开发:媒体查询,多套css样式
18、前端架构?可访问性?可维护性?
1)创建gitlab和git flow工作流进行版本管理;2)埋点系统:记录页面访问量,捕捉报错等;3)使用ESlint:统一代码风格,减少低级bug,增加可阅读性和可维护性;4)Mock数据;
5)基础组件封装;6)公共样式库,统一UI风格;7)权限管理,路由守卫,单点登录;8)请求拦截
19、hash和history的区别?hash不会被包含在http请求中,对后端完全没有影响,改变hash不会重新加载页面,只要#号前面的内容正确,就不会返回404错误;history需要服务端做完整的匹配,不然就会出现404错误
20、前端处理跨域问题?配置反向代理:在vue.config.js文件中配置proxyTable、jsonp原理,cors、iframe,postMessage....
module.exports = {
devServer: {
proxy: {
"/api": {
target: "http://typhoon.zjwater.gov.cn", //设置调用的接口域名和端口
changeOrigin: true, //是否跨域
ws:true, // 是否启用websocket
pathRewrite: { "^/api": "" } } } } } // 使用/api来代替target里面的地址
Webpack:
1、常用的loader:eslint-loader、url-loader、postcss-loader、style-loader、css-loader、sass-loader、file-loader、babel-loader、
2、基本功能及工作原理:代码转换:编译ts/es,scss;文件优化:压缩js、css代码,压缩图片;代码分割,异步加载;代码校验:代码规范校验,单元测试;
3、打包原理:将所有依赖打包成一个bundle.js,通过代码分割按需加载
4、entry:告诉webpack使用哪个模块作为构建项目的起点;output:告诉webpack在哪里输出它打包好的代码及如何命名
5、常用plugins:html-webpack-plugins(压缩html)clean-webpack-plugins(打包器清理dist目录)
6、babel:将es6代码编译成AST(抽象语法树)
canvas使用:
1、转换图片格式
function getImgToBase64(url, callback){
let canvas = document.createElement('canvas');
let ctx = canvas.getContext('2d');
let img = new Image;
img.crossOrigin = 'Anonymous';
img.onload = function(){
canvas.height = img.height;
canvas.width = img.width;
ctx.drawImage(img,0,0);
var dataURL = canvas.toDataURL('image/jpg'); callback(dataURL);
canvas = null;
};
img.src = url;
}
数组操作:
1、数组去重:Array.from(new Set([1,2,3,2,1]))或 [...new Set([1,2,3,2,1])]
2、替换数组中的元素:splice(atart, countToRemove, valueToAdd)
3、清空数组:直接将数组的长度设为0
4、获取数组中某个键值映射: arr.values() 或 Array.from(arr, ({name})=>name)
5、填充数组:let arr = new Array(10).fill(1)
6、合并数组:[...arr1, ...arr2] contact
7、两个数组的交集:[...new Set(arr1)].filter(el => arr2.includes(el))
8、删除假值:arr.filter(Boolean) 假值为:null,undefined,false,0,NAN,“”
9、从数组中获取随机值:arr[Math.floor(Math.random() * (arr.length))]
10、数组翻转:arr.reverse()
11、查找元素最后一次出现的索引:arr.lastIndexOf(1)
12、数组中所有元素相加:arr.reduce((x, y) => x+y)
Angular、vue、react对比:
angluar:比较完善,自带了丰富的指令,包含模板,数据双向绑定,过滤器,依赖注入等功能,对es6兼容不是很好,需要手写jq来解决某些问题,
vue:轻量级,支持双向数据绑定,不支持IE8
react:声明范式,操作虚拟DOM,单向数据流,