面试题2022.6.27

css中overflow:hidden的作用

1.溢出隐藏:给⼀个元素中设置overflflow:hidden,那么该元素的内容若超出了给定的宽度和⾼度属性,那么超出的部分将会被隐藏,不占位。

2.清除浮动:⼀般⽽⾔,⽗级元素不设置⾼度时,⾼度由随内容增加⾃适应⾼度。当⽗级元素内部的⼦元素全部都设置浮动flfloat之后,⼦元素会脱离标准流,不占位,⽗级元素检测不到⼦元素的⾼度,⽗级元素⾼度为0。下⾯的元素会顶上去,造成⻚⾯的塌陷。因此,需要给⽗级加个overflflow:hidden属性,这样⽗级的⾼度就随⼦级容器及⼦级内容的⾼度⽽⾃适应。

3.解决外边距塌陷:⽗级元素内部有⼦元素,如果给⼦元素添加margin-top样式,系统会错误的把margin-top错误的也添加给⽗元素,那么⽗级元素也会跟着下来,造成外边距塌陷, 给⽗级元素添加overflflow:hidden形成BFC,就可以解决这个问题了。

vue中computed和watch的区别

  • computed: 是vue的计算属性, 是通过data中已有的属性计算得来的, 理解为是对data数据的加工处理, 计算属性最终会出现在VM上可以直接读取
  • watch: 是vue的监听属性, 和computed一样都是一个对象, 当被监视的属性变化时, 回调函数自动调用, 进行相关操作(监视的属性必须存在,才能进行监视), 监听复杂类型数据(对象,数组)变化时需要加上deep属性开启深度监听
  • 两者区别:
    • computed能完成的功能,watch都可以完成
    • watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作, computed不支持异步,有异步操作时无法监听数据变化
    • computed支持缓存,当其依赖的属性的值发生变化时,计算属性会重新计算,反之,则使用缓存中的属性值;watch不支持缓存,当对应属性发生变化的时候,响应执行。
    • computed第一次加载时就监听;watch默认第一次加载时不监听(可以通过设置immediate参数为true实现第一次加载时监听)。

react中项目的优化方式

  1. render里面尽量减少新建变量和bind函数,传递参数时尽量减少传递参数的数量
<button onClick={this.add1}>+</button>
//第一种是在构造函数中绑定this,构造函数每次渲染只会执行一遍;
<button onClick={this.add4.bind(this)}>+</button>
//第二种是在render()函数里绑定this,每次render()都会重新执行一遍函数;
<button onClick={() => { this.add2(100); }}>+</button>
//第三种使用箭头函数,每次render()都会生成一个新的箭头函数
  1. 通过shouldComponentUpdate钩子函数阻止组件不必要的重新渲染, 该函数会在组件重新渲染之前调用,由函数的返回的bool值决定是否重新渲染组件。
  2. 对于类式组件使用React.PureComponent, 它以浅层对比 prop 和 state 的方式来实现了 shouldComponentUpdate() ,实现跳过所有子组件树的prop更新 (使用纯组件的前提: 组件在相同 props 传入值的情况下总会有相同的渲染内容)
  3. 对于Hooks使用React.memo来缓存组件, (React.memo是一个高阶组件,高阶组件(HOC)是参数为组件,返回值为新组件的函数)
  4. 对于Hooks使用useMemouseCallback来缓存大量计算, 但是区别于useCallback(避免组件的重复渲染), useMemo主要是在当前页面中缓存数据, 避免不必要的重复执行
  5. 延迟加载不是立即需要的组件, 多使用懒加载 (React.lazy和Suspense等)
  6. 调整CSS而不是强制组件的加载和卸载, 将不透明度调整为0对浏览器的成本消耗几乎为0(因为它不会导致重排),并且应尽可能优先于更该visibility 和 display
  7. 使用React.Fragment避免添加额外的Dom元素

redux的核心组成

