关于react.js:前端一面高频react面试题持续更新中

34次阅读

共计 6425 个字符,预计需要花费 17 分钟才能阅读完成。

如何防止组件的从新渲染?

React 中最常见的问题之一是组件不必要地从新渲染。React 提供了两个办法,在这些状况下十分有用:

  • React.memo(): 这能够避免不必要地从新渲染函数组件
  • PureComponent: 这能够避免不必要地从新渲染类组件
    这两种办法都依赖于对传递给组件的 props 的浅比拟,如果 props 没有扭转,那么组件将不会从新渲染。尽管这两种工具都十分有用,然而浅比拟会带来额定的性能损失,因而如果使用不当,这两种办法都会对性能产生负面影响。
    通过应用 React Profiler,能够在应用这些办法前后对性能进行测量,从而确保通过进行给定的更改来理论改良性能。

React 性能优化

  • shouldCompoentUpdate
  • pureComponent 自带 shouldCompoentUpdate 的浅比拟优化
  • 联合 Immutable.js 达到最优

说说你用 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 中 refs 的作用是什么

  • RefsReact 提供给咱们的平安拜访 DOM元素或者某个组件实例的句柄
  • 能够为元素增加 ref 属性而后在回调函数中承受该元素在 DOM 树中的句柄,该值会作为回调函数的第一个参数返回

在 Reducer 文件里,对于返回的后果,要留神哪些问题?

在 Reducer 文件里,对于返回的后果,必须要应用 Object.assign ()来复制一份新的 state,否则页面不会跟着数据刷新。

return Object.assign({}, state, {
  type: action.type,
  shouldNotPaint: true,
});

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.")
    );
  }
}

参考:前端 react 面试题具体解答

shouldComponentUpdate 有什么用?为什么它很重要?

组件状态数据或者属性数据产生更新的时候,组件会进入存在期,视图会渲染更新。在生命周期办法 should ComponentUpdate 中,容许抉择退出某些组件(和它们的子组件)的和解过程。
和解的最终目标是依据新的状态,以最无效的形式更新用户界面。如果咱们晓得用户界面的某一部分不会扭转,那么没有理由让 React 弄清楚它是否应该更新渲染。通过在 shouldComponentUpdate 办法中返回 false, React 将让以后组件及其所有子组件放弃与以后组件状态雷同。

传入 setstate 函数的第二个参数的作用是什么?

第二个参数是一个函数,该函数会在 setState 函数调用实现并且组件开始重渲染时调用,能够用该函数来监听渲染是否实现。

this.setstate(
  {username: "有课前端网",},
  () => console.log("re-rendered success.")
);

setState 是同步的还是异步的

有时体现出同步,有时体现出异步

  1. setState 只有在 React 本身的合成事件和钩子函数中是异步的,在原生事件和 setTimeout 中都是同步的
  2. setState 的异步并不是说外部由异步代码实现,其实自身执行的过程和代码都是同步的,只是合成事件和钩子函数中没法立马拿到更新后的值,造成了所谓的异步。当然能够通过 setState 的第二个参数中的 callback 拿到更新后的后果
  3. setState 的批量更新优化也是建设在异步(合成事件、钩子函数)之上的,在原生事件和 setTimeout 中不会批量更新,在异步中如果对同一个值进行屡次 setState,setState 的批量更新策略会对其进行笼罩,去最初一次的执行,如果是同时 setState 多个不同的值,在更新时会对其进行合并批量更新
  4. 合成事件中是异步
  5. 钩子函数中的是异步
  6. 原生事件中是同步
  7. setTimeout 中是同步

说说 React 组件开发中对于作用域的常见问题。

在 EMAScript5 语法标准中,对于作用域的常见问题如下。
(1)在 map 等办法的回调函数中,要绑定作用域 this(通过 bind 办法)。
(2)父组件传递给子组件办法的作用域是父组件实例化对象,无奈扭转。
(3)组件事件回调函数办法的作用域是组件实例化对象(绑定父组件提供的办法就是父组件实例化对象),无奈扭转。
在 EMAScript6 语法标准中,对于作用域的常见问题如下。
(1)当应用箭头函数作为 map 等办法的回调函数时,箭头函数的作用域是以后组件的实例化对象(即箭头函数的作用域是定义时的作用域),毋庸绑定作用域。
(2)事件回调函数要绑定组件作用域。
(3)父组件传递办法要绑定父组件作用域。
总之,在 EMAScript6 语法标准中,组件办法的作用域是能够扭转的。

