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 时被调用。

  1. render

React 最外围的办法,class 组件中必须实现的办法。

当 render 被调用时,它会查看 this.propsthis.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。

  1. getSnapshotBeforeUpdate

这个生命周期函数产生在 render 之后,在更新之前,给了一个机会去获取 DOM 信息,计算失去并返回一个 snapshot,这个 snapshot 会作为 componentDidUpdate 第三个参数传入。

  1. componentDidUpdate

这个函数会在更新后被立刻调用,首次渲染不会执行此办法。在这个函数中咱们能够操作 DOM,能够发动申请,还能够 setState,但留神肯定要用条件语句,否则会导致有限循环。

卸载阶段

  1. 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"分为两个步骤:

  1. 虚构 DOM 渲染:当render办法被调用时,它返回一个新的组件的虚构 DOM 构造。当调用setState()时,render会被再次调用,因为默认状况下shouldComponentUpdate总是返回true,所以默认状况下 React 是没有优化的。
  2. 原生 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,匹配 /loginLogin,所以须要两个 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 前提醒用户进行确认。