概念
  • redux是一个专门用于做状态管理的JS库(不是react插件库)。
  • 可以用在react, angular, vue等项目中, 但基本与react配合使用。
  • 作用: 集中式管理react应用中多个组件共享的状态。
三大原则
  • 单一数据源
  • State是只读的 (只能通过action修改)
  • 使用纯函数来执行修改 (在reducer中定义)
三大核心概念
  • action动作对象
    • type属性:标识属性, 值为字符串, 唯一, 必要属性
    • data属性:数据属性, 值类型任意, 可选属性
  • reducer
    • 用于初始化状态、加工状态。
    • 加工时接收旧的状态state和动作对象action,并根据旧的产生新的state
    • reducer的本质就是一个纯函数(也就是说,只要是同样的输入,必定得到同样的输出)
  • store
    • 将state、action、reducer联系在一起的对象
    • const store = createStore(reducer)

vue中路由跳转的方式

  1. this.$router.push() 跳转到指定的URL,在history栈中添加一个记录,点击后退会返回上一个页面
  2. this.$router.replace() 跳转到指定的url,不会向history里面添加新的记录,点击返回,会跳转到上上一个页面,上一个记录是不存在的。
  3. Router-link 浏览器在解析时,将它解析成一个类似于a标签。
  4. this.$router.go(n) 相对于当前页面向前或向后跳转多少个页面,类似 window.history.go(n)。n可为正数可为负数。正数返回上一个页面。

vue路由守卫

  • 路由守卫就是路由跳转的一些验证,比如登录鉴权(没有登录不能进入个人中心页)等等等

  • 分为三大类:

    • 全局守卫 => 前置守卫:beforeEach 后置钩子:afterEach

    • 单个路由守卫 => 独享守卫:beforeEnter

    • 组件内部守卫 => beforeRouteEnter beforeRouteUpdate beforeRouteLeave

  • 所有路由守卫都是三个参数

    • to: 要进入的目标路由(去哪儿)
    • from: 要离开的路由(从哪来)
    • next: 是否进行下一步(要不要继续)
  • 作用: 对vue路由进行一些权限控制

  • 应用:

    • router.beforeEach 是在每次路由切换之前执行, 可以用于权限的校验 (只有在设置了权限的页面才能跳转到即将要跳转的页面)
    • router.afterEach 是每次路由切换之后执行, 可以用于修改网页的title
    • beforeEach 可以结合全局守卫一起使用, 判断当前路由是否需要进行权限控制

受控组件和非受控组件

非受控组件
  • 定义: 页面中所有输入类DOM的值,都是现用现取
  • 表单数据由DOM本身处理。即不受setState()的控制,与传统的HTML表单输入相似,input输入值即显示最新值(使用时通过ref从DOM获取表单值)
受控组件
  • 页面中输入类的DOM,随着输入的过程,通过 setState() 更新state中的数据,需要用的时候在从状态state中取(有点类似Vue中的双向数据绑定),而呈现表单的React组件也控制着在后续用户输入时该表单中发生的情况,以这种由React控制的输入表单元素而改变其值的方式,称为:“受控组件”。
  • 标签 input、textarea、select的值的改变通常是根据用户输入进行更新,所以受控组件是必须要有value的,value用来传入一个参数,结合onchang来控制这个参数输出。每当value变化的时候,都会调用onchange的方法,事件处理器拿到新的值之后就会重新渲染视图,更新表单

普通函数和箭头函数的区别

  • 所有的箭头函数都是匿名函数, 且不能作为构造函数(不能new)
  • 当形式参数不确定时, 普通函数可以绑定argument, 而箭头函数没有argument, 通过rest参数...解决
  • 箭头函数没有原型属性
  • 箭头函数不能当作generator函数,不能使用yield关键字
  • this指向的问题: 箭头函数没有自己的this指向,箭头函数中的this依赖于箭头函数所在作用域(父作用域)的this指向 , 简单来说箭头函数遇到this就向外跳一层,找父作用域的this,如果父作用域也是箭头函数,继续向外跳一层,以此类推,如果跳到全局作用域就默认指向 window
