Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2019前端面试题 —— React相关 #12

Open
fengmiaosen opened this issue Jul 8, 2019 · 0 comments
Open

2019前端面试题 —— React相关 #12

fengmiaosen opened this issue Jul 8, 2019 · 0 comments

Comments

@fengmiaosen
Copy link
Owner

fengmiaosen commented Jul 8, 2019

  1. react 的key值用处

    • React启发式算法就是采用一系列前提和假设,使得比较前后元素树的时间复杂度由O(n3)降低为O(n),React启发式算法的前提条件主要包括两点:

      1. 不同的两个元素会产生不同的树
      2. 可以使用key属性来表明不同的渲染中哪些元素是相同的
    • React key带来了什么

    • key

    • 聊聊列表中的 key 属性

  2. virtual dom的原理和优势

    React的虚拟DOM优势在哪里

    减少了同一时间内的页面多处内容修改所触发的浏览器reflow和repaint的次数,可能把多个不同的DOM操作集中减少到了几次甚至一次,优化了触发浏览器reflow和repaint的次数

    探索Virtual DOM的前世今生
    深入框架本源系列 —— Virtual Dom
    React 源码剖析系列 - 不可思议的 react diff

  3. react-router的跳转原理

    现在回到一开始的问题,重新理解一下点击一个 Link 跳转的过程。

    有两件事需要完成:

    1. 路由的改变
    2. 页面的渲染部分的改变

    过程如下:

    1. 在最一开始 mount Router 的时候,Router 在 componentWillMount 中 listen 了一个回调函数,由 history 库管理,路由每次改变的时候触发这个回调函数。这个回调函数会触发 setState。
    2. 当点击 Link 标签的时候,实际上点击的是页面上渲染出来的 a 标签,然后通过 preventDefault 阻止 a 标签的页面跳转。
    3. Link 中也能拿到 Router -> Route 中通过 context 传递的 history,执行 hitsory.push(to),这个函数实际上就是包装了一下 window.history.pushState(),是 HTML5 history 的 API,但是 pushState 之后除了地址栏有变化其他没有任何影响,到这一步已经完成了目标1:路由的改变。
    4. 第1步中,路由改变是会触发 Router 的 setState 的,在 Router 那章有写道:每次路由变化 -> 触发顶层 Router 的监听事件 -> Router 触发 setState -> 向下传递新的 nextContext(nextContext 中含有最新的 location)
    5. 下层的 Route 拿到新的 nextContext 通过 matchPath 函数来判断 path 是否与 location 匹配,如果匹配则渲染,不匹配则不渲染,完成目标2:页面的渲染部分的改变。

    前端路由实现及 react-router v4 源码分析

  4. redux相关的解决方案(redux-thunk、redux-saga)

    redux-thunk
    redux-saga

  5. 原生js实现排行榜列表(dom)结构的首位调转顺序

    https://blog.csdn.net/w770583069/article/details/75997515

  6. react setState什么情况下是异步,什么情况下同步

    https://muyiy.cn/question/frame/18.html

    • setState 只在合成事件和钩子函数中是“异步”的,在原生事件和 setTimeout 中都是同步的。

    • setState的“异步”并不是说内部由异步代码实现,其实本身执行的过程和代码都是同步的,只是合成事件和钩子函数的调用顺序在更新之前,导致在合成事件和钩子函数中没法立马拿到更新后的值,形式了所谓的“异步”,当然可以通过第二个参数 setState(partialState, callback) 中的callback拿到更新后的结果。

    • setState 的批量更新优化也是建立在“异步”(合成事件、钩子函数)之上的,在原生事件和setTimeout 中不会批量更新,在“异步”中如果对同一个值进行多次 setState , setState 的批量更新策略会对其进行覆盖,取最后一次的执行,如果是同时 setState 多个不同的值,在更新时会对其进行合并批量更新。

      搞懂setState
      揭秘setState
      React 架构的演变 - 从同步到异步

  7. React状态管理之Context

    https://juejin.im/post/5c74026ce51d4520f0178e06?utm_source=gold_browser_extension

  8. 自己实现类似redux的 applyMiddleware

