React 小知识

什么是 Virtual DOM?


Virtual DOM 是一种编程概念。在这个概念里, UI 以一种理想化的,或者说“虚拟的”表现形式被保存于内存中,并通过如 ReactDOM 等类库使之与“真实的” DOM 同步。这一过程叫做 协调

这种方式赋予了 React 声明式的 API:您告诉 React 希望让 UI 是什么状态,React 就确保 DOM 匹配该状态。这使您可以从属性操作、事件处理和手动 DOM 更新这些在构建应用程序时必要的操作中解放出来。

与其将 “Virtual DOM” 视为一种技术,不如说它是一种模式,人们提到它时经常是要表达不同的东西。在 React 的世界里,术语 “Virtual DOM” 通常与 React 元素 关联在一起,因为它们都是代表了用户界面的对象。而 React 也使用一个名为 “fibers” 的内部对象来存放组件树的附加信息。上述二者也被认为是 React 中 “Virtual DOM” 实现的一部分。






区分Real DOM和Virtual DOM?


Real DOM Virtual DOM
更新缓慢。 更新更快。
可以直接更新 HTML。 无法直接更新 HTML。
如果元素更新,则创建新DOM。 如果元素更新,则更新 JSX 。
DOM操作代价很高。 DOM 操作非常简单。
消耗的内存较多。 很少的内存消耗。






说一下单向数据流有什么好处?


单向数据流,数据流动方向可以跟踪,流动单一,追查问题的时候可以更快捷。






什么是React?


  • 简介
    React 是一个声明式,高效且灵活的用于构建用户界面的 JavaScript 库。

  • 特点
    1 使用虚拟DOM而不是真正的DOM。
    2 可以用服务器端渲染
    3 遵循单向数据流或数据绑定。

  • 优点
    1 以声明式编写 UI,可以让你的代码更加可靠,且方便调试。
    2 由于组件逻辑使用 JavaScript 编写而非模板,因此你可以轻松地在应用中传递数据,并保持状态与 DOM 分离。
    3 一次学习,跨平台编写
    4 可以使用 Node 进行服务器渲染,或使用 React Native 开发原生移动应用。






什么JSX?


JSX 即 JavaScript XML, 是 JavaScript 语法扩展。它类似于模板语言,但它具有 JavaScript 的全部能力。JSX 最终会被编译为 React.createElement() 函数调用,返回称为 “React 元素” 的普通 JavaScript 对象。
优点:
1> 允许使用熟悉的语法来定义 HTML DOM 树;
2> 提供更加语义化的标签;
3> 程序结构更直观;
4> 抽象了 React Element 的创建过程;
5> 随时掌握 HTML 标签以及生成这些标签的代码;
6> 是原生的 JavaScript






为什么浏览器无法读取JSX?


浏览器只能处理 JavaScript 对象,而不能读取常规 JavaScript 对象中的 JSX。所以为了使浏览器能够读取 JSX,首先,需要用像 Babel 这样的 JSX 转换器将 JSX 文件转换为 JavaScript 对象,然后再将其传给浏览器。






函数组件与 class 组件?


1> 定义:

  • 函数组件
    接收唯一带有数据的 “props”(代表属性)对象与并返回一个 React 元素。这类组件被称为“函数组件”。

     function Welcome(props) {
        return <h1>Hello, {props.name}</h1>;
     }
    
  • class 组件
    使用 class 语法,继承 React.Component,并创建一个 render 函数返回 React 元素。

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

2> 共同点:

  • 所有 React 组件都必须是纯函数,两者都不能修改自身 props。
  • React 是单向数据流,父组件改变了属性,那么子组件视图都会进行更新。

3> 区别:

  • 语法: 函数 与 类 (具体可看定义1)
  • 状态管理:class 使用的是 state,函数组件使用 hooks useState(React 版本 16.8 之后,之前不能)
  • 生命周期:class 有相应的生命周期函数,函数组件使用 hooks useEffect(React 版本 16.8 之后,之前不能)