概述一下 React 中的事件处理逻辑。

为了解决跨浏览器兼容性问题,React 会将浏览器原生事件(Browser Native Event)封装为合成事件(Synthetic Event)并传入设置的事件处理程序中。
这里的合成事件提供了与原生事件雷同的接口,不过它们屏蔽了底层浏览器的细节差别,保障了行为的一致性。另外,React 并没有间接将事件附着到子元素上,而是以繁多事件监听器的形式将所有的事件发送到顶层进行解决(基于事件委托原理)。
这样 React 在更新 DOM 时就不须要思考如何解决附着在 DOM 上的事件监听器,最终达到优化性能的目标。

redux 中间件

中间件提供第三方插件的模式,自定义拦挡 action -> reducer 的过程。变为 action -> middlewares -> reducer。这种机制能够让咱们扭转数据流,实现如异步actionaction 过滤,日志输入,异样报告等性能

  • redux-logger:提供日志输入
  • redux-thunk:解决异步操作
  • redux-promise:解决异步操作,actionCreator的返回值是promise

为什么虚构 dom 会进步性能

虚构 dom 相当于在 js 和实在 dom 两头加了一个缓存,利用 dom diff 算法防止了没有必要的 dom 操作,从而进步性能

具体实现步骤如下

  • JavaScript 对象构造示意 DOM 树的构造;而后用这个树构建一个真正的 DOM 树,插到文档当中
  • 当状态变更的时候,从新结构一棵新的对象树。而后用新的树和旧的树进行比拟,记录两棵树差别
  • 把 2 所记录的差别利用到步骤 1 所构建的真正的 DOM 树上,视图就更新

虚构 DOM 肯定会进步性能吗?

很多人认为虚构 DOM 肯定会进步性能,肯定会更快,其实这个说法有点全面,因为虚构 DOM 尽管会缩小 DOM 操作,但也无奈防止 DOM 操作

  • 它的劣势是在于 diff 算法和批量解决策略, 将所有的 DOM 操作收集起来,一次性去扭转实在的 DOM, 但在首次渲染上,虚构 DOM 会多了一层计算,耗费一些性能,所以有可能会比 html 渲染的要慢
  • 留神,虚构 DOM 实际上是给咱们找了一条最短,最近的门路,并不是说比 DOM 操作的更快,而是门路最简略

在 ReactNative 中,如何解决 8081 端口号被占用而提醒无法访问的问题?

在运行 react-native start 时增加参数 port 8082;在 package.json 中批改“scripts”中的参数,增加端口号;批改我的项目下的 node\_modules \react-native\local- cli\server\server.js 文件配置中的 default 端口值。

组件更新有几种办法

  • this.setState() 批改状态的时候 会更新组件
  • this.forceUpdate() 强制更新
  • 组件件 render 之后,子组件应用到父组件中状态,导致子组件的 props 属性产生扭转的时候 也会触发子组件的更新

当渲染一个列表时,何为 key?设置 key 的目标是什么

Keys 会有助于 React 辨认哪些 items 扭转了,被增加了或者被移除了。Keys 应该被赋予数组内的元素以赋予 (DOM) 元素一个稳固的标识,抉择一个 key 的最佳办法是应用一个字符串,该字符串能惟一地标识一个列表项。很多时候你会应用数据中的 IDs 作为 keys,当你没有稳固的 IDs 用于被渲染的 items 时,能够应用我的项目索引作为渲染项的 key,但这种形式并不举荐,如果 items 能够从新排序,就会导致 re-render 变慢。

React 高阶组件、Render props、hooks 有什么区别,为什么要一直迭代

这三者是目前 react 解决代码复用的次要形式:

  • 高阶组件(HOC)是 React 中用于复用组件逻辑的一种高级技巧。HOC 本身不是 React API 的一部分,它是一种基于 React 的组合个性而造成的设计模式。具体而言,高阶组件是参数为组件,返回值为新组件的函数。
  • render props 是指一种在 React 组件之间应用一个值为函数的 prop 共享代码的简略技术,更具体的说,render prop 是一个用于告知组件须要渲染什么内容的函数 prop。
  • 通常,render props 和高阶组件只渲染一个子节点。让 Hook 来服务这个应用场景更加简略。这两种模式仍有用武之地,(例如,一个虚构滚动条组件或者会有一个 renderltem 属性,或是一个可见的容器组件或者会有它本人的 DOM 构造)。但在大部分场景下,Hook 足够了,并且可能帮忙缩小嵌套。