export default function compose(...funcs) {
  if (funcs.length === 0) {
    return arg => arg
  }

  if (funcs.length === 1) {
    return funcs[0]
  }

  return funcs.reduce((a, b) => (...args) => a(b(...args)))
}

export default function applyMiddleware(...middlewares) {
  return (createStore) => (reducer, preloadedState, enhancer) => {
    const store = createStore(reducer, preloadedState, enhancer)
    let dispatch = store.dispatch
    let chain = []

    const middlewareAPI = {
      getState: store.getState,
      dispatch: (action) => dispatch(action)
    }
    chain = middlewares.map(middleware => middleware(middlewareAPI))
    dispatch = compose(...chain)(store.dispatch)

    return {
      ...store,
      dispatch
    }
  }
}

  1. react父组件调用子组件方法

    https://blog.csdn.net/hesongGG/article/details/79373565

  2. react ref

    https://imweb.io/topic/5b6136a06025939b125f45ff
    https://juejin.im/post/5ac598916fb9a028ca53333c

  3. render props (children prop )

    Render Props
    React组件Render Props VS HOC 设计模式
    使用 Render props 吧

  4. react 组合 vs 继承

    composition-vs-inheritance

    为什么 React 推崇 HOC 和组合的方式,而不是继承的方式来扩展组件?

  5. react常用设计模式(HOC 和 render props)

  6. 手动实现redux-thunk

redux-thunk 源码全方位剖析

function createThunkMiddleware(extraArgument) {
  return ({ dispatch, getState }) => next => action => {
    if (typeof action === 'function') {
      return action(dispatch, getState, extraArgument);
    }

    return next(action);
  };
}

const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;
  1. 编写高性能React组件

    https://www.infoq.cn/article/KVE8xtRs-uPphptq5LUz
    https://imweb.io/topic/577512fe732b4107576230b9
    React性能测量和分析
    浅谈React性能优化的方向

  2. 使用react hooks实现 useInterval

    https://overreacted.io/zh-hans/making-setinterval-declarative-with-react-hooks/

function useInterval(callback, delay) {
  const savedCallback = useRef();

  // Remember the latest function.
  useEffect(() => {
    savedCallback.current = callback;
  }, [callback]);

  // Set up the interval.
  useEffect(() => {
    function tick() {
      savedCallback.current();
    }
    if (delay !== null) {
      let id = setInterval(tick, delay);
      return () => clearInterval(id);
    }
  }, [delay]);
}
  1. 避免React Context导致的重复渲染

    https://zhuanlan.zhihu.com/p/50336226

  2. redux

* 其中用到了哪些设计模式

- 发布订阅模式
  1. 基于React实现拖拽API

    How To Use The HTML Drag-And-Drop API In React

  2. react 获取组件对象示例

//#root为react容器
//获取根节点实例对象
const fiberRoot = document.querySelector('#root')._reactRootContainer._internalRoot
//从组件实例中获取单独的 Fiber 节点:
compInstance._reactInternalFiber
  1. react setstate后整个渲染流程

  2. batchedUpdates 如何影响 setState

    ReactComponent.prototype.setState = function (partialState, callback) {
      //  将setState事务放进队列中
          this.updater.enqueueSetState(this, partialState);
          if (callback) {
            this.updater.enqueueCallback(this, callback, 'setState');
           }
     };
* setState的调用路径仅是将入参中的state放到一个实例的属性中,以及将当前组件放到ReactUpdates 的全局变量dirtyComponents中,并没有发现真正是在哪里去触发更新DOM的操作

* 事件触发的方法中,有一个ReactUpdates.batchedUpdates方法的调用
    /** ReactEventListener */
    dispatchEvent: function (topLevelType, nativeEvent) {
      ...
      ReactUpdates.batchedUpdates(handleTopLevelImpl, bookKeeping);
      ...
    }