什么是纯组件?


纯(Pure) 组件是可以编写的最简单、最快的组件。它们可以替换任何只有 render() 的组件。这些组件增强了代码的简单性和应用的性能。






React 组件通信方式?


  • 父组件向子组件通信
    通过 props 向子组件传递需要的信息

    // 子组件: Child
    const Child = props =>{
      return <p>{props.name}</p>
    }
    
    // 父组件 Parent
    const Parent = ()=>{
        return <Child name="M"></Child>
    }
    
  • 子组件向父组件通信
    props + 回调方式

    // 子组件: Child
    const Child = props =>{
      const cb = msg =>{
        return () => {
            props.callback(msg)
        }
    }
    return (
        <button onClick={cb("M, Welocme!")}>Welcome~</button>
      )
    }
    
    // 父组件 Parent
    class Parent extends Component {
      callback(msg){
          console.log(msg)
      }
      render(){
          return <Child callback={this.callback.bind(this)}></Child>    
      }
    }
    
  • 跨级组件通信
    1> 使用 props,层层传递。
    2> 使用 context

  • 非嵌套关系的组件通信
    1> 使用自定义事件通信
    2> 通过 redux 等进行全局状态管理
    3> 如果是兄弟组件通信,可以找到共同父节点,结合父节点通信方式进行通信






React 中 keys 的作用是什么?


Keys 是 React 用于追踪哪些列表中元素被修改、被添加或者被移除的辅助标识。
在开发过程中,我们需要保证某个元素的 key 在其同级元素中具有唯一性。
在 React Diff 算法中,React 会借助元素的 key 值来判断该元素是新近创建的还是被移动而来的元素,从而减少不必要的元素渲染。
此外,React 还需要借助 key 值来判断元素与本地状态的关联关系。

几点注意事项:
1 key值一定要和具体的元素一一对应到。
2 尽量不要用数组的 index 去作为key

3 永远不要试图在render的时候,用随机数或者其他操作给元素加上不稳定的key,这样造成的性能开销比不加key的情况更糟糕。






React 中的 refs 作用是什么?


refs 提供了一种方式,允许我们访问 DOM 节点或在 render 方法中创建的 React 元素。
注:不能在函数组件上使用 ref 属性,因为他们没有实例。在 React 16 之后,可以使用 React hooks useRef。

  • 创建 refs
    Refs 是使用 React.createRef() 创建的,并通过 ref 属性附加到 React 元素。在构造组件时,通常将 Refs 分配给实例属性,以便可以在整个组件中引用它们。
    class MyComponent extends React.Component {
      constructor(props) {
        super(props);
        this.myRef = React.createRef(); 
      }
      render() {
        return <div ref={this.myRef} />;
      }
    }
    
  • 访问 Refs
    当 ref 被传递给 render 中的元素时,对该节点的引用可以在 ref 的 current 属性中被访问。
    const node = this.myRef.current;  
    






何时使用 Refs


下面是几个适合使用 refs 的情况:

  • 管理焦点,文本选择或媒体播放。
  • 触发强制动画。
  • 集成第三方 DOM 库。






React 中 setState 后发生了什么?setState为什么默认是异步?setState 什么时候是同步?


  1. React 中 setState 后发生了什么?
    React 会将传入的参数对象与组件当前的状态合并,然后触发所谓的调和过程。
    经过调和过程,React 会以相对高效的方式根据新的状态构建 React 元素树并且着手重新渲染整个 UI 界面。
    在React得到元素树之后,React 会自动计算出新的树与老树的节点差异,然后根据差异对界面进行最小化重渲染。
    在差异计算算法中,React 能够相对精确地知道哪些位置发生了改变以及应该如何改变,这就保证了按需要更新,而不是全部重新渲染。

  2. setState为什么默认是异步?
    假如所有 setState 是同步,意味着每执行一次 setState 时,都重新 vnode diff + dom 修改,这对性能来说是极为不好的。如果是异步,则可以把一个同步代码中的多个 setState 合并成一次组件更新。

  3. setState什么时候是同步?
    在 setTimeout或者原生事件中,setState 是同步的。






