乐趣区

关于react.js:react常见面试题

组件之间传值

  • 父组件给子组件传值

    在父组件中用标签属性的 = 模式传值

    在子组件中应用 props 来获取值

  • 子组件给父组件传值

    在组件中传递一个函数

    在子组件中用 props 来获取传递的函数,而后执行该函数

    在执行函数的时候把须要传递的值当成函数的实参进行传递

  • 兄弟组件之间传值

    利用父组件

    先把数据通过【子组件】===》【父组件】

    而后在数据通过【父组件】===〉【子组件】

    音讯订阅

    应用 PubSubJs 插件

为何 React 事件要本人绑定 this

在 React 源码中,当具体到某一事件处理函数将要调用时,将调用 invokeGuardedCallback 办法。

function invokeGuardedCallback(name, func, a) {
  try {func(a);
  } catch (x) {if (caughtError === null) {caughtError = x;}
  }
}

事件处理函数是间接调用的,并没有指定调用的组件,所以不进行手动绑定的状况下间接获取到的 this 是不精确的,所以咱们须要手动将以后组件绑定到 this 上

应用箭头函数 (arrow functions) 的长处是什么

  • 作用域平安:在箭头函数之前,每一个新创建的函数都有定义本身的 this 值(在构造函数中是新对象;在严格模式下,函数调用中的 this 是未定义的;如果函数被称为“对象办法”,则为根底对象等),但箭头函数不会,它会应用关闭执行上下文的 this 值。
  • 简略:箭头函数易于浏览和书写
  • 清晰:当一切都是一个箭头函数,任何惯例函数都能够立刻用于定义作用域。开发者总是能够查找 next-higher 函数语句,以查看 this 的值

解释 React 中 render() 的目标。

每个 React 组件强制要求必须有一个 render()。它返回一个 React 元素,是原生 DOM 组件的示意。如果须要渲染多个 HTML 元素,则必须将它们组合在一个关闭标记内,例如 <form><group><div> 等。此函数必须放弃污浊,即必须每次调用时都返回雷同的后果。

指出 (组件) 生命周期办法的不同

  • componentWillMount — 多用于根组件中的应用程序配置
  • componentDidMount — 在这能够实现所有没有 DOM 就不能做的所有配置,并开始获取所有你须要的数据;如果须要设置事件监听,也能够在这实现
  • componentWillReceiveProps — 这个周期函数作用于特定的 prop 扭转导致的 state 转换
  • shouldComponentUpdate — 如果你放心组件适度渲染,shouldComponentUpdate 是一个改善性能的中央,因为如果组件接管了新的 prop,它能够阻止 (组件) 从新渲染。shouldComponentUpdate 应该返回一个布尔值来决定组件是否要从新渲染
  • componentWillUpdate — 很少应用。它能够用于代替组件的 componentWillReceivePropsshouldComponentUpdate(但不能拜访之前的 props)
  • componentDidUpdate — 罕用于更新 DOM,响应 prop 或 state 的扭转
  • componentWillUnmount — 在这你能够勾销网络申请,或者移除所有与组件相干的事件监听器

React 中 constructor 和 getInitialState 的区别?

两者都是用来初始化 state 的。前者是 ES6 中的语法,后者是 ES5 中的语法,新版本的 React 中曾经废除了该办法。

getInitialState 是 ES5 中的办法,如果应用 createClass 办法创立一个 Component 组件,能够主动调用它的 getInitialState 办法来获取初始化的 State 对象,

var APP = React.creatClass ({getInitialState() {
    return { 
        userName: 'hi',
        userId: 0
     };
 }
})
复制代码

React 在 ES6 的实现中去掉了 getInitialState 这个 hook 函数,规定 state 在 constructor 中实现,如下:

Class App extends React.Component{constructor(props){super(props);
      this.state={};}
  }
复制代码

对 React Hook 的了解,它的实现原理是什么

React-Hooks 是 React 团队在 React 组件开发实际中,逐步认知到的一个改良点,这背地其实波及对 类组件 函数组件 两种组件模式的思考和偏重。

(1)类组件: 所谓类组件,就是基于 ES6 Class 这种写法,通过继承 React.Component 得来的 React 组件。以下是一个类组件:

