调用 setState 之后产生了什么
在代码中调用 setState 函数之后,React 会将传入的参数与之前的状态进行合并,而后触发所谓的和谐过程(Reconciliation)。通过和谐过程,React 会以绝对高效的形式依据新的状态构建 React 元素树并且着手从新渲染整个 UI 界面。在 React 失去元素树之后,React 会计算出新的树和老的树之间的差别,而后依据差别对界面进行最小化从新渲染。通过 diff 算法,React 可能准确制导哪些地位产生了扭转以及应该如何扭转,这就保障了按需更新,而不是全副从新渲染。
- 在 setState 的时候,React 会为以后节点创立一个 updateQueue 的更新列队。
- 而后会触发 reconciliation 过程,在这个过程中,会应用名为 Fiber 的调度算法,开始生成新的 Fiber 树,Fiber 算法的最大特点是能够做到异步可中断的执行。
- 而后 React Scheduler 会依据优先级高下,先执行优先级高的节点,具体是执行 doWork 办法。
- 在 doWork 办法中,React 会执行一遍 updateQueue 中的办法,以取得新的节点。而后比照新旧节点,为老节点打上 更新、插入、替换 等 Tag。
- 以后节点 doWork 实现后,会执行 performUnitOfWork 办法取得新节点,而后再反复下面的过程。
- 当所有节点都 doWork 实现后,会触发 commitRoot 办法,React 进入 commit 阶段。
- 在 commit 阶段中,React 会依据后面为各个节点打的 Tag,一次性更新整个 dom 元素
能够应用 TypeScript 写 React 利用吗?怎么操作?
(1)如果还未创立 Create React App 我的项目
- 间接创立一个具备 typescript 的 Create React App 我的项目:
npx create-react-app demo --typescript
(2)如果曾经创立了 Create React App 我的项目,须要将 typescript 引入到已有我的项目中
- 通过命令将 typescript 引入我的项目:
npm install --save typescript @types/node @types/react @types/react-dom @types/jest
- 将我的项目中任何 后缀名为‘.js’的 JavaScript 文件重命名为 TypeScript 文件即后缀名为‘.tsx’(例如 src/index.js 重命名为 src/index.tsx)
react 实现一个全局的 dialog
import React, {Component} from 'react';
import {is, fromJS} from 'immutable';
import ReactDOM from 'react-dom';
import ReactCSSTransitionGroup from 'react-addons-css-transition-group';
import './dialog.css';
let defaultState = {
alertStatus:false,
alertTip:"提醒",
closeDialog:function(){},
childs:''
}
class Dialog extends Component{
state = {...defaultState};
// css 动画组件设置为指标组件
FirstChild = props => {const childrenArray = React.Children.toArray(props.children);
return childrenArray[0] || null;
}
// 关上弹窗
open =(options)=>{options = options || {};
options.alertStatus = true;
var props = options.props || {};
var childs = this.renderChildren(props,options.childrens) || '';
console.log(childs);
this.setState({
...defaultState,
...options,
childs
})
}
// 敞开弹窗
close(){this.state.closeDialog();
this.setState({...defaultState})
}
renderChildren(props,childrens) {
// 遍历所有子组件
var childs = [];
childrens = childrens || [];
var ps = {
...props, // 给子组件绑定 props
_close:this.close // 给子组件也绑定一个敞开弹窗的事件
};
childrens.forEach((currentItem,index) => {
childs.push(React.createElement(
currentItem,
{
...ps,
key:index
}
));
})
return childs;
}
shouldComponentUpdate(nextProps, nextState){return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
}
render(){
return (
<ReactCSSTransitionGroup
component={this.FirstChild}
transitionName='hide'
transitionEnterTimeout={300}
transitionLeaveTimeout={300}>
<div className="dialog-con" style={this.state.alertStatus? {display:'block'}:{display:'none'}}>
{this.state.childs} </div>
</ReactCSSTransitionGroup>
);
}
}
let div = document.createElement('div');
let props = { };
document.body.appendChild(div);
let Box = ReactD
子类:
// 子类 jsx
import React, {Component} from 'react';
class Child extends Component {constructor(props){super(props);
this.state = {date: new Date()};
}
showValue=()=>{this.props.showValue && this.props.showValue()
}
render() {
return (
<div className="Child">
<div className="content">
Child <button onClick={this.showValue}> 调用父的办法 </button>
</div>
</div>
);
}
}
export default Child;
css:
.dialog-con{
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.3);
}
class 类的 key 改了,会产生什么,会执行哪些周期函数?
在开发过程中,咱们须要保障某个元素的 key 在其同级元素中具备唯一性。在 React Diff 算法中 React 会借助元素的 Key 值来判断该元素是早先创立的还是被挪动而来的元素,从而缩小不必要的元素重渲染。此外,React 还须要借助 Key 值来判断元素与本地状态的关联关系,因而咱们绝不可漠视转换函数中 Key 的重要性。
答:componentWillMount componentDidMount render
何为 redux
Redux 的根本思维是整个利用的 state 放弃在一个繁多的 store 中。store 就是一个简略的 javascript 对象,而扭转利用 state 的惟一形式是在利用中触发 actions,而后为这些 actions 编写 reducers 来批改 state。整个 state 转化是在 reducers 中实现,并且不应该有任何副作用。
指出 (组件) 生命周期办法的不同
componentWillMount
— 多用于根组件中的应用程序配置componentDidMount
— 在这能够实现所有没有 DOM 就不能做的所有配置,并开始获取所有你须要的数据;如果须要设置事件监听,也能够在这实现componentWillReceiveProps
— 这个周期函数作用于特定的 prop 扭转导致的 state 转换shouldComponentUpdate
— 如果你放心组件适度渲染,shouldComponentUpdate
是一个改善性能的中央,因为如果组件接管了新的prop
,它能够阻止 (组件) 从新渲染。shouldComponentUpdate 应该返回一个布尔值来决定组件是否要从新渲染componentWillUpdate
— 很少应用。它能够用于代替组件的componentWillReceiveProps
和shouldComponentUpdate
(但不能拜访之前的 props)componentDidUpdate
— 罕用于更新 DOM,响应 prop 或 state 的扭转componentWillUnmount
— 在这你能够勾销网络申请,或者移除所有与组件相干的事件监听器
参考 前端进阶面试题具体解答
何为 reducer
一个 reducer 是一个纯函数,该函数以先前的 state 和一个 action 作为参数,并返回下一个 state。
React 中 refs 的作用是什么?有哪些利用场景?
Refs 提供了一种形式,用于拜访在 render 办法中创立的 React 元素或 DOM 节点。Refs 应该审慎应用,如下场景应用 Refs 比拟适宜:
- 解决焦点、文本抉择或者媒体的管制
- 触发必要的动画
- 集成第三方 DOM 库
Refs 是应用 React.createRef()
办法创立的,他通过 ref
属性附加到 React 元素上。要在整个组件中应用 Refs,须要将 ref
在构造函数中调配给其实例属性:
class MyComponent extends React.Component {constructor(props) {super(props)
this.myRef = React.createRef()}
render() {return <div ref={this.myRef} />
}
}
因为函数组件没有实例,因而不能在函数组件上间接应用 ref
:
function MyFunctionalComponent() {return <input />;}
class Parent extends React.Component {constructor(props) {super(props);
this.textInput = React.createRef();}
render() {
// 这将不会工作!return (<MyFunctionalComponent ref={this.textInput} />
);
}
}
但能够通过闭合的帮忙在函数组件外部进行应用 Refs:
function CustomTextInput(props) {
// 这里必须申明 textInput,这样 ref 回调才能够援用它
let textInput = null;
function handleClick() {textInput.focus();
}
return (
<div>
<input
type="text"
ref={(input) => {textInput = input;}} /> <input
type="button"
value="Focus the text input"
onClick={handleClick}
/>
</div>
);
}
留神:
- 不应该适度的应用 Refs
-
ref
的返回值取决于节点的类型:- 当
ref
属性被用于一个一般的 HTML 元素时,React.createRef()
将接管底层 DOM 元素作为他的current
属性以创立ref
。 - 当
ref
属性被用于一个自定义的类组件时,ref
对象将接管该组件已挂载的实例作为他的current
。
- 当
- 当在父组件中须要拜访子组件中的
ref
时可应用传递 Refs 或回调 Refs。
Component, Element, Instance 之间有什么区别和分割?
- 元素: 一个元素
element
是一个一般对象 (plain object),形容了对于一个 DOM 节点或者其余组件component
,你想让它在屏幕上出现成什么样子。元素element
能够在它的属性props
中蕴含其余元素 (译注: 用于造成元素树)。创立一个 React 元素element
老本很低。元素element
创立之后是不可变的。 - 组件: 一个组件
component
能够通过多种形式申明。能够是带有一个render()
办法的类,简略点也能够定义为一个函数。这两种状况下,它都把属性props
作为输出,把返回的一棵元素树作为输入。 - 实例: 一个实例
instance
是你在所写的组件类component class
中应用关键字this
所指向的货色(译注: 组件实例)。它用来存储本地状态和响应生命周期事件很有用。
函数式组件 (Functional component
) 基本没有实例 instance
。类组件(Class component
) 有实例instance
,然而永远也不须要间接创立一个组件的实例,因为 React 帮咱们做了这些。
在结构函数调用 super 并将 props 作为参数传入的作用
在调用 super() 办法之前,子类构造函数无奈应用 this 援用,ES6 子类也是如此。
将 props 参数传递给 super() 调用的次要起因是在子构造函数中可能通过 this.props 来获取传入的 props
传递了 props
class MyComponent extends React.Component {constructor(props) {super(props);
console.log(this.props); // {name: 'sudheer',age: 30}
}
}
没传递 props
class MyComponent extends React.Component {constructor(props) {super();
console.log(this.props); // undefined
// 然而 Props 参数依然可用
console.log(props); // Prints {name: 'sudheer',age: 30}
}
render() {
// 构造函数内部不受影响
console.log(this.props); // {name: 'sudheer',age: 30}
}
}
react-router4 的外围
- 路由变成了组件
- 扩散到各个页面,不须要配置 比方
<link> <route></route>
如何在 React 中应用 innerHTML
减少 dangerouslySetInnerHTML 属性,并且传入对象的属性名叫 \_html
function Component(props){return <div dangerouslySetInnerHTML={{_html:'<span> 你好 </span>'}}>
</div>
}
展现组件 (Presentational component) 和容器组件 (Container component) 之间有何不同
展现组件关怀组件看起来是什么。展现专门通过 props 承受数据和回调,并且简直不会有本身的状态,但当展现组件领有本身的状态时,通常也只关怀 UI 状态而不是数据的状态。
容器组件则更关怀组件是如何运作的。容器组件会为展现组件或者其它容器组件提供数据和行为 (behavior),它们会调用 Flux actions
,并将其作为回调提供给展现组件。容器组件常常是有状态的,因为它们是(其它组件的) 数据源。
为什么要应用 React. Children. map(props. children,()=>)而不是 props. children. map (() => )?
因为不能保障 props. children 将是一个数组。
以上面的代码为例。
<Parent>
<h1> 有课前端网 </h1>
</Parent>
在父组件外部,如果尝试应用 props.children. map 映射子对象,则会抛出谬误,因为 props. children 是一个对象,而不是一个数组。
如果有多个子元素,React 会使 props.children 成为一个数组,如下所示。
<Parent>
<h1> 有课前端网 </h1>
<h2> 前端技术学习平台 </h2>
</Parent>;
// 不倡议应用如下形式,在这个案例中会抛出谬误。class Parent extends Component {render() {return <div> {this.props.children.map((obj) => obj)}</div>;
}
}
倡议应用如下形式,防止在上一个案例中抛出谬误。
class Parent extends Component {render() {return <div> {React.Children.map(this.props.children, (obj) => obj)}</div>;
}
}
vue 或者 react 优化整体优化
- 虚构 dom
为什么虚构 dom 会进步性能?(必考)
虚构 dom 相当于在 js 和实在 dom 两头加了一个缓存,利用 dom diff 算法防止了没有必要的 dom 操作,从而进步性能。
用 JavaScript 对象构造示意 DOM 树的构造;而后用这个树构建一个真正的 DOM 树,插到文档当中当状态变更的时候,从新结构一棵新的对象树。而后用新的树和旧的树进行比拟,记录两棵树差别把 2 所记录的差别利用到步骤 1 所构建的真正的 DOM 树上,视图就更新了。
React 的事件和一般的 HTML 事件有什么不同?
区别:
- 对于事件名称命名形式,原生事件为全小写,react 事件采纳小驼峰;
- 对于事件函数解决语法,原生事件为字符串,react 事件为函数;
- react 事件不能采纳 return false 的形式来阻止浏览器的默认行为,而必须要地明确地调用
preventDefault()
来阻止默认行为。
合成事件是 react 模仿原生 DOM 事件所有能力的一个事件对象,其长处如下:
- 兼容所有浏览器,更好的跨平台;
- 将事件对立寄存在一个数组,防止频繁的新增与删除(垃圾回收)。
- 不便 react 对立治理和事务机制。
事件的执行程序为原生事件先执行,合成事件后执行,合成事件会冒泡绑定到 document 上,所以尽量避免原生事件与合成事件混用,如果原生事件阻止冒泡,可能会导致合成事件不执行,因为须要冒泡到 document 上合成事件才会执行。
react 强制刷新
component.forceUpdate() 一个不罕用的生命周期办法, 它的作用就是强制刷新
官网解释如下
默认状况下,当组件的 state 或 props 发生变化时,组件将从新渲染。如果 render() 办法依赖于其余数据,则能够调用 forceUpdate() 强制让组件从新渲染。
调用 forceUpdate() 将以致组件调用 render() 办法,此操作会跳过该组件的 shouldComponentUpdate()。但其子组件会触发失常的生命周期办法,包含 shouldComponentUpdate() 办法。如果标记发生变化,React 仍将只更新 DOM。
通常你应该防止应用 forceUpdate(),尽量在 render() 中应用 this.props 和 this.state。
shouldComponentUpdate 在初始化 和 forceUpdate 不会执行
ssr 原理是什么?
外围原理其实就是借助虚构 DOM 来实现 react 代码可能在服务器运行的,node 外面能够执行 react 代码
diff 算法?
- 把树形构造依照层级合成,只比拟同级元素
- 给列表构造的每个单元增加惟一的 key 属性,不便比拟
- React 只会匹配雷同 class 的 component(这外面的 class 指的是组件的名字)
- 合并操作,调用 component 的 setState 办法的时候, React 将其标记为 dirty. 到每一个 事件循环完结, React 查看所有标记 dirty 的 component 从新绘制.
- 抉择性子树渲染。开发人员能够重写 shouldComponentUpdate 进步 diff 的性能。
React 申明组件有哪几种办法,有什么不同?
React 申明组件的三种形式:
- 函数式定义的
无状态组件
- ES5 原生形式
React.createClass
定义的组件 - ES6 模式的
extends React.Component
定义的组件
(1)无状态函数式组件 它是为了创立纯展现组件,这种组件只负责依据传入的 props 来展现,不波及到 state 状态的操作
组件不会被实例化,整体渲染性能失去晋升,不能拜访 this 对象,不能拜访生命周期的办法
(2)ES5 原生形式 React.createClass // RFC React.createClass 会自绑定函数办法,导致不必要的性能开销,减少代码过期的可能性。
(3)E6 继承模式 React.Component // RCC 目前极为举荐的创立有状态组件的形式,最终会取代 React.createClass 模式;绝对于 React.createClass 能够更好实现代码复用。
无状态组件绝对于于后者的区别: 与无状态组件相比,React.createClass 和 React.Component 都是创立有状态的组件,这些组件是要被实例化的,并且能够拜访组件的生命周期办法。
React.createClass 与 React.Component 区别:
① 函数 this 自绑定
- React.createClass 创立的组件,其每一个成员函数的 this 都有 React 主动绑定,函数中的 this 会被正确设置。
- React.Component 创立的组件,其成员函数不会主动绑定 this,须要开发者手动绑定,否则 this 不能获取以后组件实例对象。
② 组件属性类型 propTypes 及其默认 props 属性 defaultProps 配置不同
- React.createClass 在创立组件时,无关组件 props 的属性类型及组件默认的属性会作为组件实例的属性来配置,其中 defaultProps 是应用 getDefaultProps 的办法来获取默认组件属性的
- React.Component 在创立组件时配置这两个对应信息时,他们是作为组件类的属性,不是组件实例的属性,也就是所谓的类的动态属性来配置的。
③ 组件初始状态 state 的配置不同
- React.createClass 创立的组件,其状态 state 是通过 getInitialState 办法来配置组件相干的状态;
- React.Component 创立的组件,其状态 state 是在 constructor 中像初始化组件属性一样申明的。