state 和 props 的区别?


state 和 props都是普通的JavaScript对象。尽管它们两者都具有影响渲染输出的信息,但它们在组件方面的功能不同。即

  • props 是一个从外部传进组件的参数,主要作为就是从父组件向子组件传递数据,它具有可读性和不变性,只能通过外部组件主动传入新的 props 来重新渲染子组件,否则子组件的 props 以及展现形式不会改变。

  • state 的主要作用是用于组件保存、控制以及修改自己的状态,它只能在 constructor 中初始化,它算是组件的私有属性,不可通过外部访问和修改,只能通过组件内部的 this.setState 来修改,修改 state 属性会导致组件的重新渲染。






React中的事件是什么?


在 React 中,事件是对鼠标悬停、鼠标单击、按键等特定操作的触发反应。处理这些事件类似于处理 DOM 元素中的事件。但是有一些语法差异,如:

  • React 事件的命名采用小驼峰式(camelCase),而不是纯小写。
  • 使用 JSX 语法时你需要传入一个函数作为事件处理函数,而不是一个字符串。
  • 不能通过返回 false 的方式阻止默认行为。你必须显式的使用 preventDefault 。






React中的合成事件是什么?


是浏览器的原生事件的跨浏览器包装器。除兼容所有浏览器外,它还拥有和浏览器原生事件相同的接口,包括 stopPropagation() 和 preventDefault()。
具体参考 React 合成事件






什么是高阶组件(HOC)?


  • 高阶组件(HOC)是 React 中用于复用组件逻辑的一种高级技巧。HOC 自身不是 React API 的一部分,它是一种基于 React 的组合特性而形成的设计模式。
    具体而言,高阶组件是参数为组件,返回值为新组件的函数。
const EnhancedComponent = higherOrderComponent(WrappedComponent);

组件是将 props 转换为 UI,而高阶组件是将组件转换为另一个组件。
请注意,HOC 不会修改传入的组件,也不会使用继承来复制其行为。相反,HOC 通过将组件包装在容器组件中来组成新组件。HOC 是纯函数,没有副作用。






constructor 中 super 与 props 参数一起使用的目的是什么?


在 React 组件挂载之前,会调用它的构造函数。在为 React.Component 子类实现构造函数时,应在其他语句之前前调用 super(props)。否则,this.props 在构造函数中可能会出现未定义的 bug。

通常,在 React 中,构造函数仅用于以下两种情况。

  • 通过给 this.state 赋值对象来初始化内部 state
  • 为事件处理函数绑定实例
    如果不初始化 state 或不进行方法绑定,则不需要为 React 组件实现构造函数。






对于无状态组件的理解


无状态组件指的是组件内部不维护 state,只根据外部组件传入的 props 进行渲染的组件,当 props 改变时,组件重新渲染。
有状态组件内部使用 state,维护自身状态的变化,有状态组件根据外部组件传入的 props 和自身的 state,进行渲染。

  • 不依赖自身的状态组件。
  • 可以是类组件或者函数组件。
  • 可以完全避免使用 this 关键字。
  • 有更高的性能。






什么是受控组件?


在 HTML 中,表单元素(如<input><textarea><select>)通常自己维护 state,并根据用户输入进行更新。而在 React 中,可变状态(mutable state)通常保存在组件的 state 属性中,并且只能通过使用 setState() 来更新。

我们可以把两者结合起来,使 React 的 state 成为“唯一数据源”。渲染表单的 React 组件还控制着用户输入过程中表单发生的操作。被 React 以这种方式控制取值的表单输入元素就叫做“受控组件”