箭头函数的使用场景
  • 箭头函数适合于无复杂逻辑或者无副作用的纯函数场景下
  • 箭头函数的亮点是简洁,但在有多层函数嵌套的情况下,箭头函数反而影响了函数的作用范围的识别度,这种情况不建议使用箭头函数
  • 箭头函数不适合定义对象的方法

vue移动端的适配方案

1:安装插件  根据网页的宽度,设置 html 的 font-size
npm  i amfe-flexible

2:main.js引入
import 'amfe-flexible'

3:继续安装px的转化插件
npm i postcss postcss-pxtorem@5.1.1 -D

4:根目录下创建 postcss.config.js 来对 对 postcss-pxtorem 进行配置
写入配置
module.exports = {
    plugins: {
      'postcss-pxtorem': {
        // rootValue:转换的根元素的基准值
        // 正常情况下按照你的设计稿来
        // 750 宽的设计稿,750 / 10 = 75
        // 375 宽的设计稿,375 / 10 = 37.5
        rootValue: 37.5,
        // 需要转换的 CSS 属性,* 就是所有的属性都要转换
        propList: ['*'],
      },
    },
 }
 
5:重启服务 会发现px转成了rem  npm run serve

let const var的区别

  • var let(声明变量) const(声明常量变量) 的共同点和区别:

    • 共同点:都可以声明全局变量和局部变量

    • 区别:

    1.var声明的变量有变量提升,let和const没有变量提升(在声明之前打印会报错)

    2.var声明的变量可以重复声明,let和const声明的变量,在同一作用域内不能重复声明(但变量let可以重新赋值,但是常量变量const一经声明之后无法修改,不能重新赋值)

    3.var声明的全局变量可以通过window访问,let和const声明的变量无法通过全局window访问,他是存储在script中的。

    4.ES6新增的块级作用域对var没有影响,也就是说var定义的变量可以跨块级作用域访问,不能跨函数作用域访问到(如果该块级作用域处于全局环境栈var就是全局的,如果该块级作用域处于局部环境栈var就是局部的),但对于let和const如果是在块级作用域中声明(无论是全局还是局部的),就只会在块级作用域block中起作用

var let const
概述 定义变量 所声明的变量,只在let命令所在的代码块内有效 声明一个只读的常量
是否会挂在到window上 不会(形成一个新的块作用域Script中) 不会
变量提升
跨块访问 可以(没有块作用域) 不能(有块作用域) 不能
跨函数访问 不能 不能 不能
暂时性死区 不会 let 和 const 定义的变量在执行声明语句之前调用,会抛出错误(形成了暂时性死区)
是否一旦声明,必须立即初始化赋值 声明时可以不初始化 声明时可以不初始化 声明时必须初始化
同一作用域下是否可以重复声明 可以 不允许重复声明,否则会报错 不允许重复声明,否则会报错
是否可以修改 可以修改声明的变量 可以修改声明的变量 不可以修改(声明的是一个只读的常量)

遍历对象的方法

for in

for in 循环是最基础的遍历对象的方式,它还会得到对象原型链上的属性

// 创建一个对象并指定其原型,bar 为原型上的属性
const obj = Object.create({
  bar: 'bar'
})

// foo 为对象自身的属性
obj.foo = 'foo'

for (let key in obj) {
  console.log(obj[key]) // foo, bar
}

在这种情况下可以使用对象的 hasOwnProperty() 方法过滤掉原型链上的属性

for (let key in obj) {
  if (obj.hasOwnProperty(key)) {
    console.log(obj[key]) // foo
  }
}
//这时候原型上的 bar 属性就被过滤掉了

Object.keys + forEach()

Object.keys() 是 ES5 新增的一个对象方法,该方法返回对象自身属性名组成的数组,它会自动过滤掉原型链上的属性,然后可以通过数组的 forEach() 方法来遍历