class DemoClass extends React.Component {
  state = {text: ""};
  componentDidMount() {//...}
  changeText = (newText) => {
    this.setState({text: newText});
  };

  render() {
    return (
      <div className="demoClass">
        <p>{this.state.text}</p>
        <button onClick={this.changeText}> 批改 </button>
      </div>
    );
  }
}

复制代码

能够看出,React 类组件外部预置了相当多的“现成的货色”等着咱们去调度 / 定制,state 和生命周期就是这些“现成货色”中的典型。要想得到这些货色,难度也不大,只须要继承一个 React.Component 即可。

当然,这也是类组件的一个不便,它太繁冗了,对于解决许多问题来说,编写一个类组件切实是一个过于简单的姿态。简单的姿态必然带来昂扬的了解老本,这也是咱们所不想看到的。除此之外,因为开发者编写的逻辑在封装后是和组件粘在一起的,这就使得 类组件外部的逻辑难以实现拆分和复用。

(2)函数组件:函数组件就是以函数的状态存在的 React 组件。晚期并没有 React-Hooks,函数组件外部无奈定义和保护 state,因而它还有一个别名叫“无状态组件”。以下是一个函数组件:

function DemoFunction(props) {const { text} = props
  return (
    <div className="demoFunction">
      <p>{` 函数组件接管的内容:[${text}]`}</p>
    </div>
  );
}
复制代码

相比于类组件,函数组件肉眼可见的特质天然包含轻量、灵便、易于组织和保护、较低的学习老本等。

通过比照,从状态上能够对两种组件做辨别,它们之间的区别如下:

  • 类组件须要继承 class,函数组件不须要;
  • 类组件能够拜访生命周期办法,函数组件不能;
  • 类组件中能够获取到实例化后的 this,并基于这个 this 做各种各样的事件,而函数组件不能够;
  • 类组件中能够定义并保护 state(状态),而函数组件不能够;

除此之外,还有一些其余的不同。通过下面的区别,咱们不能说谁好谁坏,它们各有本人的劣势。在 React-Hooks 呈现之前,类组件的能力边界显著强于函数组件。

实际上,类组件和函数组件之间,是面向对象和函数式编程这两套不同的设计思维之间的差别。而函数组件更加符合 React 框架的设计理念:React 组件自身的定位就是函数,一个输出数据、输入 UI 的函数。作为开发者,咱们编写的是申明式的代码,而 React 框架的次要工作,就是及时地把申明式的代码转换为命令式的 DOM 操作,把数据层面的形容映射到用户可见的 UI 变动中去。这就意味着从原则上来讲,React 的数据应该总是紧紧地和渲染绑定在一起的,而类组件做不到这一点。函数组件就真正地将数据和渲染绑定到了一起。函数组件是一个更加匹配其设计理念、也更有利于逻辑拆分与重用的组件表达形式。

为了能让开发者更好的的去编写函数式组件。于是,React-Hooks 便应运而生。

React-Hooks 是一套可能使函数组件更弱小、更灵便的“钩子”。

函数组件比起类组件少了很多货色,比方生命周期、对 state 的治理等。这就给函数组件的应用带来了十分多的局限性,导致咱们并不能应用函数这种模式,写出一个真正的全功能的组件。而 React-Hooks 的呈现,就是为了帮忙函数组件补齐这些(绝对于类组件来说)缺失的能力。

如果说函数组件是一台笨重的快艇,那么 React-Hooks 就是一个内容丰盛的零部件箱。“重装战舰”所预置的那些设施,这个箱子里根本全都有,同时它还不强制你全都要,而是容许你自在地抉择和应用你须要的那些能力,而后将这些能力以 Hook(钩子)的模式“钩”进你的组件里,从而定制出一个最适宜你的“专属战舰”。

React 的严格模式如何应用,有什么用途?

StrictMode 是一个用来突出显示应用程序中潜在问题的工具。与 Fragment 一样,StrictMode 不会渲染任何可见的 UI。它为其后辈元素触发额定的检查和正告。
能够为应用程序的任何局部启用严格模式。例如:

import React from 'react';
function ExampleApplication() {
  return (
    <div>
      <Header />
      <React.StrictMode>        
        <div>
          <ComponentOne />
          <ComponentTwo />
        </div>
      </React.StrictMode>      
      <Footer />
    </div>
  );
}

复制代码

在上述的示例中,不会对 HeaderFooter 组件运行严格模式查看。然而,ComponentOneComponentTwo 以及它们的所有后辈元素都将进行查看。

StrictMode 目前有助于:

  • 辨认不平安的生命周期
  • 对于应用过期字符串 ref API 的正告
  • 对于应用废除的 findDOMNode 办法的正告
  • 检测意外的副作用
  • 检测过期的 context API

为什么要应用 React. Children. map(props. children,()=>)而不是 props. children. map (() => )?

因为不能保障 props. children 将是一个数组。
以上面的代码为例。

<Parent>
    <h1> 有课前端网 </h1>
</Parent>

在父组件外部,如果尝试应用 props.children. map 映射子对象,则会抛出谬误,因为 props. children 是一个对象,而不是一个数组。
如果有多个子元素,React 会使 props.children 成为一个数组,如下所示。

<Parent>
  <h1> 有课前端网 </h1>
  <h2> 前端技术学习平台 </h2>
</Parent>;
// 不倡议应用如下形式,在这个案例中会抛出谬误。class Parent extends Component {render() {return <div> {this.props.children.map((obj) => obj)}</div>;
  }
}

