1.render函数中return如果没有使用()会有什么问题?(jsx)

如果返回的是单行的元素,那么没有使用()不会有任何问题;
如果返回的是多行元素标签,标签没有换行那么也没有问题;
如果返回的是多行元素标签且换行了,那么会报错,错误的原因是jsx编译成js时会在每一行添加,所以变 成了return;

下面是babel的playground示例,preset预设选择es6和react。

  1. class App extends React.Component {
  2. render() {
  3. return // 多行元素且换行
  4. <div>
  5. <span>123</span>
  6. </div>
  7. }
  8. }
  9. // babel解析结果:
  10. // ... 省略n多代码
  11. _createClass(App, [{
  12. key: "render",
  13. value: function render() {
  14. return; //
  15. React.createElement("div", null, React.createElement("span", null, "123"));
  16. }
  17. }]);
  18. // ... 省略n多代码
  1. class App extends React.Component {
  2. render() {
  3. return <div> // 多行元素但是不换行
  4. <span>123</span>
  5. </div>
  6. }
  7. }
  8. // babel解析结果:
  9. function (_React$Component) {
  10. _inherits(App, _React$Component);
  11. function App() {
  12. _classCallCheck(this, App);
  13. return _possibleConstructorReturn(this, _getPrototypeOf(App).apply(this, arguments));
  14. }
  15. _createClass(App, [{
  16. key: "render",
  17. value: function render() {
  18. return React.createElement("div", null, React.createElement("span", null, "123"));
  19. }
  20. }]);
  21. return App;
  22. }(React.Component);
class App extends React.Component {
    render() {
      return <div>123</div>
    }
}
// babel解析结果:
var App =
/*#__PURE__*/
function (_React$Component) {
  _inherits(App, _React$Component);

  function App() {
    _classCallCheck(this, App);

    return _possibleConstructorReturn(this, _getPrototypeOf(App).apply(this, arguments));
  }

  _createClass(App, [{
    key: "render",
    value: function render() {
      return React.createElement("div", null, "123");
    }
  }]);

  return App;
}(React.Component);

2.componentWillUpdate可以直接修改state值吗?(生命周期)

当组件收到新的props或者state时,会在渲染之前调用componentWillUpdate(),使用此作为在更新发生之前执行准备更新的机会,初始渲染时不会调用这个方法。
你不能在这个方法中调用this.setState(),会触发重复循环。在componentWillUpdate()返回之前,你也不应该执行任何其他的操作触发对eact组件的更新。—来自react官网—

3.说说你对React的渲染原理的理解(渲染原理)

React使用JSX,可以使用在JS中写HTML标签,然后ES6的写法babel把JSX解析成虚拟DOM,es5的话使用React.createElement方法创建虚拟DOM,把虚拟DOM挂载到真实的DOM节点上。React组件会执行React.Component的钩子函数,组件内的状态值通过setState方法进行改变,然后触发render()函数进行渲染,这个过程中React会使用diff算法与之前的虚拟DOM树进行比较,只渲染之前改动的节点。(表达的不好QAQ)

JSX代码经过babel编译之后变成React.createElement的表达式,这个表达式在render函数被调用的时候执行生成一个element。
在首次渲染的时候,先去按照规则初始化element,接着ReactComponentComponentWrapper通过递归,最终调用ReactDOMComponent的mountComponent方法来帮助生成真实DOM节点。

4.什么是渲染劫持?(高阶函数)

通过高阶组件反向继承所传入的组件,然后控制wrappedComponent组件的渲染结果,并且可以做各种操作

1 读取、添加、修改、删除任何一个将被渲染的React Element的props 2 在渲染方法中读取或更改React Elements tree(WrappedComponent children) 3 根据条件不同,选择性的渲染子树 4 给子树里的元素变更样式

条件渲染:

function iiHOC(WrappedComponent) {
  return class Enhancer extends WrappedComponent {
    render() {
      if (this.props.loggedIn) {
        return super.render()
      } else {
        return null
      }
    }
  }
}

通过 render 来变成 React Elements tree 的结果

function iiHOC(WrappedComponent) {
  return class Enhancer extends WrappedComponent {
    render() {
      const elementsTree = super.render()
      let newProps = {};
      if (elementsTree && elementsTree.type === 'input') {
        newProps = {value: 'may the force be with you'}
      }
      const props = Object.assign({}, elementsTree.props, newProps)
      const newElementsTree = React.cloneElement(elementsTree, props, elementsTree.props.children)
      return newElementsTree
    }
  }
}

来源:深入理解 React 高阶组件

5.说说Context有哪些属性

childContextTypes, contextTypes

6.怎么使用Context开发组件

参考:聊一聊我对 React Context 的理解以及应用

7. 为什么React并不推荐我们优先考虑使用Context(v16之前的版本)

绝大多数的应用不需要直接使用Context。
如果你希望你的应用是稳定的,那么就不要使用Context。 因为这是一个实验性质的API,它可能会在未来的React版本中移除。
如果你不熟悉state管理库如Redux或MobX,不要使用Context。 对于许多实际的应用,这些state管理库和React一起使用来管理那些与组件相关的state一个很不错的选择。 很多情况下使用Redux就可以解决你的问题,而不是使用Context。
如果你不是一个有经验的React开发人员,不要使用Context。 使用props和state来实现功能是一个更好的方法。
尽管有上面这些警告你还坚持使用Context,那么请将Context单独隔离到一个小区域中,并尽可能地避免直接使用Context,以便在这个API更改时应用能更容易升级。

8.除了实例的属性可以获取Context外哪些地方还能直接获取Context呢

组件的构造方法:

constructor(props,context)

生命周期:

componentWillReceiveProps(nextProps, nextContext)
shouldComponentUpdate(nextProps, nextState, nextContext)
componetWillUpdate(nextProps, nextState, nextContext)
componentDidUpdate(prevProps, prevState, prevContext)

函数组件:

function Welcome(props, context) {
    return (<div>{this.props}</div>)
}

9.childContextTypes是什么?它有什么用

Context提供者通过childContextTypes定义传递的数据参数,可以像propTypes一样定义数据类型,getChildContext传递数据的值。
Context生产者,需要通过一个静态属性childContextTypes声明提供给子组件的Context对象的属性,并实现一个实例getChildContext方法,返回一个代表Context的纯对象 (plain object) 。

import React from 'react';
import PropsTypes from 'prop-types';

class Parent extends React.Component {
    static childContextTypes = {
    color: PropTypes.string.isRequired,
  }
    getChildContext() {
      return {
        color: 'red',
    }
  }
    render() {
      // ...
  }
}

class ChildComp extends React.Component {
    static contextTypes = {
       color: PropTypes.string.isRequired,
  }
    render() {
      const color = this.context.color;

  }
}

10.contextType是什么?它有什么用

子组件需要通过一个静态属性contextTypes声明后,才能访问父组件Context对象的属性,否则,即使属性名没写错,拿到的对象也是undefined