HTML
一、你对 盒子模型理解
多少?
a.什么是盒模型?
css基础框盒模型是CSS规范的一个模块,它定义了一种长方形的盒子
b.盒模型的分类:
盒模型从标准定义上分为标准盒模型和替代(IE)盒模型,从元素类型上分为块级盒子和内联盒子
c.盒模型的切换:
1.通过box-sizing属性进行切换;
2.ie盒模型:box-sizing:border-box;定义width,
height代表元素边框盒(包含border,padding,content)的宽和高
3.标准盒模型:box-sizing: content-box;定义width,height代表content的宽和高
d.盒模型属性设置
margin和paddin值的设置;
1个值的情况:如10px4个方向都为10px;
2个值的情况:如10px 20px 上下10px 左右20px
3个值的情况:如10px 20px 30px 上10px左右20px下30px
4个值的情况:如10px 20px 30px 40px 上10px 右20px 下30px 左40px(顺时针)
border值:border:1px solid red 三个值分别代表border-width, border-style,
border-color可设置一个或多个属性的值
二、谈谈你对 css选择器
的理解?
a.css选择器:
通俗的讲CSS选择器用来对选定的页面元素进行样式修改。
b.选择器(11种):
标签选择器h1{},通配选择器*{},类选择器.box{},ID选择器#box{},
标签属性选择器a[title]{},伪类选择器p:first-child{}
伪元素选择器p::first-line{},后代选择器.box p,子代选择器.box > p,
相邻兄弟选择器 h1+p,通用兄弟选择器 h1~p
三、谈谈你对 css选择器优先级
的理解?
a.css选择器优先级是基于不同种类选择器组成的匹配规则
b.css选择器的优先级:
!important>行内样式>ID选择器>类,伪类,属性选择器>
标签,伪元素选择器>通配符,子类选择器,兄弟选择器
四、css中哪些属性是可以继承的
?
a.字体font,font-family,font-size,font-style,font-variant,font-weight
b.字母间距 letter-spacing
c.可见性 visibility
d.文字展示 line-height, text-align, text-indent, text-transform,
f.字间距 word-spacing
五、如何区分 px/em/rem/vw/vh
?
px:就是pixel像素的缩写,可以简单理解为网页开发的基本长度单位
em: em是一个相对长度单位,相对于当前元素内文本的字体尺寸
rem: rem是CSS3新增的一个相对单位,基于html元素的字体大小来决定,通常配合媒体查询用于解决移动端适配问题
vw和vh:vw和vh是相对于视口的长度单位,1vw即值为视口宽度的1%,1vh意味着值为视口高度的1%
a.px:相对单位,网页开发基本长度单位
b.em:相对单位,相对当前盒子字体大小进行计算
c.rem:相对单位,相对根元素html字体大小进行计算
d.vw+vh:相对单位,相对当前网页视口宽度和高度进行计算
六、如何实现 绝对集中
?
<div class="content">
<div class="box"></div>
</div>
*{
margin: 0;
padding: 0;
}
html,body {
width: 100%;
height: 100%;
}
a.定宽高
1.绝对定位+负margin值
.content {
height: 100%;
border: 1px red solid;
position: relative;
}
.box {
position: absolute;
top: 50%;
left: 50%;
width: 200px;
height: 200px;
border: 4px red solid;
margin: -100px -100px;
}
2.绝对定位+margin auto
.box {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 200px;
height: 200px;
border: 4px red solid;
margin: auto;
}
b.不定宽高
1.gird 父display: grid;子margin:auto
.content {
height: 100%;
border: 1px red solid;
position: relative;
display: grid;
}
.box {
border: 4px red solid;
margin: auto;
}
2.flex布局
.content {
height: 100%;
border: 1px red solid;
position: relative;
display: flex;
justify-content: center;
align-items: center;
}
.box {
border: 4px red solid;
}
3.绝对定位+transform
.content {
height: 100%;
border: 1px red solid;
position: relative;
}
.box {
position: absolute;
top: 50%;
left: 50%;
border: 4px red solid;
transform: translate(-50%, -50%)
}
七、假设高度已知,请写出三栏布局,其中左栏、右栏宽度各为300px,中间自适应
*{
margin: 0;
padding: 0;
}
html,body {
height: 100%;
}
1.float布局
.con{
height: 100%;
border: 1px red solid;
}
.con:after{
content: ".";
clear: both;
display: block;
height: 0;
}
.con div {
height: 300px;
}
.con .left{
float: left;
width: 300px;
background-color: red;
}
.con .right{
float: right;
width: 300px;
background-color: yellow;
}
.con .content{
background-color: orange;
}
<div class="con">
<div class="left"></div>
<div class="right"></div>
<div class="content"></div>
</div>
2.绝对定位布局
.con{
height: 100%;
border: 1px red solid;
position: relative;
}
.con div {
height: 300px;
}
.con .left{
position: absolute;
top: 0;
left: 0;
background-color: red;
width: 300px;
}
.con .right{
position: absolute;
top: 0;
right: 0;
background-color: yellow;
width: 300px;
}
.con .content{
background-color: orange;
position: absolute;
left: 300px;
right: 300px;
}
<div class="con">
<div class="left"></div>
<div class="content"></div>
<div class="right"></div>
</div>
3.flex布局
.con{
height: 100%;
border: 1px red solid;
position: relative;
display: flex;
}
.con div {
height: 300px;
}
.con .left{
width: 300px;
background-color: red;
}
.con .content{
background-color: orange;
flex: 1;
}
.con .right{
width: 300px;
background-color: yellow;
}
<div class="con">
<div class="left"></div>
<div class="content"></div>
<div class="right"></div>
</div>
4.网格布局
.con{
height: 100%;
border: 1px red solid;
position: relative;
display: grid;
grid-template-columns: 300px auto 300px;
grid-template-rows: 100px;
}
.con div {
height: 300px;
}
.con .left{
background-color: red;
}
.con .content{
background-color: orange;
}
.con .right{
background-color: yellow;
}
5.table布局
八、CSS position
属性
absolute 生成绝对定位的元素,相对于 static 定位以外的第一个父元素进行定位。
元素的位置通过 "left", "top", "right" 以及 "bottom" 属性进行规定。
fixed 生成固定定位的元素,相对于浏览器窗口进行定位。
元素的位置通过 "left", "top", "right" 以及 "bottom" 属性进行规定
relative 生成相对定位的元素,相对于其正常位置进行定位。
因此,"left:20" 会向元素的 LEFT 位置添加 20 像素。
static 默认值。没有定位,元素出现在正常的流中(忽略 top, bottom, left, right 或者 z-index 声明)。
sicky 粘性定位,该定位基于用户滚动的位置
九、display:flex
1.justify-content: center属性定义了项目在主轴上的对齐方式。
2.align-items属性定义项目在交叉轴上如何对齐。
3.flex: 1 -> flex: flex-grow:1, flex-shrink:1, flex-basis:0%
3.flex: auto -> flex: flex-grow:1, flex-shrink:1, flex-basis:auto
flex-grow属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。
flex-shrink属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。
flex-basis属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。
浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小。
javascript
1、如何实现 new
操作符
1.实例化对象
2.返回值的问题:构造函数中如果有值返回,那实例化后的对象就是这个返回值
const TMap = function(options) {
this.name = options.name
this.address = options.address
}
const map = new TMap({
name: 'xiaolin',
address:'shenzhen'
})
console.log(map, 'map')
1.创建空对象
2.获取构造函数
3.对象的__proto__指向Constructor.prototype
4.用apply的方式把构造函数Constructor的this指向obj执行Constructor
5.根据ret的执行结果判断返回构造函数的返回对象还是新创建的空对象
const ObejectFactory = (...args) => {
const obj = {}
const Constructor = [].shift.call(args)
obj.__proto__ = Constructor.prototype
const ret = Constructor.apply(obj, args)
return typeof ret === 'object' ? ret : obj
}
console.log(ObejectFactory(TMap, {name: '11', address: '22'}), '22')
2. instanceof
原理
1.获取实例对象的隐式原型
2.获取构造函数的prototype属性
3.while 循环 -> 在原型链上不断向上查找
4.在原型链上不断查找 构造函数的显式原型
5.直到left = null 都没有找到,返回false
6.构造函数的prototype属性出现在实例对象的原型链上返回true
定义:instanceof运算符用于检测构造函数的prototype属性是否出现某个实例对象的原型链上
function instance_of(Obj, Constructor) {
let left = Obj.__proto__
let right = Constructor.prototype
while(true) {
if (left === null) {
return false
} else if (left === right) {
return true
}
left = left.__proto__
}
}
3.浏览器的运行机制
浏览器的运行机制
1.构建DOM树(parse):渲染引擎解析HTML文档,首先将标签转换成DOM树中的DOM node(包括js生成的标签)
生成内容树(Content Tree/DOM Tree);
2.构建渲染树(construct):解析对应的css样式文件信息(包括js生成的样式和外部css文件),而这一些文件
信息以及HTML中可见的指令(如<b></b>),构建渲染树(Rendering Tree/Frame Tree);render tree中
每个NODE都有自己的style,而且render tree不包含隐藏的节点(比如display:none的节点,
还有head节点),因为这一些额节点不会用于呈现;
3.布局渲染树(reflow/layout):从根节点递归调用,计算每一个元素的大小、位置,给出每个节点所应该在屏
幕上出现的精确坐标;
4.绘制渲染树(paint/repaint):遍历渲染树,使用UI层来绘制每个节点;
回流必将引起重绘,重绘不一定会引起回流。
回流(重构/回流/reflow):当渲染树中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新
构建,这就称为回流(reflow),每个页面至少需要一次回流,就是在页面第一次加载的时候。
1、页面渲染初始化;(无法避免)
2、添加或删除可见的DOM元素;
3、元素位置的改变,或者使用动画;
4、元素尺寸的改变--大小、外边距、边框;
5、浏览器窗口尺寸的变化(resize事件发生时);
6、填充内容的改变,比如文本的改变或图片大小改变而引起的计算值宽度和高度的改变;
7、读取某些元素属性;(offsetLeft/Top/Height/Width,clientTop/Left/Width/Height,
scrollTop/Left/Width/Height,width/height,getComputedStyle(),currentStyle(IE))
重绘重排的代价:耗时,导致浏览器卡慢。
重绘 (Repaint):当页面中元素样式的改变并不影响它在文档流中的位置时(例如:color、background-color、
visibility等),
浏览器会将新样式赋予给元素并重新绘制它,这个过程称为重绘。
4.实现函数防抖 debounce
一、函数防抖:事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时
二、场景:搜索框(电商网站商品搜索,后台管理系统数据查询)
const search = document.getElementById('search')
const debounce = (fn, inital) => {
let timer = null
return () => {
clearTimeout(timer)
timer = setTimeout(fn, inital)
}
}
search.oninput = debounce(function(){
console.log('xiaolin')
}, 2000)
5.实现函数节流 throttle
一、函数节流:规定在一个单位时间内,事件响应函数只能被触发一次。如果这个单位时间内触发多次函数,只有一次生效
二、场景:a.window.onresize事件 b.mousemove事件
function throttle(fn, interval) {
let timer;
return (event) => {
if (timer) return false
timer = setTimeout(() => {
clearTimeout(timer)
timer = null
fn(event)
}, interval)
}
}
window.onresize = throttle(function(event) {
console.log(1)
}, 2000)
6.请描述 event loop
(事件循环/事件轮询)的机制,可画图
请描述event loop(事件循环/事件轮询)的机制,可画图
1.同步代码。一行一行放在Call Stack(调用栈)执行
2.遇到异步,会先记录下,等待时机(定时器、网络请求等)
3.时机到了,就移动到Callback Queue(回调队列)
4.如Call Stack为空(即同步代码执行完)Event Loop 开始工作
5.轮询查找Callback Queue,如有则移动到Call Stack执行
6.然后继续轮询查找
a.JS是单线程的
b.异步(setTimeout, ajax等)使用回调,基于event loop
c.DOM事件也使用回调,基于event loop
7.宏任务 macroTask
和微任务 microTask
宏任务macroTask和微任务microTask
a.什么是宏任务,什么是微任务
1.宏任务:setTimeout, setTnterval, Ajax, DOM事件
2.微任务: Promise async/await
3.微任务执行时机比宏任务要早(先记住)
b.event loop 和 DOM渲染
1.每次Call Stack清空(即每次轮询结束),即同步任务执行完
2.都是DOM重新渲染的机会,DOM结构如有改变则重新渲染
3.然后再去触发下一次Event Loop
c.微任务和宏任务的区别
1.宏任务:DOM渲染后触发,如setTimeout
2.微任务:DOM渲染前触发,如Promise
3.微任务是ES6语法规定的
4.宏任务是由浏览器规定的
d.微任务、宏任务和DOM渲染,在event loop的过程
8.深拷贝和浅拷贝
区别:
1.深拷贝和浅拷贝是针对复杂数据类型来说的,浅拷贝只拷贝一层,而深拷贝是层层拷贝
a.浅拷贝
浅拷贝是会将对象的每个属性进行依次复制,但是当对象的属性值是引用类型时,实质复制的是其引用,
当引用指向的值改变时也会跟着变化。
可以使用 `Object.assign`、扩展运算符 `...` 、`for in`、
`Array.prototype.slice()`、`Array.prototype.concat()`
let a = {
age: 1,
jobs: {
first: 'FE'
}
}
let b = { ...a }
a.jobs.first = 'native'
console.log(b.jobs.first)
b.深拷贝
深拷贝复制变量值,对于非基本类型的变量,则递归至基本类型变量后,再复制。 深拷贝后的对象
与原来的对象是完全隔离的,互不影响,对一个对象的修改并不会影响另一个对象。
1.深拷贝最简单的实现是: `JSON.parse(JSON.stringify(obj))`
`JSON.parse(JSON.stringify(obj))` 是最简单的实现方式,但是有一些缺陷:
1.对象的属性值是函数时,无法拷贝。
2.原型链上的属性无法拷贝
3.不能正确的处理 Date 类型的数据
4.不能处理 RegExp
5.会忽略 symbol
6.会忽略 undefined
2.拷贝函数
const obj1 = {
age: 20,
name: 'xxx',
address: {
city: 'beijing'
},
arr: ['a', 'b', 'c'],
regexp: /^1[3456789]d{9}$/,
b: new Date()
}
function deepClone(obj) {
if (obj instanceof RegExp) return new RegExp(obj)
if (obj instanceof Date) return new Date(obj)
if (typeof obj !== 'object' || obj == null) return obj
let result = obj instanceof Array ? [] : {}
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
result[key] = deepClone(obj[key])
}
}
return result
}
console.log(deepClone(obj1))
9. script标签的 defer
和 async
有什么区别?
1.无:HTML暂停解析,下载JS,执行JS,再继续解析HTML
2.defer:HTML继续解析,并行下载JS,HTML解析完再执行JS
3.async:HTML继续解析,并行下载JS,执行JS,再解析HTML
10.内存泄露的场景
a.被全局变量,函数引用,组件销毁时未清除
b.被全局事件,定时器引用,组件销毁时未清除
c.被自定义事件引用,组件销毁时未清除
11.Javascript垃圾回收
当对象不再被引用时被垃圾回收机制回收(“对象有没有其他对象引用到它”)。
内存泄露就是不再被需要的内存, 由于某种原因, 无法被释放
a.引用计数法:
1.引用计数算法的原理是设置一个引用数,判断当前引用数是否是0
2.代码中有一个对象空间,多了一个变量名指向它,引用计数器就为它的引用数 + 1,
减b少一个引用引用计数器就为它的引用数 - 1, 一旦引用数变为 0, 该对象空间就会被认为是垃圾,然后被回收
b.标记清除法:从根开始,找所有从根开始引用的对象标记,然后找这些对象引用的对象标记,
把不能达到的回收(这个算法把“对象是否不再需要”简化定义为“对象是否可以获得”。)
3.通过构造函数中设置(构造函数this指向 new 的对象)
避免内存泄漏:
1.尽少创建全局变量
2.手动清除计时器
3.少用闭包
4.使用弱引用WeakMap和WeakSet
12. if-else
代码优化方案
1.提前return, 去除不必要的else
2.使用条件三目运算符
3.合并条件表达式
13. 介绍下原型和原型链
原型:在javascript中,函数可以有属性。每个函数都有一个特殊的属性叫作原型(prototype)
原型链:就是当我们访问对象的某个属性或方法时,如果在当时对象中找不到定义,会继续在当前对象的原型对象中查
找,如果原型对象中依然没有找到,会继续在原型对象的原型中查找(原型也是对象,也有自己的原型)如此继续,直到
找到为止,或者查找到最顶层的原型对象(Object的原型对象)中也没有找到,就结束查找,返回undefined。可以看
出,这个查找过程是一个链式的查找,每个对象都有一个到它自身原型对象的链接,这些链接组件的整个链条就是原型链。
原型和原型链存在的意义:使得是让对象可以共享构造函数原型属性和方法,节省内存。构造函数原型上的属性和方法
越多,节省内存越大
function foo() {
}
const bar = new foo()
console.log(bar.__proto__ === foo.prototype)
console.log(bar.__proto__.__proto__)
console.log(bar.__proto__.__proto__.__proto__)
console.log(foo.prototype)
console.log(foo.prototype.prototype)
14. 闭包
闭包:有权访问另一个函数作用域中的变量的函数
场景:
a.事件函数的封装
b.用闭包模拟私有方法
c.在循环中给页面元素绑定事件响应函数
特点:
1.创建私有变量
2.延长变量的生命周期
存在什么问题:闭包本身会造成内部变量常驻内存
function makeCounter() {
let num = 0;
function changeBy(val) {
num += val
}
return {
add: function() {
changeBy(1)
},
val: function() {
return num
}
}
}
const res = makeCounter()
res.add()
res.add()
console.log(res.val())
vue
一、 vue2响应式的原理
vue2响应式的原理它主要指的这个状态改变以后,你的视图要去自动去更新
vue是通过两个步骤来实现的第一步我叫数据劫持,数据劫持也叫做数据拦截
通过Object.defineProperty来把对象的每一个属性都把它转成这个setter,getter
在修改对应的属性的时候他就能去触发这个setter,这样就可以知道哪个属性被修改了
第二步是依赖收集就是我们在渲染视图的时候要将这个观察者(Watcher)和具体的属性把它结合起来
通过这个发布订阅的模式,将数据的改变就能够更加精准的去更新这个视图
二、 vue diff算法
简述diff算法过程
1.patch(elem, vnode)和patch(vnode, newVnode)
2.patchVnode和addVnodes和removeVnodes
3.updateChildren(key的重要性)
4.vue 的diff算法是个深度优先算法
思路:
当组件创建和更新的时候, vue 会执行内部的 update 函数,该函数使用 render 函数生成虚拟的 dom 树,
找到差异点,最终更新到真实dom
将新旧对比差异的过程叫 diff, vue 在内部通过一个叫做 patch 的函数来完成该过程。
在对比的过程,vue 采用深度优先,同级比较的方式进行比较,同级比较就是说它不会跨越结构进行比较,
在判断两个节点是否相同的时候,是根据虚拟节点的 key 和 tag 来进行判断的。
具体来说,首先对根节点进行对比,如果相同则将旧节点关联的真实dom的引用挂到新节点上,然后根据需要
更新属性到真实dom,然后再对比其子节点数组;如果不相同,则按照新节点的信息递归创建所有真实dom,
同时挂到对应虚拟节点上,然后移除掉旧的dom。
在对比其子节点数组时,vue对每个子节点数组使用了两个指针,分别指向头尾,然后不断向中间靠拢来进行对比,
这样做的目的是尽量复用真实dom,尽量少的销毁和创建真实dom。如果发现相同,则进入和根节点一样的对比流程,
如果发现不同,则移动真实dom到合适的位置。
这样一直递归的遍历下去,直到整棵树完成对比。
Vue2 Vue3 React三者diff算法有何区别?
1.只比较同一层级,不跨级比较
2.tag不同则删除重建(不再去比较内部的细节)
3.子节点通过key区分
Vue2: 双端比较
Vue3:最长递增子序列
React:仅右移
www.cnblogs.com/zhilili/p/1…
三、 Vue-router二种模式
1. hash
模式
1.原理:
在 url 中的
对应的hash值来判断加载对应的路由加载对应的组件
2.优点:
1.只需要前端配置路由表, 不需要后端的参与
2.兼容性好, 浏览器都能支持
3.hash值改变不会向后端发送请求, 完全属于前端路由
3.缺点:
1.hash值前面需要加
2. history
模式
1.原理:
1.history是使用了 H5 提供的pushState() 和 replaceState(),允许开发者直接更改前端路由,
即更新浏览器 URL 地址而不重新发起请求(将url替换并且不刷新页面)。
2.优点:
1.符合url地址规范, 不需要#, 使用起来比较美观
3.缺点:
在用户手动输入地址或刷新页面时会发起url请求, 后端需要配置index.html页面用户匹配不到静态资源的情况,
否则会出现404错误
兼容性比较差, 是利用了 HTML5 History对象中新增的 pushState() 和 replaceState() 方法,需要
特定浏览器的支持.
四、 Vue 的响应式原理中 Object.defineProperty 的缺陷
1.object.defineproperty 无法监控到数组下标的变化,导致通过数组下标添加元素,无法实时响应
2.object.defineProperty 只能劫持对象的属性,从而需要对每个对象,每个属性进行遍历,如果,
属性值是对象,还需要深度遍历。Proxy 可以劫持整个对象,并返回一个新的对象
五、Vue $.set
a.原因:受 javascript 的限制,Vue.js 不能检测到对象属性的添加或删除。因为 Vue.js 在初始化实例时将属性转为
getter/setter,所以 属性必须在 data 对象上才能让 Vue.js 转换它,才能让它是响应的。
b.Vue 不能检测以下变动的数组:
1.当你利用索引直接设置一个项时,例如:vm.items[indexOfItem] = newValue
2.当你修改数组的长度时,例如:vm.items.length = newLength
c.eg:
1.使用 this.arr[0] 去更新 array 的内容,视图没有刷新
2.使用 Vue.set(this.arr, 0, !this.arr[0]) 去更新 array 的内容,视图被刷新
3.使用 this.arr[0] = !this.arr[0] 和 this.obj.a = !this.obj.a 同时更新,视图被刷新
d.结论:
1.如果方法里面单纯的更新数组 Array 的话,要使用 Vue.set();
2.如果方法里面同时有数组和对象的更新,直接操作 data 即可;
f.原理:
1.每个组件实例都有相应的 watcher 实例对象,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的
setter 被调用时,会通知 watcher 重新计算,从而致使它关联的组件得以更新
2.受现代 JavaScript 的限制 (而且 Object.observe 也已经被废弃),Vue 不能检测到对象属性的添加或删
除。由于 Vue 会在初始化实例时对属性执行 getter/setter 转化过程,所以属性必须在 data 对象上存在才能
让 Vue 转换它,
这样才能让它是响应的
六、反向代理的原理 nginx
原理:反向代理需要用到nginx。反向代理是在服务器端进行处理。首先修改hosts文件,将域名指向开发者的电脑本
身,把自己伪装成服务端,再通过nginx对不同的请求进行转发,把静态资源指向开发者本地电脑的资源,将接口指向
实际的服务器。
程序运行过程:
1.浏览器访问页面,假设访问淘宝页面:taobao.com/index.html
2.taobao.com域名解析先经过hosts文件配置,发现taobao.com域名指向127.0.0.1,则向本机发起请求。
3.nginx接收到taobao.com/index.html请求,根据nginx的配置,将把这个请求转发给127.0.0.1:3000。
4.浏览器运行index.html文件,发起taobao.com/api/getNew请求
5.nginx接收到taobao.com/api/getNew请求请求,根据nginx的配置,将把这个请求转发给真正的淘宝服务器中。
6.淘宝服务器将数据返回给nginx,再返回给浏览器执行。
七、场景题
第一次打开时,显示页面 A,页面 A 有一个setInterval事件,每隔一秒钟会向后台发送一个Ajax请求。
这时我点击页面 A 上的跳转按钮,跳到页面 B,通过观察网络连接,发现页面 A 上的Ajax请求仍然在继续。
答案:
router切换时,原来的组件确实已经销毁了,你可以看到ready生命周期函数是每次都触发了的。
你这里的问题不在于组件是否销毁,因为setInterval事件本身和组件没有关系。
setInterval相当于该组件申请的一种资源,在使用该组件时获取,在离开该组件时释放。
这个过程只能是你手动进行的。所以你应该在离开该组件时,比如route的deactivate或者beforeDestory生命周
期函数里手动clearInterval。
其实很多框架里都是这样,比如桌面程序中某个窗口初始化时需要打开数据库连接(我们也可以视为一种资源),
当窗口关闭时,程序本身并不知道“打开数据库连接”的反向操作是什么。所以我们需要在窗口销毁的回调方法里手动去
释放这个资源,去写断开连接的代码。
定时器危害:
如果不手动清除定时器,它会一直占用内存资源。更可怕的是,一旦使用定时器进行轮询,定时器所占的内存资源将会
不断上升,若与定时器重叠问题一起出现,常导致页面卡顿
react
一、react 里面 function component 和 class component的区别
funciton App(props){
return(
<div class="App"></div>
)
}
class App extends React.Component{
constructor(props){
super(props);
this.state = {}
}
}
render(){
return(
<div class="App"></div>
)
}
a.写法
function component 简单、直接接受props作为参数,return返回代码片段
class component 复杂,继承自React.Component,constructor中接受props参数,render中返回
b.state状态
function component 无状态组件
class component 可以使用this.state,setState()等
c.生命周期
function component 无
class component 有
d.优点
function component 代码量少,容易编写;无状态组件,更好的体现容器和表现分离。提倡使用
class component 1.需要state来改变内部组件的状态;
2.需要使用一些周期函数;
3.可以提升性能,有些时候我们需要减少组件的渲染次数,
我们就需要在组件内部使用shouldComponentUpdate方法来判断,
或者继承React.PureComponent类(自动调用shouldComponentUpdate)
来实现state和props的浅比较进行判断组件是否需要重新渲染。
http
1.描述 cookie
localStorage
sessionStorage
区别
a.cookie
1.本身用于浏览器和server通讯
2.存储大小4KB
3.http请求时需要发送到服务端,增加请求数据量
b.localStorage sessionStorage
1.localStorage数据会永久存储,除非代码或手动删除
2.sessionStorage数据只存在于当前会话,浏览器关闭则清空
3.存储大小5M
2. http常见的状态码有哪些
a.状态码分类
1.1xx服务器收到请求
2.2xx请求成功,200
3.3xx重定向,如302
301 Moved Permanently 永久重定向,表示请求的资源已经永久的搬到了其他位置
302 Found 临时重定向,表示请求的资源临时搬到了其他位置
303 See Other 表示请求资源存在另一个URI,应使用GET定向获取请求资源
304 Not Modified 表示客户端发送附带条件的请求(GET方法请求报文中的IF…)时,条件不满足
4.4xx客户端错误,如404
400 Bad Request 表示请求报文存在语法错误或参数错误,服务器不理解
401 Unauthorized 表示发送的请求需要有HTTP认证信息或者是认证失败了
403 Forbidden 表示对请求资源的访问被服务器拒绝了
404 Not Found 表示服务器找不到你请求的资源
5.5xx服务端错误,500
500 Internal Server Error 表示服务器执行请求的时候出错了
503 Service Unavailable 表示服务器超负载或正停机维护,无法处理请求
504 网关超时
3. http有哪些请求方法? get和post有什么区别
?
1.GET
2.POST
3.PUT
4.DELETE
a.get用来获取数据,post用来提交数据
b.get参数有长度限制(受限于url长度,具体的数值取决于浏览器和服务器的限制,最长2048字节),而post无限制
c.get是明文传输,post是放在请求体中
d.get是会被浏览器主动缓存的
4. 缓存:強缓存 和 协商缓存
1. 強缓存 Expires
和 Cache-Control
实现强缓存可以通过两种响应头实现:`Expires` 和 `Cache-Control`
Expires: Wed, 22 Oct 2018 08:41:00 GMT -> HTTP / 1.0
Cache-control: max-age=30 -> HTTP / 1.1,优先级高于 `Expires`
2. 协商缓存 Last-Modified
和 If-Modified-Since
ETag
和 If-None-Match
Last-Modified 和 If-Modified-Since
`Last-Modified` 表示本地文件最后修改日期,`If-Modified-Since` 会将 `Last-Modified`
的值发送给服务器,询问服务器在该日期后资源是否有更新,有更新的话就会将新的资源发送回来。
但是如果在本地打开缓存文件,就会造成 `Last-Modified` 被修改,所以在 HTTP / 1.1 出现了 `ETag`
ETag 和 If-None-Match
`ETag` 类似于文件指纹,`If-None-Match` 会将当前 `ETag` 发送给服务器,询问该资源 `ETag`
是否变动,有变动的话就将新的资源发送回来。并且 `ETag` 优先级比 `Last-Modified` 高
浏览器
1. 描述从输入url到页面展示的完整过程
a.网络请求中
1.DNS查询(得到IP),建立TCP连接(三次握手)
2.浏览器发起HTTP请求
3.收到请求响应,得到HTML源代码
b.解析
1.HTML构建DOM树
2.CSS构建CSSOM树(style tree)
3.两者结合,形成render tree
c.渲染
1.计算各个DOM的尺寸、定位、最后绘制到页面
2.遇到JS可能会执行
3.异步CSS、图片加载,可能会触发重新渲染
前端安全
1. XSS 跨域脚本攻击
1.Cross Site Script跨域脚本攻击
2.手段:黑客将JS代码插入到网页内容中,渲染时执行JS代码
3.预防:特殊字符替换(前端或者后端)
<script>alert(1)</script>
escape('<script>alert(1)</script>')
2. CSRF 跨站请求伪造
1.Cross Site Request Forgery 跨站请求伪造
2.手段:黑客诱导用户去访问另一个网站的接口,伪造请求
3.预防:严格的跨域限制 + 验证码机制
过程
1.用户登录了A网站,有了cookie
2.黑客诱导用户到B网站,并发起A网站的请求
3.A网站的API发现有cookie,认为是用户自己操作的
3. 点击劫持
1.Click Jacking
2.手段: 诱导界面上蒙一个透明的iframe,诱导用户点击
3.预防:让iframe不能跨域加载
4. SQL注入
1.手段:黑客提交内容时写入SQL语句,破坏数据库
2.预防:处理输入的内容,替换特殊字符