Object.keys(obj).forEach((key) => {
  console.log(obj[key]) // foo
})

另外还有 Object.values() 方法和 Object.entries() 方法,这两方法的作用范围和 Object.keys() 方法类似

for in 循环和 Object.keys() 方法都不会返回对象的不可枚举属性

如果需要遍历不可枚举的属性,就要用到 Object.getOwnPropertyNames() 方法了

Object.getOwnPropertyNames

Object.getOwnPropertyNames() 也是 ES5 新增的一个对象方法,该方法返回对象自身属性名组成的数组,包括不可枚举的属性,也可以通过数组的 forEach 方法来遍历

// 创建一个对象并指定其原型,bar 为原型上的属性
// baz 为对象自身的属性并且不可枚举
const obj = Object.create({
  bar: 'bar'
}, {
  baz: {
    value: 'baz',
    enumerable: false
  }
})

obj.foo = 'foo'

// 不包括不可枚举的 baz 属性
Object.keys(obj).forEach((key) => {
  console.log(obj[key]) // foo
})

// 包括不可枚举的 baz 属性
Object.getOwnPropertyNames(obj).forEach((key) => {
  console.log(obj[key]) // baz, foo
})

有什么方式实现无限滚动

无限滚动的核心在于对滚动事件的监听,当我们监听到滚动条距离滚动区域底部一定的距离时,即加载下一页的数据,合并到当页的数据中,这样就可以实现一个简单的无限滚动了。

  1. 监听滚动条
  2. 在监听事件里计算滚动条距离滚动区域底部的距离,当距离不足10px时,则加载下一页数据
  3. 组件销毁,清除监听器

跨域和常见的跨域方式

同源和跨域概念

  • 同源策略: 是浏览器最核心最基本的安全功能, 限制了从一个源(网站)加载的文档或脚本如何与来自另一个源(网站)的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。
  • 协议名、域名、端口,这三项都相同,则被称为同源。三项中只要有一项不同,则被称为跨源。
  • 跨域并不是http请求发送不出去,请求可以发出去,服务端也能接受并正常返回结果,只是结果被浏览器拦截了

跨域的方法

jsonp
  • 原理: 引入资源不受同源策略的限制, 因为script标签支持跨域访问,所以我们可以创建script标签,src指向一个跨域文件。

    那么,该跨域文件的响应内容,就变成script标签内的内容了。

    所以,该内容也可以被理解成是正在被执行的js代码。

  • jsonp的兼容性很好,但是仅仅只支持get请求。

  • 实现方法:

    • 首先在本页面声明一个用来获取数据的回调函数
    • 创建一个script标签,将要跨域的地址加上该回调函数赋值给script的src属性
    • 服务器接收到该请求后,会在返回的文件中 将该回调函数名和数据拼接起来,返回给客户端。客户端执行该回调函数,就可以获取到服务端传过来的数据。
cors
  • CORS(Cross-Origin Resource Sharing),跨域资源共享。CORS 是官方的跨域解决方案,它的特点是不需要在客户端做任何特殊的操作,完全在服务器中进行处理,支持
    get 和post 请求。跨域资源共享标准新增了一组HTTP 首部字段,允许服务器声明哪些
    源站通过浏览器有权限访问哪些资源
  • CORS 是通过设置一个响应头来告诉浏览器,该请求允许跨域,浏览器收到该响应
    以后就会对响应放行。
//cors主要是服务端的设置
router.get("/testAJAX" , function (req , res) {
	//通过res 来设置响应头,来允许跨域请求
	//res.set("Access-Control-Allow-Origin","http://127.0.0.1:3000");
	res.set("Access-Control-Allow-Origin","*");
	res.send("testAJAX 返回的响应");
});
配置代理
  • 在vue或者react中很常用的方式, vue是在vue.config.js里面配置一个proxy, 里面有一个target属性指向跨域链接
  • react中也可以配置单个代理或者多个代理, 单个代理的话直接在package.json中加上'proxy'的地址, 配置多个代理的话可以通过一个http-proxy-middleware插件通过app.use注册多个代理