(1)HOC 官网解释∶

高阶组件(HOC)是 React 中用于复用组件逻辑的一种高级技巧。HOC 本身不是 React API 的一部分,它是一种基于 React 的组合个性而造成的设计模式。

简言之,HOC 是一种组件的设计模式,HOC 承受一个组件和额定的参数(如果须要),返回一个新的组件。HOC 是纯函数,没有副作用。

// hoc 的定义
function withSubscription(WrappedComponent, selectData) {
  return class extends React.Component {constructor(props) {super(props);
      this.state = {data: selectData(DataSource, props)
      };
    }
    // 一些通用的逻辑解决
    render() {
      // ... 并应用新数据渲染被包装的组件!
      return <WrappedComponent data={this.state.data} {...this.props} />;
    }
  };

// 应用
const BlogPostWithSubscription = withSubscription(BlogPost,
  (DataSource, props) => DataSource.getBlogPost(props.id));

HOC 的优缺点∶

  • 长处∶ 逻辑服用、不影响被包裹组件的外部逻辑。
  • 毛病∶ hoc 传递给被包裹组件的 props 容易和被包裹后的组件重名,进而被笼罩

(2)Render props 官网解释∶

“render prop” 是指一种在 React 组件之间应用一个值为函数的 prop 共享代码的简略技术

具备 render prop 的组件承受一个返回 React 元素的函数,将 render 的渲染逻辑注入到组件外部。在这里,”render” 的命名能够是任何其余无效的标识符。

// DataProvider 组件外部的渲染逻辑如下
class DataProvider extends React.Components {
     state = {name: 'Tom'}

    render() {
    return (
        <div>
          <p> 共享数据组件本人外部的渲染逻辑 </p>
          {this.props.render(this.state) }      </div>
    );
  }
}

// 调用形式
<DataProvider render={data => (<h1>Hello {data.name}</h1>
)}/>

由此能够看到,render props 的优缺点也很显著∶

  • 长处:数据共享、代码复用,将组件内的 state 作为 props 传递给调用者,将渲染逻辑交给调用者。
  • 毛病:无奈在 return 语句外拜访数据、嵌套写法不够优雅

(3)Hooks 官网解释∶

Hook 是 React 16.8 的新增个性。它能够让你在不编写 class 的状况下应用 state 以及其余的 React 个性。通过自定义 hook,能够复用代码逻辑。

// 自定义一个获取订阅数据的 hook
function useSubscription() {const data = DataSource.getComments();
  return [data];
}
// 
function CommentList(props) {const {data} = props;
  const [subData] = useSubscription();
    ...
}
// 应用
<CommentList data='hello' />

以上能够看出,hook 解决了 hoc 的 prop 笼罩的问题,同时应用的形式解决了 render props 的嵌套天堂的问题。hook 的长处如下∶

  • 应用直观;
  • 解决 hoc 的 prop 重名问题;
  • 解决 render props 因共享数据 而呈现嵌套天堂的问题;
  • 能在 return 之外应用数据的问题。

须要留神的是:hook 只能在组件顶层应用,不可在分支语句中应用。、

vue 或者 react 优化整体优化

  1. 虚构 dom

为什么虚构 dom 会进步性能?(必考)

虚构 dom 相当于在 js 和实在 dom 两头加了一个缓存,利用 dom diff 算法防止了没有必要的 dom 操作,从而进步性能。

用 JavaScript 对象构造示意 DOM 树的构造;而后用这个树构建一个真正的 DOM 树,插到文档当中当状态变更的时候,从新结构一棵新的对象树。而后用新的树和旧的树进行比拟,记录两棵树差别把 2 所记录的差别利用到步骤 1 所构建的真正的 DOM 树上,视图就更新了。

如何通知 React 它应该编译生产环境版

通常状况下咱们会应用 WebpackDefinePlugin 办法来将 NODE_ENV 变量值设置为 production。编译版本中 React会疏忽 propType 验证以及其余的告警信息,同时还会升高代码库的大小,React 应用了 Uglify 插件来移除生产环境下不必要的正文等信息

正文完
 0