倡议应用如下形式,防止在上一个案例中抛出谬误。

class Parent extends Component {render() {return <div> {React.Children.map(this.props.children, (obj) => obj)}</div>;
  }
}

hooks 和 class 比拟的劣势?

一、更容易复用代码

二、清新的代码格调 + 代码量更少

毛病

状态不同步
不好用的 useEffect,

类组件和函数组件有何不同?

解答

在 React 16.8 版本(引入钩子)之前,应用基于类的组件来创立须要保护外部状态或利用生命周期办法的组件(即 componentDidMountshouldComponentUpdate)。基于类的组件是 ES6 类,它扩大了 React 的 Component 类,并且至多实现了 render() 办法。

类组件:

class Welcome extends React.Component {render() {return <h1>Hello, {this.props.name}</h1>;
  }
}
复制代码

函数组件是无状态的(同样,小于 React 16.8 版本),并返回要出现的输入。它们渲染 UI 的首选只依赖于属性,因为它们比基于类的组件更简略、更具性能。

函数组件:

function Welcome(props) {return <h1>Hello, {props.name}</h1>;
}
复制代码

留神:在 React 16.8 版本中引入钩子意味着这些区别不再实用(请参阅 14 和 15 题)。

进一步浏览

  • React 中比照函数式组件和类组件
  • React 中函数与类组件比对

什么是 React Context?

Context 通过组件树提供了一个传递数据的办法,从而防止了在每一个层级手动的传递 props 属性。

react 实现一个全局的 dialog

import React, {Component} from 'react';
import {is, fromJS} from 'immutable';
import ReactDOM from 'react-dom';
import ReactCSSTransitionGroup from 'react-addons-css-transition-group';
import './dialog.css';
let defaultState = {
  alertStatus:false,
  alertTip:"提醒",
  closeDialog:function(){},
  childs:''
}
class Dialog extends Component{
  state = {...defaultState};
  // css 动画组件设置为指标组件
  FirstChild = props => {const childrenArray = React.Children.toArray(props.children);
    return childrenArray[0] || null;
  }
  // 关上弹窗
  open =(options)=>{options = options || {};
    options.alertStatus = true;
    var props = options.props || {};
    var childs = this.renderChildren(props,options.childrens) || '';
    console.log(childs);
    this.setState({
      ...defaultState,
      ...options,
      childs
    })
  }
  // 敞开弹窗
  close(){this.state.closeDialog();
    this.setState({...defaultState})
  }
  renderChildren(props,childrens) {
    // 遍历所有子组件
    var childs = [];
    childrens = childrens || [];
    var ps = {
        ...props,  // 给子组件绑定 props
        _close:this.close  // 给子组件也绑定一个敞开弹窗的事件    
       };
    childrens.forEach((currentItem,index) => {
        childs.push(React.createElement(
            currentItem,
            {
                ...ps,
                key:index
            }
        ));
    })
    return childs;
  }
  shouldComponentUpdate(nextProps, nextState){return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
  }
   
  render(){
    return (
      <ReactCSSTransitionGroup
        component={this.FirstChild}
        transitionName='hide'
        transitionEnterTimeout={300}
        transitionLeaveTimeout={300}>
        <div className="dialog-con" style={this.state.alertStatus? {display:'block'}:{display:'none'}}>
            {this.state.childs}        </div>
      </ReactCSSTransitionGroup>
    );
  }
}
let div = document.createElement('div');
let props = { };
document.body.appendChild(div);
let Box = ReactD
复制代码

子类:

// 子类 jsx
import React, {Component} from 'react';
class Child extends Component {constructor(props){super(props);
        this.state = {date: new Date()};
  }
  showValue=()=>{this.props.showValue && this.props.showValue()
  }
  render() {
    return (
      <div className="Child">
        <div className="content">
           Child           <button onClick={this.showValue}> 调用父的办法 </button>
        </div>
      </div>
    );
  }
}
export default Child;
复制代码

css:

.dialog-con{
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.3);
}
复制代码

state 和 props 区别是啥?

  • state 是组件本人治理数据,管制本人的状态,可变;
  • props 是内部传入的数据参数,不可变;
  • 没有 state 的叫做无状态组件,有 state 的叫做有状态组件;
  • 多用 props,少用 state,也就是多写无状态组件。

