React

1. 什么是React?

React是用于构建用户界面的JavaScript库 , 起源于Facebook的内部项目,该公司对市场上所有 JavaScript MVC框架都不满意,决定自行开发一套,用于架设自己的网站 ,React 不是一个 MVC 框架,仅仅是视图(V)层的库

2. 什么是JSX?

jsx是JavaScript的一种语法扩展,它跟模板语言很接近,但是它充分具备JavaScript的能力

JSX就是用来声明React当中的元素,React使用JSX来描述用户界面

JSX语法糖允许前端开发者使用我们最熟悉的类HTML标签语法来创建虚拟DOM在降低学习成本

3. class组件和函数组件区别

语法上:

函数式组件是一个纯函数,它是需要接受props参数并且返回一个React元素就可以了。类组件是需要继承React.Component的,而且class组件需要创建render并且返回React元素,语法上来讲更复杂。

状态管理:

函数式组件没有状态管理,类组件有状态管理。

调用方式:

函数式组件可以直接调用,返回一个新的React元素;类组件在调用时是需要创建一个实例的,然后通过调用实例里的render方法来返回一个React元素。

4. 事件处理方法this指向改变

当我们把事件函数写成普通函数的形式时 , 调用函数使用state变量会报错,提示state变量不存在,

是因为

  • 事件处理程序的函数式函数调用模式,在严格模式下,this指向undefined

  • render函数是被组件实例调用的,因此render函数中的this指向当前组件

解决方法: 1. 把普通函数改成箭头函数 2. 调用函数的时候使用bind方法改变this指向

5. React如何获取表单数据

  1. 给文本框绑定value属性,value属性绑定state中定义的变量

  2. 给表单绑定onChange事件,调用定义的方法

  3. 在方法中我们获取e.target.value属性,赋给value属性绑定的变量

6. React条件渲染方法有哪些

  1. if-else的条件渲染方法

  2. 三元运算符进行条件渲染,可以缩短代码量

  3. switch的多条件渲染效果

  4. HOC条件渲染

7. React怎么实现列表渲染

react中可以使用map方法渲染列表,return对应的页面结构即可, React 在渲染列表时,会要求开发者为每一个列表元素指定唯一的 key ,我们尽量不要使用index索引值作为key,如果对数据进行:逆序添加、逆序删除等破坏顺序操作:可能会引起页面更新错误问题。

8. React中key的作用是什么?

key是虚拟DOM对象的唯一标识,在更新显示时key起到极其重要的作用 ,简单的来说就是为了提高diff的同级比较的效率,避免原地复用带来的副作用

react采用的是自顶而下的更新策略,每次小的改动都会生成一个全新的的vdom,从而进行diff,如果不写key,就会发生本来应该更新却没有更新

9. React组件样式的定义方式

  1. 外联样式

    定义css文件,在组件中通过import导入css样式,

    import "App.css"

  2. 内联样式

    React推崇的是内联的方式定义样式。这样做的目的就在于让你的组件更加的容易复用

    定义一个style属性,属性中定义对应的css样式即可,比如style={{fontSize:'15px'}}

    外层花括号是语法,内层花括号是对象边界符

10. Props校验数据类型

