react有什么特点
- react应用过的虚构DOM,而不是实在DOM
- react能够用服务器渲染
- react遵循单向数据流 或者数据绑定
React 数据长久化有什么实际吗?
封装数据长久化组件:
let storage={ // 减少 set(key, value){ localStorage.setItem(key, JSON.stringify(value)); }, // 获取 get(key){ return JSON.parse(localStorage.getItem(key)); }, // 删除 remove(key){ localStorage.removeItem(key); }};export default Storage;
在React我的项目中,通过redux存储全局数据时,会有一个问题,如果用户刷新了网页,那么通过redux存储的全局数据就会被全副清空,比方登录信息等。这时就会有全局数据长久化存储的需要。首先想到的就是localStorage,localStorage是没有工夫限度的数据存储,能够通过它来实现数据的长久化存储。
然而在曾经应用redux来治理和存储全局数据的根底上,再去应用localStorage来读写数据,这样不仅是工作量微小,还容易出错。那么有没有联合redux来达到持久数据存储性能的框架呢?当然,它就是redux-persist。redux-persist会将redux的store中的数据缓存到浏览器的localStorage中。其应用步骤如下:
(1)首先要装置redux-persist:
npm i redux-persist
(2)对于reducer和action的解决不变,只需批改store的生成代码,批改如下:
import {createStore} from 'redux'import reducers from '../reducers/index'import {persistStore, persistReducer} from 'redux-persist';import storage from 'redux-persist/lib/storage';import autoMergeLevel2 from 'redux-persist/lib/stateReconciler/autoMergeLevel2';const persistConfig = { key: 'root', storage: storage, stateReconciler: autoMergeLevel2 // 查看 'Merge Process' 局部的具体情况};const myPersistReducer = persistReducer(persistConfig, reducers)const store = createStore(myPersistReducer)export const persistor = persistStore(store)export default store
(3)在index.js中,将PersistGate标签作为网页内容的父标签:
import React from 'react';import ReactDOM from 'react-dom';import {Provider} from 'react-redux'import store from './redux/store/store'import {persistor} from './redux/store/store'import {PersistGate} from 'redux-persist/lib/integration/react';ReactDOM.render(<Provider store={store}> <PersistGate loading={null} persistor={persistor}> {/*网页内容*/} </PersistGate> </Provider>, document.getElementById('root'));
这就实现了通过redux-persist实现React长久化本地数据存储的简略利用。
React 生命周期函数
挂载阶段
挂载阶段也能够了解为初始化阶段,也就是把咱们的组件插入到 DOM 中。
constructor
getDerivedStateFromProps
~~UNSAFE_componentWillMount~~
render
(React Updates DOM and refs)
componentDidMount
- constructor
组件的构造函数,第一个被执行。显式定义构造函数时,须要在第一行执行 super(props)
,否则不能再构造函数中拿到 this
。
在构造函数中,咱们个别会做两件事:
- 初始化 state
- 对自定义办法进行 this 绑定
- getDerivedStateFromProps
是一个动态函数,所以不能在这里应用 this,也表明了 React 官网不心愿调用方滥用这个生命周期函数。每当父组件引发以后组件的渲染过程时,getDerivedStateFromProps 都会被调用,这样咱们有机会依据新的 props 和以后的 state 来调整一个新的 state。
这个函数会在收到新的 props,调用了 setState 或 forceUpdate 时被调用。
- render
React 最外围的办法,class 组件中必须实现的办法。
当 render 被调用时,它会查看 this.props
和 this.state
的变动并返回一下类型之一:
- 原生的 DOM,如 div
- React 组件
- 数组或 Fragment
- Portals(传送门)
- 字符串或数字,被渲染成文本节点
- 布尔值或 null,不会渲染任何货色
- componentDidMount
在组件挂载之后立刻调用。依赖于 DOM 节点的初始化应该放在这里。如需通过网络申请获取数据,此处是实例化申请的好中央。这个办法比拟适宜增加订阅的中央,如果增加了订阅,请记得在卸载的时候勾销订阅。
你能够在 componentDidMount 外面间接调用 setState,它将触发额定渲染,但此渲染会产生在浏览器更新屏幕之前,如此保障了即便 render 了两次,用户也不会看到中间状态。
更新阶段
更新阶段是指当组件的 props 产生了扭转,或者组件外部调用了 setState 或者产生了 forceUpdate,这个阶段的过程包含:
UNSAFE_componentWillReceiveProps
getDerivedStateFromProps
sholdComponentUpdate
UNSAFE_componentWIllUpdate
render
getSnapshotBeforeUpdate
(React Updates DOM and refs)
componentDidUpdate
- shouldComponentUpdate
它有两个参数,依据此函数的返回值来判断是否从新进行渲染,首次渲染或者是当咱们调用了 forceUpdate 时并不会触发此办法,此办法仅用于性能优化。
然而官网提倡咱们应用内置的 PureComponent 而不是本人编写 shouldComponentUpdate。
- getSnapshotBeforeUpdate
这个生命周期函数产生在 render 之后,在更新之前,给了一个机会去获取 DOM 信息,计算失去并返回一个 snapshot,这个 snapshot 会作为 componentDidUpdate 第三个参数传入。
- componentDidUpdate
这个函数会在更新后被立刻调用,首次渲染不会执行此办法。在这个函数中咱们能够操作 DOM,能够发动申请,还能够 setState,但留神肯定要用条件语句,否则会导致有限循环。
卸载阶段
- componentWillUnmount
这个生命周期函数会在组件卸载销毁之前被调用,咱们能够在这里执行一些革除操作。不要在这里调用 setState,因为组件不会从新渲染。
对 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的时候,会自动更新页面。
redux有什么毛病
- 一个组件所须要的数据,必须由父组件传过来,而不能像
flux
中间接从store
取。 - 当一个组件相干数据更新时,即便父组件不须要用到这个组件,父组件还是会从新
render
,可能会有效率影响,或者须要写简单的shouldComponentUpdate
进行判断。
如何用 React构建( build)生产模式?
通常,应用 Webpack的 DefinePlugin办法将 NODE ENV设置为 production。这将剥离 propType验证和额定的正告。除此之外,还能够缩小代码,因为 React应用 Uglify的dead-code来打消开发代码和正文,这将大大减少包占用的空间。
setState办法的第二个参数有什么用?应用它的目标是什么?
它是一个回调函数,当 setState办法执行完结并从新渲染该组件时调用它。在工作中,更好的形式是应用 React组件生命周期之——“存在期”的生命周期办法,而不是依赖这个回调函数。
export class App extends Component { constructor(props) { super(props); this.state = { username: "雨夜清荷", }; } render() { return <div> {this.state.username}</div>; } componentDidMount() { this.setstate( { username: "有课前端网", }, () => console.log("re-rendered success. ") ); }}
在 Redux中应用 Action要留神哪些问题?
在Redux中应用 Action的时候, Action文件里尽量放弃 Action文件的污浊,传入什么数据就返回什么数据,最妤把申请的数据和 Action办法分来到,以放弃 Action的污浊。
react组件的划分业务组件技术组件?
- 依据组件的职责通常把组件分为UI组件和容器组件。
- UI 组件负责 UI 的出现,容器组件负责管理数据和逻辑。
- 两者通过
React-Redux
提供connect
办法分割起来
参考:前端react面试题具体解答
传入 setstate函数的第二个参数的作用是什么?
第二个参数是一个函数,该函数会在 setState函数调用实现并且组件开始重渲染时调用,能够用该函数来监听渲染是否实现。
this.setstate( { username: "有课前端网", }, () => console.log("re-rendered success. "));
React如何判断什么时候从新渲染组件?
组件状态的扭转能够因为props
的扭转,或者间接通过setState
办法扭转。组件取得新的状态,而后React决定是否应该从新渲染组件。只有组件的state发生变化,React就会对组件进行从新渲染。这是因为React中的shouldComponentUpdate
办法默认返回true
,这就是导致每次更新都从新渲染的起因。
当React将要渲染组件时会执行shouldComponentUpdate
办法来看它是否返回true
(组件应该更新,也就是从新渲染)。所以须要重写shouldComponentUpdate
办法让它依据状况返回true
或者false
来通知React什么时候从新渲染什么时候跳过从新渲染。
React的Fiber工作原理,解决了什么问题
- React Fiber 是一种基于浏览器的单线程调度算法。
React Fiber 用相似 requestIdleCallback 的机制来做异步 diff。然而之前数据结构不反对这样的实现异步 diff,于是 React 实现了一个相似链表的数据结构,将原来的 递归diff 变成了当初的 遍历diff,这样就能做到异步可更新了
react-router里的<Link>
标签和<a>
标签有什么区别
比照<a>
,Link
组件防止了不必要的重渲染
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有什么坑点?
1. JSX做表达式判断时候,须要强转为boolean类型
如果不应用!!b
进行强转数据类型,会在页面外面输入0
。
render() { const b = 0; return <div> { !!b && <div>这是一段文本</div> } </div>}
2. 尽量不要在 componentWillReviceProps
里应用 setState,如果肯定要应用,那么须要判断完结条件,不然会呈现有限重渲染,导致页面解体
3. 给组件增加ref时候,尽量不要应用匿名函数,因为当组件更新的时候,匿名函数会被当做新的prop解决,让ref属性承受到新函数的时候,react外部会先清空ref,也就是会以null为回调参数先执行一次ref这个props,而后在以该组件的实例执行一次ref,所以用匿名函数做ref的时候,有的时候去ref赋值后的属性会取到null
4. 遍历子节点的时候,不要用 index 作为组件的 key 进行传入
如何有条件地向 React 组件增加属性?
对于某些属性,React 十分聪慧,如果传递给它的值是虚值,能够省略该属性。例如:
var InputComponent = React.createClass({ render: function () { var required = true; var disabled = false; return <input type="text" disabled={disabled} required={required} />; },});
渲染后果:
<input type="text" required>
另一种可能的办法是:
var condition = true;var component = <div value="foo" {...(condition && { disabled: true })} />;
HOC相比 mixins 有什么长处?
HOC 和 Vue 中的 mixins 作用是统一的,并且在晚期 React 也是应用 mixins 的形式。然而在应用 class 的形式创立组件当前,mixins 的形式就不能应用了,并且其实 mixins 也是存在一些问题的,比方:
- 隐含了一些依赖,比方我在组件中写了某个
state
并且在mixin
中应用了,就这存在了一个依赖关系。万一下次他人要移除它,就得去mixin
中查找依赖 - 多个
mixin
中可能存在雷同命名的函数,同时代码组件中也不能呈现雷同命名的函数,否则就是重写了,其实我始终感觉命名真的是一件麻烦事。。 - 雪球效应,尽管我一个组件还是应用着同一个
mixin
,然而一个mixin
会被多个组件应用,可能会存在需要使得mixin
批改本来的函数或者新增更多的函数,这样可能就会产生一个保护老本
HOC 解决了这些问题,并且它们达成的成果也是统一的,同时也更加的政治正确(毕竟更加函数式了)。
当调用setState
时,React render
是如何工作的?
咱们能够将"render
"分为两个步骤:
- 虚构 DOM 渲染:当
render
办法被调用时,它返回一个新的组件的虚构 DOM 构造。当调用setState()
时,render
会被再次调用,因为默认状况下shouldComponentUpdate
总是返回true
,所以默认状况下 React 是没有优化的。 - 原生 DOM 渲染:React 只会在虚构DOM中批改实在DOM节点,而且批改的次数非常少——这是很棒的React个性,它优化了实在DOM的变动,使React变得更快。
React-Router 4的Switch有什么用?
Switch 通常被用来包裹 Route,用于渲染与门路匹配的第一个子 <Route>
或 <Redirect>
,它外面不能放其余元素。
如果不加 <Switch>
:
import { Route } from 'react-router-dom'<Route path="/" component={Home}></Route><Route path="/login" component={Login}></Route>
Route 组件的 path 属性用于匹配门路,因为须要匹配 /
到 Home
,匹配 /login
到 Login
,所以须要两个 Route,然而不能这么写。这样写的话,当 URL 的 path 为 “/login” 时,<Route path="/" />
和<Route path="/login" />
都会被匹配,因而页面会展现 Home 和 Login 两个组件。这时就须要借助 <Switch>
来做到只显示一个匹配组件:
import { Switch, Route} from 'react-router-dom'<Switch> <Route path="/" component={Home}></Route> <Route path="/login" component={Login}></Route></Switch>
此时,再拜访 “/login” 门路时,却只显示了 Home 组件。这是就用到了exact属性,它的作用就是准确匹配门路,常常与<Switch>
联结应用。只有当 URL 和该 <Route>
的 path 属性完全一致的状况下能力匹配上:
import { Switch, Route} from 'react-router-dom'<Switch> <Route exact path="/" component={Home}></Route> <Route exact path="/login" component={Login}></Route></Switch>
react router
import React from 'react'import { render } from 'react-dom'import { browserHistory, Router, Route, IndexRoute } from 'react-router'import App from '../components/App'import Home from '../components/Home'import About from '../components/About'import Features from '../components/Features'render( <Router history={browserHistory}> // history 路由 <Route path='/' component={App}> <IndexRoute component={Home} /> <Route path='about' component={About} /> <Route path='features' component={Features} /> </Route> </Router>, document.getElementById('app'))render( <Router history={browserHistory} routes={routes} />, document.getElementById('app'))
React Router 提供一个routerWillLeave生命周期钩子,这使得 React组件能够拦挡正在产生的跳转,或在来到route前提醒用户。routerWillLeave返回值有以下两种:
return
false
勾销此次跳转return
返回提示信息,在来到 route 前提醒用户进行确认。