在结构函数调用 super 并将 props 作为参数传入的作用

在调用 super() 办法之前,子类构造函数无奈应用 this 援用,ES6 子类也是如此。
将 props 参数传递给 super() 调用的次要起因是在子构造函数中可能通过 this.props 来获取传入的 props

传递了 props

class MyComponent extends React.Component {constructor(props) {super(props);
    console.log(this.props); // {name: 'sudheer',age: 30}
  }
}

没传递 props

class MyComponent extends React.Component {constructor(props) {super();
    console.log(this.props); // undefined
    // 然而 Props 参数依然可用
    console.log(props); // Prints {name: 'sudheer',age: 30}
  }
  render() {
    // 构造函数内部不受影响
    console.log(this.props); // {name: 'sudheer',age: 30}
  }
}

React 中 refs 的作用是什么?有哪些利用场景?

Refs 提供了一种形式,用于拜访在 render 办法中创立的 React 元素或 DOM 节点。Refs 应该审慎应用,如下场景应用 Refs 比拟适宜:

  • 解决焦点、文本抉择或者媒体的管制
  • 触发必要的动画
  • 集成第三方 DOM 库

Refs 是应用 React.createRef() 办法创立的,他通过 ref 属性附加到 React 元素上。
要在整个组件中应用 Refs,须要将 ref 在构造函数中调配给其实例属性:

class MyComponent extends React.Component {constructor(props) {super(props)
    this.myRef = React.createRef()}
  render() {return <div ref={this.myRef} />
  }
}

高阶组件的利用场景

权限管制

利用高阶组件的 条件渲染 个性能够对页面进行权限管制,权限管制个别分为两个维度: 页面级别 页面元素级别

// HOC.js    
function withAdminAuth(WrappedComponent) {    
    return class extends React.Component {    
        state = {isAdmin: false,}    
        async componentWillMount() {const currentRole = await getCurrentUserRole();    
            this.setState({isAdmin: currentRole === 'Admin',});    
        }    
        render() {if (this.state.isAdmin) {return <WrappedComponent {...this.props} />;    
            } else {return (<div> 您没有权限查看该页面,请分割管理员!</div>);    
            }    
        }    
    };    
}

// 应用
// pages/page-a.js    
class PageA extends React.Component {constructor(props) {super(props);    
        // something here...    
    }    
    componentWillMount() {// fetching data}    
    render() {// render page with data}    
}    
export default withAdminAuth(PageA);    

可能你曾经发现了,高阶组件其实就是装璜器模式在 React 中的实现:通过给函数传入一个组件(函数或类)后在函数外部对该组件(函数或类)进行性能的加强(不批改传入参数的前提下),最初返回这个组件(函数或类),即容许向一个现有的组件增加新的性能,同时又不去批改该组件,属于 包装模式(Wrapper Pattern) 的一种。

什么是装璜者模式:在不扭转对象本身的前提下在程序运行期间动静的给对象增加一些额定的属性或行为

能够进步代码的复用性和灵活性

再对高阶组件进行一个小小的总结:

  • 高阶组件 不是组件 一个把某个组件转换成另一个组件的 函数
  • 高阶组件的次要作用是 代码复用
  • 高阶组件是 装璜器模式在 React 中的实现

封装组件的准则

封装准则

1、繁多准则:负责繁多的页面渲染

2、多重职责:负责多重职责,获取数据,复用逻辑,页面渲染等

3、明确承受参数:必选,非必选,参数尽量设置以_结尾,防止变量反复

4、可扩大:需要变动可能及时调整,不影响之前代码

5、代码逻辑清晰

6、封装的组件必须具备高性能,低耦合的个性

7、组件具备繁多职责:封装业务组件或者根底组件,如果不能给这个组件起一个有意义的名字,证实这个组件承当的职责可能不够繁多,须要持续抽组件,直到它能够是一个独立的组件即可

什么是管制组件?

在 HTML 中,表单元素如 <input><textarea><select> 通常保护本人的状态,并依据用户输出进行更新。当用户提交表单时,来自上述元素的值将随表单一起发送。
而 React 的工作形式则不同。蕴含表单的组件将跟踪其状态中的输出值,并在每次回调函数 (例如onChange) 触发时从新渲染组件,因为状态被更新。以这种形式由 React 管制其值的输出表单元素称为 受控组件

redux 是如何更新值得

用户发动操作之后,dispatch 发送 action,依据 type,触发对于的 reducer,reducer 就是一个纯函数,接管旧的 state 和 action,返回新的 state。通过 subscribe(listener)监听器,派发更新。

退出移动版