异步的几种解决方法

1.回调函数(callback)

异步编程最基本的方法:

$.ajax(url,()=>{
	//do something...
	$.ajax(url1,()=>{
		//do something...
		$.ajax(url2,()=>{
			//do something...
		})
	})
})

存在的问题:回调地狱,多个回调嵌套,各个部分之间高度耦合,使得程序结构混乱,流程难以追踪,不能使用try…catch…捕获错误,不能return。

2.事件监听
  • 采用事件驱动模式,任务的执行不取决于代码的顺序,而取决于某个事件是否发生。

什么是事件驱动模式?
js是采用事件驱动(event-driven)响应用户操作的。
比如:通过鼠标或者按键在浏览器窗口或者网页元素(按钮,文本框…)上执行的操作,我们称之为事件(event);
由鼠标或热键引发的一连串程序的动作,称之为事件驱动(event-driver);
对事件进行处理的程序或函数,我们称之为事件处理程序(event handler);

3.Promise
  • Promise对象是CommonJS工作组提出的一种规范,目的是为异步编程提供统一接口。
    Promise的思想是:每一个异步任务立刻返回一个promise对象,由于是立刻返回,所以可以采用同步的操作流程,这个promise对象有一个then方法,允许指定回调函数,在异步任务完成后调用。

  • Promise的三种状态:
    Pending——Promise实例创建时的初始状态。
    Fulfilled——成功状态
    Rejected——失败状态

  • Pending状态可以转换为Fulfilled状态或者Rejected状态,但是Fulfilled状态或Rejected状态不能转换为Pending状态,也就是说,这种状态转换是不可逆的。

  • ES6提供了原生的Promise构造函数,用来生成Promise实例