var ReactDefaultBatchingStrategy = {
  // 用于标记当前是否出于批量更新
  isBatchingUpdates: false,
  // 当调用这个方法时,正式开始批量更新
  batchedUpdates: function (callback, a, b, c, d, e) {
    var alreadyBatchingUpdates = ReactDefaultBatchingStrategy.isBatchingUpdates;

    ReactDefaultBatchingStrategy.isBatchingUpdates = true;

    // 如果当前事务正在更新过程在中,则调用callback,既enqueueUpdate
    if (alreadyBatchingUpdates) {
      return callback(a, b, c, d, e);
    } else {
    // 否则执行更新事务
      return transaction.perform(callback, null, a, b, c, d, e);
    }
  }
};
  1. react 生命周期函数执行流程

  2. React Fiber

  3. React 在两个主要阶段执行工作:render 和 commit

    • render

    render 方法返回的每个元素创建一个新的 Fiber� 节点。在后续更新中,现有 React 元素的 Fiber 节点将被重复使用和更新。这一阶段是为了得到标记了副作用的 Fiber 节点树
    render 阶段的工作是可以异步执行的。React 可以根据可用时间片来处理一个或多个 Fiber 节点,然后停下来暂存已完成的工作,并转而去处理某些事件,接着它再从它停止的地方继续执行。但有时候,它可能需要丢弃完成的工作并再次从顶部开始。由于在此阶段执行的工作不会导致任何用户可见的更改(如 DOM 更新),因此暂停行为才有了意义

    • commit

    commit 阶段始终是同步的。这是因为在此阶段执行的工作会导致用户可见的变化,例如 DOM 更新。这就是为什么 React 需要在一次单一过程中完成这些更新

  4. react 受控组件 和 非受控组件

    受控组件

  5. Redux 实现撤销重做

    redux-undo

  6. redux middleware 详解
    https://zhuanlan.zhihu.com/p/20597452

  7. 将 React 应用优化到 60fps

    • 避免过早优化
      正常的性能优化过程应该包含以下几个步骤:

      • 确定发现存在性能的缺陷

      • 使用 DevTools 来解析发现瓶颈所在

      • 尝试使用优化技巧解决这些问题

      • 测试是否确实有性能提升

      • 重复第二步

    • 需要使用 shouldComponentUpdate 吗

      • 使用简单 Props 的纯组件
      • 叶子组件或者在组件树中较深位置的组件
    • 将高性能消耗的代码放置到较高阶组件中

      • 将可视化数据与覆盖层信息抽取出来放置到独立的组件中
      • 将执行大量数据转换的代码移出到容器组件中
      • 使用不可变数据结构(Immutable)来降低比较带来的性能消耗
    • 不要滥用 this.setState

      • 不应该将render()函数中用不到的状态放置到this.state对象中
  8. Virtual Dom的更新

    https://segmentfault.com/a/1190000016145981

  9. React SSR 实现原理

https://juejin.im/post/5bc7ea48e51d450e46289eab
  1. redux原理

    redux原理解析,看这篇就够
    redux middleware 详解

  2. react hooks

    你可能不知道的React hooks
    从React Hooks看React的本质
    10个案例让你彻底理解React hooks的渲染逻辑

  3. React16 技术原理小册

    React 技术揭秘 ***

    beginwork

参考资料

@fengmiaosen fengmiaosen changed the title 2019前端面试题之 React相关知识点 2019前端面试题(一)—— React相关知识点 Jul 8, 2019
@fengmiaosen fengmiaosen changed the title 2019前端面试题(一)—— React相关知识点 2019前端面试题(一)—— React相关 Jul 8, 2019
@fengmiaosen fengmiaosen changed the title 2019前端面试题(一)—— React相关 2019前端面试题 —— React相关 Jul 8, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant