什么起因会促使你脱离 create-react-app 的依赖
当你想去配置 webpack 或 babel presets。
React 16 中新生命周期有哪些
对于 React16 开始利用的新生命周期:能够看出,React16 自上而下地对生命周期做了另一种维度的解读:
- Render 阶段:用于计算一些必要的状态信息。这个阶段可能会被 React 暂停,这一点和 React16 引入的 Fiber 架构(咱们前面会重点解说)是无关的;
- Pre-commit 阶段:所谓“commit”,这里指的是“更新真正的 DOM 节点”这个动作。所谓 Pre-commit,就是说我在这个阶段其实还并没有去更新实在的 DOM,不过 DOM 信息曾经是能够读取的了;
- Commit 阶段:在这一步,React 会实现实在 DOM 的更新工作。Commit 阶段,咱们能够拿到实在 DOM(包含 refs)。
与此同时,新的生命周期在流程方面,依然遵循“挂载”、“更新”、“卸载”这三个狭义的划分形式。它们别离对应到:
-
挂载过程:
- constructor
- getDerivedStateFromProps
- render
- componentDidMount
-
更新过程:
- getDerivedStateFromProps
- shouldComponentUpdate
- render
- getSnapshotBeforeUpdate
- componentDidUpdate
-
卸载过程:
- componentWillUnmount
React.forwardRef 是什么?它有什么作用?
React.forwardRef 会创立一个 React 组件,这个组件可能将其承受的 ref 属性转发到其组件树下的另一个组件中。这种技术并不常见,但在以下两种场景中特地有用:
- 转发 refs 到 DOM 组件
- 在高阶组件中转发 refs
为什么虚构 dom 会进步性能
虚构 dom 相当于在 js 和实在 dom 两头加了一个缓存,利用 dom diff 算法防止了没有必要 的 dom 操作,从而进步性能
具体实现步骤如下:
- 用 JavaScript 对象构造示意 DOM 树的构造; 而后用这个树构建一个真正的 DOM 树,插到文档当中;
- 当状态变更的时候,从新结构一棵新的对象树。而后用新的树和旧的树进行比拟,记 录两棵树差别;
- 把 2 所记录的差别利用到步骤 1 所构建的真正的 DOM 树上,视图就更新了。
vue 或者 react 优化整体优化
- 虚构 dom
为什么虚构 dom 会进步性能?(必考)
虚构 dom 相当于在 js 和实在 dom 两头加了一个缓存,利用 dom diff 算法防止了没有必要的 dom 操作,从而进步性能。
用 JavaScript 对象构造示意 DOM 树的构造;而后用这个树构建一个真正的 DOM 树,插到文档当中当状态变更的时候,从新结构一棵新的对象树。而后用新的树和旧的树进行比拟,记录两棵树差别把 2 所记录的差别利用到步骤 1 所构建的真正的 DOM 树上,视图就更新了。
对 componentWillReceiveProps 的了解
该办法当 props
发生变化时执行,初始化 render
时不执行,在这个回调函数外面,你能够依据属性的变动,通过调用 this.setState()
来更新你的组件状态,旧的属性还是能够通过 this.props
来获取, 这里调用更新状态是平安的,并不会触发额定的 render
调用。
应用益处: 在这个生命周期中,能够在子组件的 render 函数执行前获取新的 props,从而更新子组件本人的 state。能够将数据申请放在这里进行执行,须要传的参数则从 componentWillReceiveProps(nextProps)中获取。而不用将所有的申请都放在父组件中。于是该申请只会在该组件渲染时才会收回,从而加重申请累赘。
componentWillReceiveProps 在初始化 render 的时候不会执行,它会在 Component 承受到新的状态 (Props) 时被触发,个别用于父组件状态更新时子组件的从新渲染。
参考 前端进阶面试题具体解答
hooks 父子传值
父传子
在父组件中用 useState 申明数据
const [data, setData] = useState(false)
把数据传递给子组件
<Child data={data} />
子组件接管
export default function (props) {const { data} = props
console.log(data)
}
子传父
子传父能够通过事件办法传值,和父传子有点相似。在父组件中用 useState 申明数据
const [data, setData] = useState(false)
把更新数据的函数传递给子组件
<Child setData={setData} />
子组件中触发函数更新数据,就会间接传递给父组件
export default function (props) {const { setData} = props
setData(true)
}
如果存在多个层级的数据传递,也可按照此办法顺次传递
// 多层级用 useContext
const User = () => {
// 间接获取,不必回调
const {user, setUser} = useContext(UserContext);
return <Avatar user={user} setUser={setUser} />;
};
React 组件中怎么做事件代理?它的原理是什么?
React 基于 Virtual DOM 实现了一个 SyntheticEvent 层(合成事件层),定义的事件处理器会接管到一个合成事件对象的实例,它合乎 W3C 规范,且与原生的浏览器事件领有同样的接口,反对冒泡机制,所有的事件都主动绑定在最外层上。
在 React 底层,次要对合成事件做了两件事:
- 事件委派: React 会把所有的事件绑定到构造的最外层,应用对立的事件监听器,这个事件监听器上维持了一个映射来保留所有组件外部事件监听和处理函数。
- 主动绑定: React 组件中,每个办法的上下文都会指向该组件的实例,即主动绑定 this 为以后组件。
react 性能优化是哪个周期函数
shouldComponentUpdate
这个办法用来判断是否须要调用 render 办法从新描述 dom。因为 dom 的描述十分耗费性能,如果咱们能在shouldComponentUpdate 方
法中可能写出更优化的dom diff
算法,能够极大的进步性能
如何通知 React 它应该编译生产环境版
通常状况下咱们会应用
Webpack
的DefinePlugin
办法来将NODE_ENV
变量值设置为production
。编译版本中React
会疏忽propType
验证以及其余的告警信息,同时还会升高代码库的大小,React
应用了Uglify
插件来移除生产环境下不必要的正文等信息
何为 redux
Redux 的根本思维是整个利用的 state 放弃在一个繁多的 store 中。store 就是一个简略的 javascript 对象,而扭转利用 state 的惟一形式是在利用中触发 actions,而后为这些 actions 编写 reducers 来批改 state。整个 state 转化是在 reducers 中实现,并且不应该有任何副作用。
这段代码有什么问题?
class App extends Component {constructor(props) {super(props);
this.state = {
username: "有课前端网",
msg: " ",
};
}
render() {return <div> {this.state.msg}</div>;
}
componentDidMount() {this.setState((oldState, props) => {
return {msg: oldState.username + "-" + props.intro,};
});
}
}
render (< App intro=” 前端技术业余学习平台 ”></App>,ickt)
在页面中失常输入“有课前端网 - 前端技术业余学习平台”。然而这种写法很少应用,并不是罕用的写法。React 容许对 setState 办法传递一个函数,它接管到先前的状态和属性数据并返回一个须要批改的状态对象,正如咱们在下面所做的那样。它岂但没有问题,而且如果依据以前的状态(state)以及属性来批改以后状态,举荐应用这种写法。
React setState 调用之后产生了什么?是同步还是异步?
(1)React 中 setState 后产生了什么
在代码中调用 setState 函数之后,React 会将传入的参数对象与组件以后的状态合并,而后触发和谐过程(Reconciliation)。通过和谐过程,React 会以绝对高效的形式依据新的状态构建 React 元素树并且着手从新渲染整个 UI 界面。
在 React 失去元素树之后,React 会主动计算出新的树与老树的节点差别,而后依据差别对界面进行最小化重渲染。在差别计算算法中,React 可能绝对准确地晓得哪些地位产生了扭转以及应该如何扭转,这就保障了按需更新,而不是全副从新渲染。
如果在短时间内频繁 setState。React 会将 state 的扭转压入栈中,在适合的机会,批量更新 state 和视图,达到进步性能的成果。
(2)setState 是同步还是异步的
如果所有 setState 是同步的,意味着每执行一次 setState 时(有可能一个同步代码中,屡次 setState),都从新 vnode diff + dom 批改,这对性能来说是极为不好的。如果是异步,则能够把一个同步代码中的多个 setState 合并成一次组件更新。所以默认是异步的,然而在一些状况下是同步的。
setState 并不是单纯同步 / 异步的,它的体现会因调用场景的不同而不同。在源码中,通过 isBatchingUpdates 来判断 setState 是先存进 state 队列还是间接更新,如果值为 true 则执行异步操作,为 false 则间接更新。
- 异步: 在 React 能够管制的中央,就为 true,比方在 React 生命周期事件和合成事件中,都会走合并操作,提早更新的策略。
- 同步: 在 React 无法控制的中央,比方原生事件,具体就是在 addEventListener、setTimeout、setInterval 等事件中,就只能同步更新。
个别认为,做异步设计是为了性能优化、缩小渲染次数:
setState
设计为异步,能够显著的晋升性能。如果每次调用setState
都进行一次更新,那么意味着render
函数会被频繁调用,界面从新渲染,这样效率是很低的;最好的方法应该是获取到多个更新,之后进行批量更新;- 如果同步更新了
state
,然而还没有执行render
函数,那么state
和props
不能放弃同步。state
和props
不能放弃一致性,会在开发中产生很多的问题;
应用状态要留神哪些事件?
要留神以下几点。
- 不要间接更新状态
- 状态更新可能是异步的
- 状态更新要合并。
- 数据从上向下流动
对 React-Intl 的了解,它的工作原理?
React-intl 是雅虎的语言国际化开源我的项目 FormatJS 的一部分,通过其提供的组件和 API 能够与 ReactJS 绑定。
React-intl 提供了两种应用办法,一种是援用 React 组件,另一种是间接调取 API,官网更加举荐在 React 我的项目中应用前者,只有在无奈应用 React 组件的中央,才应该调用框架提供的 API。它提供了一系列的 React 组件,包含数字格式化、字符串格式化、日期格式化等。
在 React-intl 中,能够配置不同的语言包,他的工作原理就是依据须要,在语言包之间进行切换。
diff 算法如何比拟?
- 只对同级比拟,跨层级的 dom 不会进行复用
- 不同类型节点生成的 dom 树不同,此时会间接销毁老节点及子孙节点,并新建节点
- 能够通过 key 来对元素 diff 的过程提供复用的线索
- 单节点 diff
- 单点 diff 有如下几种状况:
- key 和 type 雷同示意能够复用节点
- key 不同间接标记删除节点,而后新建节点
- key 雷同 type 不同,标记删除该节点和兄弟节点,而后新创建节点
在 Redux 中应用 Action 要留神哪些问题?
在 Redux 中应用 Action 的时候,Action 文件里尽量放弃 Action 文件的污浊,传入什么数据就返回什么数据,最妤把申请的数据和 Action 办法分来到,以放弃 Action 的污浊。
react 中的 Portal 是什么?
Portals 提供了一种很好的将子节点渲染到父组件以外的 DOM 节点的形式。
第一个参数(child)是任何可渲染的 React 子元素,例如一个元素,字符串或碎片。
第二个参数(container)则是一个 DOM 元素。
ReactDOM.createPortal(child, container)
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} />
}
}
constructor
答案是:在 constructor 函数外面,须要用到 props 的值的时候,就须要调用 super(props)
- class 语法糖默认会帮你定义一个 constructor,所以当你不须要应用 constructor 的时候,是能够不必本人定义的
- 当你本人定义一个 constructor 的时候,就肯定要写 super(),否则拿不到 this
- 当你在 constructor 外面想要应用 props 的值,就须要传入 props 这个参数给 super,调用 super(props),否则只须要写 super()