var promise = new Promise(function(resolve, reject) {
  // 异步操作的代码
  if (/* 异步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});
  • resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从Pending变为Resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从Pending变为Rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

  • Promise实例生成以后,可以用then方法分别指定Resolved状态和Reject状态的回调函数。then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法。

4.async函数

返回一个Promise对象,配合await使用

5.generator函数
  • generator函数是协程在ES6中的实现,最大特点是可以交出函数的执行权。整个generator函数就是一个异步任务的容器,异步操作需要暂停的地方,都用yield语句注明。yield表达式只能用在 Generator 函数里面,用在其他地方都会报错。

  • 形式上,Generator 函数是一个普通函数,但是有两个特征。

    • 一是,function关键字与函数名之间有一个星号;
    • 二是,函数体内部使用yield表达式,定义不同的内部状态(yield在英语里的意思就是“产出”)。
  • 调用 Generator 函数,返回一个遍历器对象,代表 Generator 函数的内部指针。以后,每次调用遍历器对象的next方法,就会返回一个有着value和done两个属性的对象。value属性表示当前的内部状态的值,是yield表达式后面那个表达式的值;done属性是一个布尔值,表示是否遍历结束。

generator函数和async函数的区别

1、generator函数被调用后返回一个遍历器对象(lterator),async函数返回一个promise对象
2、async函数内置执行器,可以像普通函数那样调用,generator函数需要使用co模块来实现流程控制或者自定义流程控制。
3、async是generator的语法糖

MVC、MVP和MVVM

js大文件上传

文件切片 + 断点续传

很多时候我们在处理文件上传时,如视频文件,小则几十M,大则 1G+,以一般的HTTP请求发送数据的方式的话,会遇到的问题:

1、文件过大,超出服务端的请求大小限制;
2、请求时间过长,请求超时;
3、传输中断,必须重新上传导致前功尽弃

js: https://www.jb51.net/article/218610.htm
vue:https://blog.csdn.net/qq_41579104/article/details/124456211
react:https://www.jb51.net/article/236865.htm

js实现基本思路

1、通过dom获取文件对象,并且对文件进行MD5加密(文件内容+文件标题形式),采用SparkMD5进行文件加密;
2、进行分片设置,文件File基于Blob, 继承了Blob的功能,可以把File当成Blob的子类,利于Blob的slice方法进行文件分片处理,并且依次进行上传
3、分片文件上传完成后,请求合并接口后端进行文件合并处理即可

react实现思路

1、将文件切成多个小的文件;

2、将切片并行上传;

3、所有切片上传完成后,服务器端进行切片合成;

4、当分片上传失败,可以在重新上传时进行判断,只上传上次失败的部分实现断点续传;

5、当切片合成为完整的文件,通知客户端上传成功;

6、已经传到服务器的完整文件,则不需要重新上传到服务器,实现秒传功能;

vue中常用的指令

  1. v-model指令:用于表单输入,实现表单控件和数据的双向绑定。
  2. v-on:简写为@,基础事件绑定
  3. v-bind:简写为,动态绑定一些元素的属性,类型可以是:字符串、对象或数组。
  4. v-if指令:取值为true/false,控制元素是否需要被渲染
  5. v-else指令:和v-if指令搭配使用,没有对应的值。当v-if的值false,v-else才会被渲染出来。
  6. v-show指令:指令的取值为true/false,分别对应着显示/隐藏。
  7. v-for指令:遍历data中存放的数组数据,实现列表的渲染。
  8. v-once: 通过使用 v-once 指令,你也能执行一次性地插值,当数据改变时,插值处的内容不会更新

改变this指向的方式

(a)call()
  • 使用: 函数.call(thisArg, arg1, arg2, ...)

  • 参数:

    • thisArg:在fun函数运行时指定的this值。指定this的值并不一定是函数执行时真正的this值,如果是原始值的this会指向该原始值的自动包装对象。
    • arg1, arg2, ...:若干个参数列表
  • 使用说明:

    • 1.调用函数
    • 2.在函数执行过程中强制将this指向call方法的第一参数 (obj 如果不传参/传参为null/undefined => 作为普通函数调用,用全局的window代替)
    • 3.如果函数需要接收参数,从第二参数开始依次往后传
(b)apply();
  • 使用: 函数.call(thisArg, [argsArray])

  • 参数:

    • thisArg:在fun函数运行时指定的this值。指定this的值并不一定是函数执行时真正的this值,如果是原始值的this会指向该原始值的自动包装对象。
    • argsArray:一个数组或者类数组对象,其中的数组元素将作为单独的参数传给fun函数。参数为null或者undefined,则表示不需要传入任何参数。
  • (用法同call)

    call()apply():借鸡生蛋 => 并不生成新的函数,而是借用一次原本的函数

(c)bind();
  • 使用: 函数.bind(thisArg, arg1, arg2, ...)
  • 用法:
    • 1.调用函数,根据原函数得到一个新函数,必须手动去调用(对原函数没有影响)
    • 2.在函数执行过程中强制将this指向bind方法的第一参数(obj如果不传参/传参为null/undefined => 作为普通函数调用,用全局的window代替)
    • 3.如果函数需要接收参数 =>
      • a. 从bind()方法的第二参数开始依次往后传 => 此后新函数的参数指定
      • b. bind()方法不指定 => 新函数调用时传入
      • 总结: 函数的参数可以由bind()和新函数共同决定

微信小程序开发和web开发的区别

  • 小程序的主要开发语言是 JavaScript, 小程序的开发同普通的网页开发相比有很大的相似性

  • 网页开发渲染线程和脚本线程是互斥的,这也是为什么长时间的脚本运行可能会导致页面失去响应,而在小程序中,二者是分开的,分别运行在不同的线程中。网页开发者可以使用到各种浏览器暴露出来的 DOM API,进行 DOM 选中和操作。而小程序的逻辑层和渲染层是分开的,逻辑层运行在 JSCore 中,并没有一个完整浏览器对象,因而缺少相关的DOM API和BOM API。这一区别导致了前端开发非常熟悉的一些库,例如 jQuery、 Zepto 等,在小程序中是无法运行的。同时 JSCore 的环境同 NodeJS 环境也是不尽相同,所以一些 NPM 的包在小程序中也是无法运行的。

  • 网页开发者需要面对的环境是各式各样的浏览器 (PC 端需要面对 IE、Chrome、QQ浏览器等,在移动端需要面对Safari、Chrome以及 iOS、Android 系统中的各式 WebView) 。而小程序开发过程中需要面对的是两大操作系统 iOS 和 Android 的微信客户端,以及用于辅助开发的小程序开发者工具,小程序中三大运行环境也是有所区别的

react中props和state的区别

  • props: 主要是用于组件之间传递参数,获取组件的属性值。 组件之间数据单向流动 ,从父组件流向子组件。对于外界/父组件的属性值,无法直接修改,它是只读的。
  • state: 主要用于组件更新控制,如果想重新渲染或更新组件,只需要修改state即可,然后根据具体修改的state,重新渲染用户界面(无需操作DOM对象)

组件绑定和js原生绑定事件哪个先执行

先执行js原生绑定事件,再执行合成事件,因为合成事件是发生在冒泡阶段

Token一般是存放在哪里

Token其实就是访问资源的凭证。一般是用户通过用户名和密码登录成功之后,服务器将登陆凭证做数字签名,加密之后得到的字符串作为token。它在用户登录成功之后会返回给客户端,客户端主要有这么几种存储方式:

  • 存储在localStorage中,每次调用接口的时候放在HTTP请求头的Authorization字段里传给后台。
  • 存储在cookie 中,让它自动发送,不过缺点就是不能跨域。

存储在cookie和webStorage中的区别:

  • 将token存放在webStroage中,可以通过周域的js来访问。这样会导致很容易受到xss攻击(一种注入代码攻击,通过在目标网站上注入script代码,当访问者浏览网站的时候通过执行注入的script代码达到窃取用户信息),特别是项目中引入很多第三方js类库的情况下。如果js脚本被盗用,攻击者就可以轻易访问你的网站, webStroage作为一种储存机制,在传输过程中不会执行任何安全标准。
  • 将token存放在cookie中可以指定 httponly,来防止被Javascript读取,也可以指定secure,来保证token只在HTTPS下传输。缺点是不符合Restful最佳实践,容易受到CSRF攻击(恶意攻击者盗用已经认证过的用户信息,以用户信息名义进行一些操作, 由于身份已经认证过,所以目标网站会认为操作都是真正的用户操作的。CSRF并不能拿到用户信息,它只是盗用的用户凭证去进行操作)

hooks中父组件使用子组件的方法

/* child子组件 */
// https://reactjs.org/docs/hooks-reference.html#useimperativehandle
import {useState, useImperativeHandle} from 'react';
// props子组件中需要接受ref
const ChildComp = ({cRef}) => {
	const [val, setVal] = useState();
	// 此处注意useImperativeHandle方法的的第一个参数是目标元素的ref引用
	useImperativeHandle(cRef, () => ({
		// changeVal 就是暴露给父组件的方法
	    changeVal: (newVal) => {
	      setVal(newVal);
	    }
  	}));
  	...
  	return (
		<div>{val}</div>
	)
}
/* FComp 父组件 */
import {useRef} from 'react;
...
const FComp = () => {
	const childRef = useRef();
	const updateChildState = () => {
		// changeVal就是子组件暴露给父组件的方法
		childRef.current.changeVal(99);
	}
	...
	return (
		<>
			{/* 此处注意需要将childRef通过props属性从父组件中传给自己 cRef={childRef} */}
			<ChildComp ref={childRef} cRef={childRef} />
			<button onClick={updateChildState}>触发子组件方法</button>
		</>
	)
}
posted @ 2022-06-27 12:22  嘻嘻不是菜鸟了  阅读(78)  评论(0)    收藏  举报