class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: ''};

    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(event) {
    this.setState({value: event.target.value});
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          名字:
          <input type="text" value={this.state.value} onChange={this.handleChange} />
        </label> 
      </form>
    );
  }
}






以下使用React.createElement的等价项是什么?


Babel 会把 JSX 转译成一个名为 React.createElement() 函数调用。
以下两种示例代码完全等效:

const element = (
  <h1 className="greeting">
    Hello, world!
  </h1>
);
const element = React.createElement(
  'h1',
  {className: 'greeting'},
  'Hello, world!'
);






ReactJS 生命周期有哪些不同阶段?


可以参考 React 生命周期图谱

组件的生命周期可以分为以下几个阶段,常用的生命周期已经加粗。

  • 挂载:
    当组件实例被创建并插入 DOM 中时,其生命周期调用顺序如下:
    constructor()
    static getDerivedStateFromProps()
    render()
    componentDidMount()
  • 更新:
    当组件的 props 或 state 发生变化时会触发更新。组件更新的生命周期调用顺序如下:
    static getDerivedStateFromProps()
    shouldComponentUpdate()
    render()
    getSnapshotBeforeUpdate()
    componentDidUpdate()

  • 卸载:
    当组件从 DOM 中移除时会调用如下方法:
    componentWillUnmount()






React 中 render() 的作用


render() 方法是 class 组件中唯一必须实现的方法。

当 render 被调用时,它会检查 this.props 和 this.state 的变化并做出相应返回。

render() 函数应该为纯函数,这意味着在不修改组件 state 的情况下,每次调用时都返回相同的结果,并且它不会直接与浏览器交互。






shouldComponentUpdate 的作用?


用来判断是否需要调用 render 方法重新描绘 dom。因为 dom 的描绘非常消耗性能,如果我们能在 shouldComponentUpdate 方法中能够写出更优化的 dom diff 算法,可以极大的提高性能。






为什么虚拟 dom 会提高性能?


虚拟 dom 相当于在 js 和真实 dom 中间加了一个缓存,利用 dom diff 算法避免了没有必要的 dom 操作,从而提高性能。






React diff 原理?







React Hook 有什么优势?


  • 简介
    Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。
    可以让你在函数组件里“钩入” React state 及生命周期等特性的函数。Hook 不能在 class 组件中使用 —— 这使得你不使用 class 也能使用 React。
  • 优点
    无需复杂的DOM结构
    简洁易懂






为什么类方法需要绑定?


在 JavaScript 中, this 的值取决于当前上下文。在 React 类的组件方法中,开发人员通常希望它引用组件的当前实例,因此有必要将这些方法绑定到该实例。






React context 是什么?


Context 提供了一个无需为每层组件手动添加 props,就能在组件树间进行数据传递的方法。

  • React.createContext
    const MyContext = React.createContext(defaultValue);
    
    创建一个 Context 对象。当 React 渲染一个订阅了这个 Context 对象的组件,这个组件会从组件树中离自身最近的那个匹配的 Provider 中读取到当前的 context 值。
  • Context.Provider
    <MyContext.Provider value={/* 某个值 */}>
    
    每个 Context 对象都会返回一个 Provider React 组件,它允许消费组件订阅 context 的变化。
  • Class.contextType
    class MyClass extends React.Component {
      componentDidMount() {
        let value = this.context;
        /* 在组件挂载完成后,使用 MyContext 组件的值来执行一些有副作用的操作 */
      }
      componentDidUpdate() {
        let value = this.context;
        /* ... */
      }
      componentWillUnmount() {
        let value = this.context;
        /* ... */
      }
      render() {
        let value = this.context;
        /* 基于 MyContext 组件的值进行渲染 */
      }
    }
    MyClass.contextType = MyContext;
    
    挂载在 class 上的 contextType 属性会被重赋值为一个由 React.createContext() 创建的 Context 对象。此属性能让你使用 this.context 来消费最近 Context 上的那个值。你可以在任何生命周期中访问到它,包括 render 函数中。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容