react和vue的区别
相同点:
- 数据驱动页面,提供响应式的试图组件
- 都有virtual DOM,组件化的开发,通过props参数进行父子之间组件传递数据,都实现了webComponents标准
- 数据流动单向,都反对服务器的渲染SSR
- 都有反对native的办法,react有React native, vue有wexx
不同点:
- 数据绑定:Vue实现了双向的数据绑定,react数据流动是单向的
- 数据渲染:大规模的数据渲染,react更快
- 应用场景:React配合Redux架构适宜大规模多人合作简单我的项目,Vue适宜小快的我的项目
- 开发格调:react举荐做法jsx + inline style把html和css都写在js了
vue是采纳webpack +vue-loader单文件组件格局,html, js, css同一个文件
对有状态组件和无状态组件的了解及应用场景
(1)有状态组件
特点:
- 是类组件
- 有继承
- 能够应用this
- 能够应用react的生命周期
- 应用较多,容易频繁触发生命周期钩子函数,影响性能
- 外部应用 state,保护本身状态的变动,有状态组件依据内部组件传入的 props 和本身的 state进行渲染。
应用场景:
- 须要应用到状态的。
- 须要应用状态操作组件的(无状态组件的也能够实现新版本react hooks也可实现)
总结: 类组件能够保护本身的状态变量,即组件的 state ,类组件还有不同的生命周期办法,能够让开发者可能在组件的不同阶段(挂载、更新、卸载),对组件做更多的管制。类组件则既能够充当无状态组件,也能够充当有状态组件。当一个类组件不须要治理本身状态时,也可称为无状态组件。
(2)无状态组件 特点:
- 不依赖本身的状态state
- 能够是类组件或者函数组件。
- 能够完全避免应用 this 关键字。(因为应用的是箭头函数事件无需绑定)
- 有更高的性能。当不须要应用生命周期钩子时,应该首先应用无状态函数组件
- 组件外部不保护 state ,只依据内部组件传入的 props 进行渲染的组件,当 props 扭转时,组件从新渲染。
应用场景:
- 组件不须要治理 state,纯展现
长处:
- 简化代码、专一于 render
- 组件不须要被实例化,无生命周期,晋升性能。 输入(渲染)只取决于输出(属性),无副作用
- 视图和数据的解耦拆散
毛病:
- 无奈应用 ref
- 无生命周期办法
- 无法控制组件的重渲染,因为无奈应用shouldComponentUpdate 办法,当组件承受到新的属性时则会重渲染
总结: 组件外部状态且与内部无关的组件,能够思考用状态组件,这样状态树就不会过于简单,易于了解和治理。当一个组件不须要治理本身状态时,也就是无状态组件,应该优先设计为函数组件。比方自定义的 <Button/>
、 <Input />
等组件。
对 Redux 的了解,次要解决什么问题
React是视图层框架。Redux是一个用来治理数据状态和UI状态的JavaScript利用工具。随着JavaScript单页利用(SPA)开发日趋简单, JavaScript须要治理比任何时候都要多的state(状态), Redux就是升高治理难度的。(Redux反对React、Angular、jQuery甚至纯JavaScript)。
在 React 中,UI 以组件的模式来搭建,组件之间能够嵌套组合。但 React 中组件间通信的数据流是单向的,顶层组件能够通过 props 属性向上层组件传递数据,而上层组件不能向下层组件传递数据,兄弟组件之间同样不能。这样简略的单向数据流撑持起了 React 中的数据可控性。
当我的项目越来越大的时候,治理数据的事件或回调函数将越来越多,也将越来越不好治理。治理一直变动的 state 十分艰难。如果一个 model 的变动会引起另一个 model 变动,那么当 view 变动时,就可能引起对应 model 以及另一个 model 的变动,顺次地,可能会引起另一个 view 的变动。直至你搞不清楚到底产生了什么。state 在什么时候,因为什么起因,如何变动未然不受管制。 当零碎变得盘根错节的时候,想重现问题或者增加新性能就会变得举步维艰。如果这还不够蹩脚,思考一些来自前端开发畛域的新需要,如更新调优、服务端渲染、路由跳转前申请数据等。state 的治理在大我的项目中相当简单。
Redux 提供了一个叫 store 的对立仓储库,组件通过 dispatch 将 state 间接传入store,不必通过其余的组件。并且组件通过 subscribe 从 store获取到 state 的扭转。应用了 Redux,所有的组件都能够从 store 中获取到所需的 state,他们也能从store 获取到 state 的扭转。这比组件之间相互传递数据清晰清朗的多。
次要解决的问题: 单纯的Redux只是一个状态机,是没有UI出现的,react- redux作用是将Redux的状态机和React的UI出现绑定在一起,当你dispatch action扭转state的时候,会自动更新页面。
如何解决 props 层级过深的问题
- 应用Context API:提供一种组件之间的状态共享,而不用通过显式组件树逐层传递props;
- 应用Redux等状态库。
参考:前端react面试题具体解答
React中什么是受控组件和非控组件?
(1)受控组件 在应用表单来收集用户输出时,例如<input><select><textearea>
等元素都要绑定一个change事件,当表单的状态发生变化,就会触发onChange事件,更新组件的state。这种组件在React中被称为受控组件,在受控组件中,组件渲染出的状态与它的value或checked属性绝对应,react通过这种形式打消了组件的部分状态,使整个状态可控。react官网举荐应用受控表单组件。
受控组件更新state的流程:
- 能够通过初始state中设置表单的默认值
- 每当表单的值发生变化时,调用onChange事件处理器
- 事件处理器通过事件对象e拿到扭转后的状态,并更新组件的state
- 一旦通过setState办法更新state,就会触发视图的从新渲染,实现表单组件的更新
受控组件缺点: 表单元素的值都是由React组件进行治理,当有多个输入框,或者多个这种组件时,如果想同时获取到全副的值就必须每个都要编写事件处理函数,这会让代码看着很臃肿,所以为了解决这种状况,呈现了非受控组件。
(2)非受控组件 如果一个表单组件没有value props(单选和复选按钮对应的是checked props)时,就能够称为非受控组件。在非受控组件中,能够应用一个ref来从DOM取得表单值。而不是为每个状态更新编写一个事件处理程序。
React官网的解释:
要编写一个非受控组件,而不是为每个状态更新都编写数据处理函数,你能够应用 ref来从 DOM 节点中获取表单数据。
因为非受控组件将实在数据贮存在 DOM 节点中,所以在应用非受控组件时,有时候反而更容易同时集成 React 和非 React 代码。如果你不介意代码好看性,并且心愿疾速编写代码,应用非受控组件往往能够缩小你的代码量。否则,你应该应用受控组件。
例如,上面的代码在非受控组件中接管单个属性:
class NameForm extends React.Component { constructor(props) { super(props); this.handleSubmit = this.handleSubmit.bind(this); } handleSubmit(event) { alert('A name was submitted: ' + this.input.value); event.preventDefault(); } render() { return ( <form onSubmit={this.handleSubmit}> <label> Name: <input type="text" ref={(input) => this.input = input} /> </label> <input type="submit" value="Submit" /> </form> ); }}
总结: 页面中所有输出类的DOM如果是现用现取的称为非受控组件,而通过setState将输出的值保护到了state中,须要时再从state中取出,这里的数据就受到了state的管制,称为受控组件。
React中有应用过getDefaultProps吗?它有什么作用?
通过实现组件的getDefaultProps,对属性设置默认值(ES5的写法):
var ShowTitle = React.createClass({ getDefaultProps:function(){ return{ title : "React" } }, render : function(){ return <h1>{this.props.title}</h1> }});
React如何获取组件对应的DOM元素?
能够用ref来获取某个子节点的实例,而后通过以后class组件实例的一些特定属性来间接获取子节点实例。ref有三种实现办法:
- 字符串格局:字符串格局,这是React16版本之前用得最多的,例如:
<p ref="info">span</p>
- 函数格局:ref对应一个办法,该办法有一个参数,也就是对应的节点实例,例如:
<p ref={ele => this.info = ele}></p>
- createRef办法:React 16提供的一个API,应用React.createRef()来实现
React Hook 的应用限度有哪些?
React Hooks 的限度次要有两条:
- 不要在循环、条件或嵌套函数中调用 Hook;
- 在 React 的函数组件中调用 Hook。
那为什么会有这样的限度呢?Hooks 的设计初衷是为了改良 React 组件的开发模式。在旧有的开发模式下遇到了三个问题。
- 组件之间难以复用状态逻辑。过来常见的解决方案是高阶组件、render props 及状态治理框架。
- 简单的组件变得难以了解。生命周期函数与业务逻辑耦合太深,导致关联局部难以拆分。
- 人和机器都很容易混同类。常见的有 this 的问题,但在 React 团队中还有类难以优化的问题,心愿在编译优化层面做出一些改良。
这三个问题在肯定水平上妨碍了 React 的后续倒退,所以为了解决这三个问题,Hooks 基于函数组件开始设计。然而第三个问题决定了 Hooks 只反对函数组件。
那为什么不要在循环、条件或嵌套函数中调用 Hook 呢?因为 Hooks 的设计是基于数组实现。在调用时按程序退出数组中,如果应用循环、条件或嵌套函数很有可能导致数组取值错位,执行谬误的 Hook。当然,本质上 React 的源码里不是数组,是链表。
这些限度会在编码上造成肯定水平的心智累赘,老手可能会写错,为了防止这样的状况,能够引入 ESLint 的 Hooks 查看插件进行预防。
React中的setState和replaceState的区别是什么?
(1)setState() setState()用于设置状态对象,其语法如下:
setState(object nextState[, function callback])
- nextState,将要设置的新状态,该状态会和以后的state合并
- callback,可选参数,回调函数。该函数会在setState设置胜利,且组件从新渲染后调用。
合并nextState和以后state,并从新渲染组件。setState是React事件处理函数中和申请回调函数中触发UI更新的次要办法。
(2)replaceState() replaceState()办法与setState()相似,然而办法只会保留nextState中状态,原state不在nextState中的状态都会被删除。其语法如下:
replaceState(object nextState[, function callback])
- nextState,将要设置的新状态,该状态会替换以后的state。
- callback,可选参数,回调函数。该函数会在replaceState设置胜利,且组件从新渲染后调用。
总结: setState 是批改其中的局部状态,相当于 Object.assign,只是笼罩,不会缩小原来的状态。而replaceState 是齐全替换原来的状态,相当于赋值,将原来的 state 替换为另一个对象,如果新状态属性缩小,那么 state 中就没有这个状态了。
React 废除了哪些生命周期?为什么?
被废除的三个函数都是在render之前,因为fber的呈现,很可能因为高优先级工作的呈现而打断现有工作导致它们会被执行屡次。另外的一个起因则是,React想束缚使用者,好的框架可能让人不得已写出容易保护和扩大的代码,这一点又是从何谈起,能够从新减少以及行将废除的生命周期剖析动手
1) componentWillMount
首先这个函数的性能齐全能够应用componentDidMount和 constructor来代替,异步获取的数据的状况下面曾经阐明了,而如果抛去异步获取数据,其余的即是初始化而已,这些性能都能够在constructor中执行,除此之外,如果在 willMount 中订阅事件,但在服务端这并不会执行 willUnMount事件,也就是说服务端会导致内存透露所以componentWilIMount齐全能够不应用,但使用者有时候不免因为各 种各样的状况在 componentWilMount中做一些操作,那么React为了束缚开发者,罗唆就抛掉了这个API
2) componentWillReceiveProps
在老版本的 React 中,如果组件本身的某个 state 跟其 props 密切相关的话,始终都没有一种很优雅的解决形式去更新 state,而是须要在 componentWilReceiveProps 中判断前后两个 props 是否雷同,如果不同再将新的 props更新到相应的 state 下来。这样做一来会毁坏 state 数据的繁多数据源,导致组件状态变得不可预测,另一方面也会减少组件的重绘次数。相似的业务需要也有很多,如一个能够横向滑动的列表,以后高亮的 Tab 显然隶属于列表本身的时,依据传入的某个值,间接定位到某个 Tab。为了解决这些问题,React引入了第一个新的生命周期:getDerivedStateFromProps。它有以下的长处∶
- getDSFP是静态方法,在这里不能应用this,也就是一个纯函数,开发者不能写出副作用的代码
- 开发者只能通过prevState而不是prevProps来做比照,保障了state和props之间的简略关系以及不须要解决第一次渲染时prevProps为空的状况
- 基于第一点,将状态变动(setState)和低廉操作(tabChange)辨别开,更加便于 render 和 commit 阶段操作或者说优化。
3) componentWillUpdate
与 componentWillReceiveProps 相似,许多开发者也会在 componentWillUpdate 中依据 props 的变动去触发一些回调 。 但不论是 componentWilReceiveProps 还 是 componentWilUpdate,都有可能在一次更新中被调用屡次,也就是说写在这里的回调函数也有可能会被调用屡次,这显然是不可取的。与 componentDidMount 类 似, componentDidUpdate 也不存在这样的问题,一次更新中 componentDidUpdate 只会被调用一次,所以将原先写在 componentWillUpdate 中 的 回 调 迁 移 至 componentDidUpdate 就能够解决这个问题。
另外一种状况则是须要获取DOM元素状态,然而因为在fber中,render可打断,可能在wilMount中获取到的元素状态很可能与理论须要的不同,这个通常能够应用第二个新增的生命函数的解决 getSnapshotBeforeUpdate(prevProps, prevState)
4) getSnapshotBeforeUpdate(prevProps, prevState)
返回的值作为componentDidUpdate的第三个参数。与willMount不同的是,getSnapshotBeforeUpdate会在最终确定的render执行之前执行,也就是能保障其获取到的元素状态与didUpdate中获取到的元素状态雷同。官网参考代码:
class ScrollingList extends React.Component { constructor(props) { super(props); this.listRef = React.createRef(); } getSnapshotBeforeUpdate(prevProps, prevState) { // 咱们是否在 list 中增加新的 items ? // 捕捉滚动地位以便咱们稍后调整滚动地位。 if (prevProps.list.length < this.props.list.length) { const list = this.listRef.current; return list.scrollHeight - list.scrollTop; } return null; } componentDidUpdate(prevProps, prevState, snapshot) { // 如果咱们 snapshot 有值,阐明咱们刚刚增加了新的 items, // 调整滚动地位使得这些新 items 不会将旧的 items 推出视图。 //(这里的 snapshot 是 getSnapshotBeforeUpdate 的返回值) if (snapshot !== null) { const list = this.listRef.current; list.scrollTop = list.scrollHeight - snapshot; } } render() { return ( <div ref={this.listRef}>{/* ...contents... */}</div> ); }}
Redux中的connect有什么作用
connect负责连贯React和Redux
(1)获取state
connect 通过 context获取 Provider 中的 store,通过 store.getState()
获取整个store tree 上所有state
(2)包装原组件
将state和action通过props的形式传入到原组件外部 wrapWithConnect 返回—个 ReactComponent 对 象 Connect,Connect 重 新 render 内部传入的原组件 WrappedComponent ,并把 connect 中传入的 mapStateToProps,mapDispatchToProps与组件上原有的 props合并后,通过属性的形式传给WrappedComponent
(3)监听store tree变动
connect缓存了store tree中state的状态,通过以后state状态 和变更前 state 状态进行比拟,从而确定是否调用 this.setState()
办法触发Connect及其子组件的从新渲染
React组件的构造函数有什么作用?它是必须的吗?
构造函数次要用于两个目标:
- 通过将对象调配给this.state来初始化本地状态
- 将事件处理程序办法绑定到实例上
所以,当在React class中须要设置state的初始值或者绑定事件时,须要加上构造函数,官网Demo:
class LikeButton extends React.Component { constructor() { super(); this.state = { liked: false }; this.handleClick = this.handleClick.bind(this); } handleClick() { this.setState({liked: !this.state.liked}); } render() { const text = this.state.liked ? 'liked' : 'haven\'t liked'; return ( <div onClick={this.handleClick}> You {text} this. Click to toggle. </div> ); }}ReactDOM.render( <LikeButton />, document.getElementById('example'));
构造函数用来新建父类的this对象;子类必须在constructor办法中调用super办法;否则新建实例时会报错;因为子类没有本人的this对象,而是继承父类的this对象,而后对其进行加工。如果不调用super办法;子类就得不到this对象。
留神:
- constructor () 必须配上 super(), 如果要在constructor 外部应用 this.props 就要 传入props , 否则不必
- JavaScript中的 bind 每次都会返回一个新的函数, 为了性能等思考, 尽量在constructor中绑定事件
对 React Hook 的了解,它的实现原理是什么
React-Hooks 是 React 团队在 React 组件开发实际中,逐步认知到的一个改良点,这背地其实波及对类组件和函数组件两种组件模式的思考和偏重。
(1)类组件: 所谓类组件,就是基于 ES6 Class 这种写法,通过继承 React.Component 得来的 React 组件。以下是一个类组件:
class DemoClass extends React.Component { state = { text: "" }; componentDidMount() { //... } changeText = (newText) => { this.setState({ text: newText }); }; render() { return ( <div className="demoClass"> <p>{this.state.text}</p> <button onClick={this.changeText}>批改</button> </div> ); }}
能够看出,React 类组件外部预置了相当多的“现成的货色”等着咱们去调度/定制,state 和生命周期就是这些“现成货色”中的典型。要想得到这些货色,难度也不大,只须要继承一个 React.Component 即可。
当然,这也是类组件的一个不便,它太繁冗了,对于解决许多问题来说,编写一个类组件切实是一个过于简单的姿态。简单的姿态必然带来昂扬的了解老本,这也是咱们所不想看到的。除此之外,因为开发者编写的逻辑在封装后是和组件粘在一起的,这就使得类组件外部的逻辑难以实现拆分和复用。
(2)函数组件:函数组件就是以函数的状态存在的 React 组件。晚期并没有 React-Hooks,函数组件外部无奈定义和保护 state,因而它还有一个别名叫“无状态组件”。以下是一个函数组件:
function DemoFunction(props) { const { text } = props return ( <div className="demoFunction"> <p>{`函数组件接管的内容:[${text}]`}</p> </div> );}
相比于类组件,函数组件肉眼可见的特质天然包含轻量、灵便、易于组织和保护、较低的学习老本等。
通过比照,从状态上能够对两种组件做辨别,它们之间的区别如下:
- 类组件须要继承 class,函数组件不须要;
- 类组件能够拜访生命周期办法,函数组件不能;
- 类组件中能够获取到实例化后的 this,并基于这个 this 做各种各样的事件,而函数组件不能够;
- 类组件中能够定义并保护 state(状态),而函数组件不能够;
除此之外,还有一些其余的不同。通过下面的区别,咱们不能说谁好谁坏,它们各有本人的劣势。在 React-Hooks 呈现之前,类组件的能力边界显著强于函数组件。
实际上,类组件和函数组件之间,是面向对象和函数式编程这两套不同的设计思维之间的差别。而函数组件更加符合 React 框架的设计理念: React 组件自身的定位就是函数,一个输出数据、输入 UI 的函数。作为开发者,咱们编写的是申明式的代码,而 React 框架的次要工作,就是及时地把申明式的代码转换为命令式的 DOM 操作,把数据层面的形容映射到用户可见的 UI 变动中去。这就意味着从原则上来讲,React 的数据应该总是紧紧地和渲染绑定在一起的,而类组件做不到这一点。函数组件就真正地将数据和渲染绑定到了一起。函数组件是一个更加匹配其设计理念、也更有利于逻辑拆分与重用的组件表达形式。
为了能让开发者更好的的去编写函数式组件。于是,React-Hooks 便应运而生。
React-Hooks 是一套可能使函数组件更弱小、更灵便的“钩子”。
函数组件比起类组件少了很多货色,比方生命周期、对 state 的治理等。这就给函数组件的应用带来了十分多的局限性,导致咱们并不能应用函数这种模式,写出一个真正的全功能的组件。而React-Hooks 的呈现,就是为了帮忙函数组件补齐这些(绝对于类组件来说)缺失的能力。
如果说函数组件是一台笨重的快艇,那么 React-Hooks 就是一个内容丰盛的零部件箱。“重装战舰”所预置的那些设施,这个箱子里根本全都有,同时它还不强制你全都要,而是容许你自在地抉择和应用你须要的那些能力,而后将这些能力以 Hook(钩子)的模式“钩”进你的组件里,从而定制出一个最适宜你的“专属战舰”。
diff算法如何比拟?
- 只对同级比拟,跨层级的dom不会进行复用
- 不同类型节点生成的dom树不同,此时会间接销毁老节点及子孙节点,并新建节点
- 能够通过key来对元素diff的过程提供复用的线索
- 单节点diff
- 单点diff有如下几种状况:
- key和type雷同示意能够复用节点
- key不同间接标记删除节点,而后新建节点
- key雷同type不同,标记删除该节点和兄弟节点,而后新创建节点
类组件(Class component)和函数式组件(Functional component)之间有何不同
- 类组件不仅容许你应用更多额定的性能,如组件本身的状态和生命周期钩子,也能使组件间接拜访
store
并维持状态 - 当组件仅是接管
props
,并将组件本身渲染到页面时,该组件就是一个 '无状态组件(stateless component)',能够应用一个纯函数来创立这样的组件。这种组件也被称为哑组件(dumb components)或展现组件
React的严格模式如何应用,有什么用途?
StrictMode
是一个用来突出显示应用程序中潜在问题的工具。与 Fragment
一样,StrictMode
不会渲染任何可见的 UI。它为其后辈元素触发额定的检查和正告。
能够为应用程序的任何局部启用严格模式。例如:
import React from 'react';function ExampleApplication() { return ( <div> <Header /> <React.StrictMode> <div> <ComponentOne /> <ComponentTwo /> </div> </React.StrictMode> <Footer /> </div> );}
在上述的示例中,不会对 Header
和 Footer
组件运行严格模式查看。然而,ComponentOne
和 ComponentTwo
以及它们的所有后辈元素都将进行查看。
StrictMode
目前有助于:
- 辨认不平安的生命周期
- 对于应用过期字符串 ref API 的正告
- 对于应用废除的 findDOMNode 办法的正告
- 检测意外的副作用
- 检测过期的 context API
何为 Children
在JSX表达式中,一个开始标签(比方<a>
)和一个敞开标签(比方</a>
)之间的内容会作为一个非凡的属性props.children
被主动传递给蕴含着它的组件。
这个属性有许多可用的办法,包含 React.Children.map
,React.Children.forEach
, React.Children.count
, React.Children.only
,React.Children.toArray
。
setState 是同步异步?为什么?实现原理?
1. setState是同步执行的
setState是同步执行的,然而state并不一定会同步更新
2. setState在React生命周期和合成事件中批量笼罩执行
在React的生命周期钩子和合成事件中,屡次执行setState,会批量执行
具体表现为,屡次同步执行的setState,会进行合并,相似于Object.assign,雷同的key,前面的会笼罩后面的
当遇到多个setState调用时候,会提取单次传递setState的对象,把他们合并在一起造成一个新的
繁多对象,并用这个繁多的对象去做setState的事件,就像Object.assign的对象合并,后一个
key值会笼罩后面的key值
通过React 解决的事件是不会同步更新 this.state的. 通过 addEventListener || setTimeout/setInterval 的形式解决的则会同步更新。
为了合并setState,咱们须要一个队列来保留每次setState的数据,而后在一段时间后执行合并操作和更新state,并清空这个队列,而后渲染组件。
Redux 中间件是怎么拿到store 和 action? 而后怎么解决?
redux中间件实质就是一个函数柯里化。redux applyMiddleware Api 源码中每个middleware 承受2个参数, Store 的getState 函数和dispatch 函数,别离取得store和action,最终返回一个函数。该函数会被传入 next 的下一个 middleware 的 dispatch 办法,并返回一个接管 action 的新函数,这个函数能够间接调用 next(action),或者在其余须要的时刻调用,甚至基本不去调用它。调用链中最初一个 middleware 会承受实在的 store的 dispatch 办法作为 next 参数,并借此完结调用链。所以,middleware 的函数签名是({ getState,dispatch })=> next => action。
在 Redux 中,何为 store
Store 是一个 javascript 对象,它保留了整个利用的 state。与此同时,Store 也承当以下职责:
- 容许通过
getState()
拜访 state - 运行通过
dispatch(action)
扭转 state - 通过
subscribe(listener)
注册 listeners - 通过
subscribe(listener)
返回的函数解决 listeners 的登记