array(数组)、bool(布尔值)、func(函数number(数字)、object(对象)、string(字符串)

11.受控组件和非受控组件

受控组件 由React控制的输入表单元素而改变其值的方式,称为受控组件。 比如,给表单元素input绑定一个onChange事件,当input状态发生变化时就会触发onChange事件,从而更新组件的state。 非受控组件 非受控组件指的是,表单数据由DOM本身处理。即不受setState()的控制,与传统的HTML表单输入相似,input输入值即显示最新值。 在非受控组件中,可以使用一个ref来从DOM获得表单值。

12. props和state的区别

props是指组件间传递的一种方式,props自然也可以传递state。由于React的数据流是自上而下的,所以是从父组件向子组件进行传递;另外组件内部的this.props属性是只读的不可修改!

state是组件内部的状态(数据),不能够直接修改,必须要通过setState来改变值的状态,从而达到更新组件内部数据的作用。

13.说说React生命周期中有哪些坑?如何避免

        ComponentWillReceiveProps方法被改为getDeriveStateFromProps方法,在旧版本中ComponentWillReceiveProps方法可用,很多人其实并不明白这个方法到底数如何触发的,触发条件是父组件修改传递给子组件的属性的时候这个修改会带动子组件修改触发ComponentWillReceiveProps生命周期方法

14.调和阶段setState干了什么

        一个组件的显示状态是由数据状态和外部参数决定,数据状态就是state,当需要修改值时必须通过setstate来改变,从而达到更新组件内部数据的作用

15.说说redux的实现原理是什么,写出核心代码?

一、是什么

React是用于构建用户界面的,帮助我们解决渲染DOM的过程

而在整个应用中会存在很多个组件,每个组件的state是由自身进行管理,包括组件定义自身的state、组件之间的通信通过props传递、使用Context实现数据共享

如果让每个组件都存储自身相关的状态,理论上来讲不会影响应用的运行,但在开发及后续维护阶段,我们将花费大量精力去查询状态的变化过程

这种情况下,如果将所有的状态进行集中管理,当需要更新状态的时候,仅需要对这个管理集中处理,而不用去关心状态是如何分发到每一个组件内部的

redux就是一个实现上述集中管理的容器,遵循三大基本原则:

  • 单一数据源
  • state 是只读的
  • 使用纯函数来执行修改

注意的是,redux并不是只应用在react中,还与其他界面库一起使用,如Vue

二、工作原理

redux 要求我们把数据都放在 store 公共存储空间

一个组件改变了 store 里的数据内容,其他组件就能感知到 store 的变化,再来取数据,从而间接的实现了这些数据传递的功能

工作流程图如下所示:

预览

根据流程图,可以想象,React Components 是借书的用户, Action Creactor 是借书时说的话(借什么书), Store 是图书馆管理员,Reducer 是记录本(借什么书,还什么书,在哪儿,需要查一下), state 是书籍信息

整个流程就是借书的用户需要先存在,然后需要借书,需要一句话来描述借什么书,图书馆管理员听到后需要查一下记录本,了解图书的位置,最后图书馆管理员会把这本书给到这个借书人

转换为代码是,React Components 需要获取一些数据, 然后它就告知 Store 需要获取数据,这就是就是 Action Creactor , Store 接收到之后去 Reducer 查一下, Reducer 会告诉 Store 应该给这个组件什么数据

16.React合成事件的原理

        合成事件是模拟原生dom事件左右能力的一个对象,浏览器的原生事件:浏览器包装器,兼容所有的浏览器,拥有与浏览器原生事件相同的接口

17.React组件之间如何通信

        常用的组件通讯方式有父传子、子传父、兄弟组件传值

        父传子就是在父组件中的子组件标签上绑定一个自定义数据,子组件通过props进行接收传递过来的数据

子传父就是在父组件的子组件标签绑定一个方法,将方法传递给子组件,子组件拿到这个方法就父组件接收这个方法

        兄弟组件传值就是通过他们的上一层组件作为父组件,将数据共享给父组件,最后再实现兄弟之间专递

18.为什么react元素有一个$$type属性?

        因为json不支持symbol类型,所以即使服务器存在用json作为文本返回,react会检测element$typeof,如果元素丢失或者无效,会拒绝处理该元素

19.说说Connect组件的原理是什么

        Connect有四个参数,一般只用到前两种

        第一个参数是将store中的数据作为props绑定到组件上,主要原理就是将需要绑定的props作为一个函数传过来,在connect传给一个真实的数据

        第二个参数是用于更改数据必须要触发action,在这里的主要功能是将action作为props绑定到组件上

20.说说你对redux中间件的理解?常用的中间件有哪些?实现原理?

        Redux中间件就是放在dispatch的过程,在分发axtion进行拦截处理,redux的整个工作流程是当action发出后,reducer一级算出state,整个过程是一个同步操作,如果需要异步操作或者错误日志,这个过程就需要加上中间件,

        常用的中间件:redux-thuck用于异步操作、redux-logger用于日志记录

        实现原理:中间件都需要你通过applyMiddleware进行注册,作用就是将所有的中间件组成一个数组,一次执行然后作为第二个参数传入到createStore

21.React性能优化的手段有哪些?

  • 使用 shouldComponentUpdate 避免不需要的渲染,但是如果对 props 和 state 做深比较,代价很大,所以需要根据业务进行些取舍;在有子组件的情况下,为了避免子组件的重复渲染,可以通过父组件来判断子组件是否需要 PureRender。

  • 将 props 设置为数组或对象:每次调用 React 组件都会创建新组件,就算传入的数组或对象的值没有改变,他们的引用地址也会发生改变,比如,如果按照如下的写法,那么每次渲染时 style 都是一个新对象

// 不推荐
<button style={{ color: 'red' }} />

// 推荐
const style = { color: 'red' }
<button style={style} />

// 不推荐
<button style={this.props.style || {} } />  

// 推荐
const defaultStyle = {}
<button style={this.props.style || defaultStyle } />   
  • 将函数的绑定移动到构造函数内:可以避免每次都绑定事件。
  • 使用 immutable 不可变数据,在我们项目中使用引用类型时,为了避免对原始数据的影响,一般建议使用 shallowCopy 和 deepCopy 对数据进行处理,但是这样会造成 CPU 和 内存的浪费,所以推荐使用 immutable,优点如下
    • 降低了“可变”带来的复杂度
    • 节省内存,immutable 使用结构共享尽量复用内存,没有被引用的对象会被垃圾回收
    • 可以更好的做撤销/重做,复制/粘贴,时间旅行
    • 不会有并发问题(因为数据本身就是不可变的)
    • 拥抱函数式编程
  • 给子组件设置一个唯一的 key,因为在 diff 算法中,会用 key 作为唯一标识优化渲染

22. 简述React的生命周期函数?

挂载阶段:

  • constructor() 在 React 组件挂载之前,会调用它的构造函数。

  • componentWillMount: 在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用。

  • componentDidMount(): 在组件挂载后(插入 DOM 树中)立即调用

更新运行阶段:

  • componentWillReceiveProps: 在接受父组件改变后的props需要重新渲染组件时用到的比较多,外部组件传递频繁的时候会导致效率比较低

  • shouldComponentUpdate():用于控制组件重新渲染的生命周期,state发生变化,组件会进入重新渲染的流程,在这里return false可以阻止组件的更新

  • render(): render() 方法是 class 组件中唯一必须实现的方法。

  • *componentWillUpdate()**: shouldComponentUpdate返回true以后,组件进入重新渲染完成之前进入这个函数。

  • componentDidUpdate(): 每次state改变并重新渲染页面后都会进入这个生命周期 卸载或销毁阶段 componentWillUnmount (): 在此处完成组件的卸载和数据的销毁。

23. React旧生命周期有哪些问题?

(1) componentWillMount ,在ssr中 这个方法将会被多次调用, 所以会重复触发多遍,同时在这里如果绑定事件, 将无法解绑,导致内存泄漏 , 变得不够安全高效逐步废弃。 (2) componentWillReceiveProps 外部组件多次频繁更新传入多次不同的 props,会导致不必要的异步请求 (3) componetWillupdate, 更新前记录 DOM 状态, 可能会做一些处理,与componentDidUpdate相隔时间如果过长, 会导致 状态不太信

24. React新生命周期有哪些改变?

  1. 用 getDerivedStateFromProps替换了 compoentWillMount和compontWillReceiveProps生命周期函数

  2. 用getSnapshotBeforeUpdate函数替换componetWillUpdate方法,避免和CompoentDidUpdate函数中获取数据不一致的问题

25.说说对高阶组件的理解?应用场景?

高阶函数(Higher-order function),至少满足下列一个条件的函数 接受一个或多个函数作为输入,输出一个函数 在React中,高阶组件即接受一个或多个组件作为参数并且返回一个组件,本质也就是一个函数,并不是一个组件 高阶组件的主要功能是封装并分离组件的通用逻辑,让通用逻辑在组件间更好地被复用 高阶组件可以传递所有的props,但是不能传递ref 高阶组件能够提高代码的复用性和灵活性,在实际应用中,常常用于与核心业务无关但又在多个模块使用的功能,如权限控制、日志记录、数据校验、异常处理、统计上报等

26.bind、call、apply 区别?如何实现一个bind?

一、作用

call apply bind 作用是改变函数执行时的上下文,简而言之就是改变函数运行时的this指向

那么什么情况下需要改变this的指向呢?下面举个例子

const name="lucy";
const obj={
    name:"martin",
    say:function () {
        console.log(this.name);
    }
};
obj.say(); //martin,this指向obj对象
setTimeout(obj.say,0); //lucy,this指向window对象

从上面可以看到,正常情况say方法输出martin

但是我们把say放在setTimeout方法中,在定时器中是作为回调函数来执行的,因此回到主栈执行时是在全局执行上下文的环境中执行的,这时候this指向window,所以输出luck

我们实际需要的是this指向obj对象,这时候就需要该改变this指向了

1setTimeout(obj.say.bind(obj),0); //martin,this指向obj对象

二、区别

下面再来看看applycallbind的使用

apply

apply接受两个参数,第一个参数是this的指向,第二个参数是函数接受的参数,以数组的形式传入

改变this指向后原函数会立即执行,且此方法只是临时改变this指向一次

function fn(...args){
    console.log(this,args);
}
let obj = {
    myname:"张三"
}

fn.apply(obj,[1,2]); // this会变成传入的obj,传入的参数必须是一个数组;
fn(1,2) // this指向window

当第一个参数为nullundefined的时候,默认指向window(在浏览器中)

fn.apply(null,[1,2]); // this指向window
fn.apply(undefined,[1,2]); // this指向window

call

call方法的第一个参数也是this的指向,后面传入的是一个参数列表

apply一样,改变this指向后原函数会立即执行,且此方法只是临时改变this指向一次

function fn(...args){
    console.log(this,args);
}
let obj = {
    myname:"张三"
}

fn.call(obj,1,2); // this会变成传入的obj,传入的参数必须是一个数组;
fn(1,2) // this指向window

同样的,当第一个参数为nullundefined的时候,默认指向window(在浏览器中)

fn.call(null,[1,2]); // this指向window
fn.call(undefined,[1,2]); // this指向window

bind

bind方法和call很相似,第一参数也是this的指向,后面传入的也是一个参数列表(但是这个参数列表可以分多次传入)

改变this指向后不会立即执行,而是返回一个永久改变this指向的函数

function fn(...args){
    console.log(this,args);
}
let obj = {
    myname:"张三"
}

const bindFn = fn.bind(obj); // this 也会变成传入的obj ,bind不是立即执行需要执行一次
bindFn(1,2) // this指向obj
fn(1,2) // this指向window

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蜡笔小开心

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值