美文网首页【头号玩家公会】
React进阶(七)模板语言JSX与虚拟DOM

React进阶(七)模板语言JSX与虚拟DOM

作者: 这波能反杀 | 来源:发表于2018-08-18 14:20 被阅读1065次
    梦 想

    我们想要创建一个组件,首先需要理解一个重要的概念:JSX

    const element = <h1>Hello, world!</h1>;
    

    这种类似于html代码的东西就是JSX。我们可以简单的将其理解为一种渲染数据的模板语言。有接触过其他模板语言的同学应该知道,模板语言其实是为了简化直接调用DOM API来渲染数据的复杂度,模板语言的本质仍然是JS代码。记住这个特性,在理解虚拟DOM这个重要概念时会大有帮助。

    在React的组件中,只有引入了React的模块才能正确识别JSX代码。

    // 必不可少
    import React from 'react';
    

    JSX与html非常类似,因此如果你对html已经非常熟悉的话,使用JSX就非常简单。但除此之外,JSX还具有模板语言的特性。

    • 可以在JSX中使用表达式
    const ele = <h1>Hello, {name}!</h1>
    
    const ele = <h1>{sayHello('alex')}!</h1>
    
    const ele = <h1>{condition ? 'React' : 'React Native'}!</h1>
    
    • 每一个标签都可以接收属性
    const element = <div tabIndex="0">注意观察属性</div>
    const element = <div tabIndex={0}>注意观察属性</div>
    const element = <div tabIndex={num}>接收变量</div>
    

    JSX默认支持所有html标签,并且支持所有html标签默认的属性。不过需要注意的是,为了与创建类的关键字class区分开,html标签的class属性在JSX中使用className代替。

    const element = <div className="index">Hello world.</div>
    
    • 作为返回结果

    在引入了React的模块中,我们可以自定一个返回JSX模板的函数,也可以让JSX参与到条件判断中。

    import React from 'react';
    
    ...
    
    function getResult(type) {
      if(type === 'React') {
        return <div>React</div>
      } else {
        return <div>React Native</div>
      }
    }
    

    当我们需要自定义组件时,这种场景会用得非常多,往往我们都需要根据传入的不同状态值动态的判断哪些是我们需要的。

    • 使用[].map暂时列表数据

    当我们想要渲染一列数据时,可以借助数组中的map方法。

    const data = [1, 2, 3, 4, 5, 6, 7];
    
    <div className="wrapper">
      {data.map((item, i) => (
        <div className="num" key={i}>{item}</div>
      ))}
    </div>
    

    实践中,我们有的时候总会逼不得已需要在JSX中处理许多逻辑代码,这个时候就必须要将逻辑代码放入{}中来处理。

    const condition = true;
    
    <div className="wrapper">
      {condition && <div>hello</div>}
    </div>
    

    但是如果使用不善,会导致JSX的可读性变得非常低,因此如果大家在使用过程中发现JSX变得越来越乱越来越复杂,则建议有意识的去寻找优化方法,不断的提高自己React的使用水平。

    • JSX的本质是js对象

    对于一个我们非常属性的html标签div,我们可以用一个JSON对象去描述它。

    const div = {
      // 名字
      name: 'div',
      // 属性
      props: { className: 'wrapper', tabIndex: 0,  ... }
    
      // 父节点
      parentNode: h1<Object>,
    
     // 子节点
      children: [div<Object>, span<Object>],
    
       ...
    }
    

    这里的属性我就随意命名,大概表达意思。我们也可以通过浏览器的开发者工具将一个标签打印出来观察,也会发现每一个标签其实也是一个对象。那样我们会有更加直观的感受。

    html中的div元素

    因此,模板语言JSX本质上是一个JS对象的语法糖,这样能够更加方便我们使用,React同样也提供了如图类似的方式来创建一个JSX标签。

    const element = React.createElement(
      'h1',
      {className: 'greeting'},
      'Hello, world!'
    );
    
    // Note: this structure is simplified
    const element = {
      type: 'h1',
      props: {
        className: 'greeting',
        children: 'Hello, world!'
      }
    };
    

    也正因为如此,我们可以将JSX的标签对象一一映射到html的标签对象中。React就是借助这样的方式,帮助我们将JSX渲染到html的文档中。

    虚拟DOM

    正是因为JSX模板与html模板具有极为相似的特性,React可以借助这样的特性将JSX渲染到html中。但同时JSX与html又是不同的东西,因此我们可以简单粗暴的理解JSX就是虚拟DOM(render方法的执行结果)

    • 为什么要使用虚拟DOM

    DOM操作是一件成本很高的事情。
    如果你曾经有过页面性能优化的经验,一定会非常认可上面这句话。对于浏览器而言,每一次DOM操作都伴随着大量的计算,也正因为这样,当页面需要的操作不断变得复杂,每一次操作需要改动的元素变得更多时,浏览器的压力也会越来越大。

    大家可以在开发者工具中找到Rendering,勾选Paint flashing,这样就可以观察一个页面中元素的变动。浏览器会自动将被重绘的元素高亮显示出来。

    image.png

    如果你还没有了解过重绘回流的概念,那么说明你需要去补充一下基础知识了,这里不做深入讲解。

    那么虚拟DOM是如何帮助浏览器解决这个问题的呢?

    正常情况下,我们操作是直接改动html元素。每一次操作都会给浏览器增加更多的压力。
    而虚拟DOM可以帮我们收集短时间来的多次改动,汇总成为一次改动。这样对于浏览器来说,压力就减少了很多。如图。

    image.png

    这就是虚拟DOM的批处理能力。当然,计算的压力同样存在,但是因为虚拟DOM是JS计算的,因此这样的方式将本来属于浏览器的压力让JS来抗,而我们知道,JS的抗压能力是比浏览器优秀很多的。

    除了批处理能力,React中虚拟DOM的diff算法也是一大亮点,不过因为是初学阶段,这里不做深入讲解,也不建议大家太早的关注更深层次的知识。如果有兴趣的同学可以参考 https://zhuanlan.zhihu.com/p/20346379

    讲个题外话。

    最近发现了一个非常有意思的事情。

    一个小哥在某个群里问React到底比jQuery好在哪?可能很多人都会觉得这真的是一个很傻的问题,然而这个Java开发的小哥哥确实从心底认为jquery很好用,反而React学习成本很高,也用的不太舒服,所以它的好处到底在哪里,为什么大家都不用easyUI了?

    本来这是一件很小的事情,但是突然想到之前也遇到一个类似的事情,一个组里的小伙伴很疑惑为什么我们要用async/await?我试图解释了半天他也理解不了这个东西到底好在哪里。

    同样的事情还发生在我自己身上,为什么我们还要去费劲心思去学typescript?JS不是很好用嘛,干嘛要去学一个超集?当初ts刚出来的时候名声大噪,也动手去尝试了它的语法,真的感觉很麻烦,用起来加那么多限制条件,鼓捣了一下午也没觉得typescript到底好在哪里。于是放弃。正是因为认知的原因,傻乎乎的错过了好久typescript,直到3.0出来了,才在机缘巧合之下惊喜的发现哇靠,typescript简直就是神器,这才深深的感受到自己真的错过了太多。

    最近我特别留意了蛮多正在学习React的同学,或者已经学了很长时间甚至已经在工作中使用React的同学,发现很多人并没有发现React到底好在哪里。而大家关注的重点往往是,某个功能用React应该怎么实现,而不是React这样实现,好在哪里 ~,往往大家学习React的起因也不是因为已经感受到了React带来的好处才去学的。这样不同的认知与不同的学习源动力,自然会导致截然不同的学习效果。就连学习效率也会天差地别。

    正如我之前说过的,工作经验丰富<非工作年限>的开发人员更能够直接的体会到新东西(React/Typescript)等的优势,因为经历过前端开发刀耕火种的年代,自然就明白模块化组件化虚拟DOM等概念的重要意义,也就更容易把这些知识看得更加重要,视若珍宝。而初学者直接上来就接触这些概念,就常常只会把他们当成一个普通的知识点去学,然后遗忘,所以同样的东西在不同的人眼中就不一样。

    so, 经验丰富的前端开发者也不会有想要去嘲讽jQuery怎么这么难用,因为我们确确实实经过了一些事情,那个年代jQuery就是神器,尽管现阶段jquery已经慢慢被弃用,但是它在整个前端发展历程中的意义仍然无法替代。所以如果我们在技术群里偶尔看到某个程序员用着React/vue嘲讽jQuery的时候,就凭这一点就可以知道这个人一定资历尚浅,强行装逼。

    对于新手来说,要怎么去感受到React的好,我也没有什么切实可行的办法,只是告诉大家有这样的一个现象,因为我自己也深陷其中,也许到了某个阶段,自然就明悟了也说不定,我只能在文章里告诉大家这个东西很重要,但是总归没有自己切身体会来得深刻,毕竟搞得全文都是重点最终给人的感觉也只是全文都不是重点,所以学习这种东西,看努力,不过要走在行业前列,更看天赋,看领悟,看运气。大抵如此。

    相关文章

      网友评论

      • 何思源:“经历过前端开发刀耕火种的年代,自然就明白模块化组件化虚拟DOM等概念的重要意义,也就更容易把这些知识看得更加重要,视若珍宝。”这一点很到位。普通人只能看到知识本身,而高手能掌握知识的推演和演进,进而习得这个学科的核心思维。
        -----
        PS:我分享了一个快速克服写作畏难心理的方法,1分钟解决问题,亲测有效——《为什么你在简书写不出文章?》https://www.jianshu.com/p/f1e5c3b5ec20
      • 乐健君:支持:+1:
      • 币布斯:不明觉厉。支持点赞!欢迎回访
      • 霖山:学习!
      • 淡月6688:点赞支持!
      • 贝贝_d1cc:波神,啥时候可以写个ts的心得和技巧呗!向您学习学习,您的文章比较好懂,能把住关键点
      • Been101:期待后面的
      • 香草拿铁去冰不加糖:ts作为静态类型检查好处还是很多的,常见的就是智能提示,用起来真的是贼爽了。js这种根本没提示,记不住还要去翻文档。。:sob: :sob:
      • YC____:一次操作都会给浏览器增加更多的"眼力" 是不是 "压力" 啊
        这波能反杀:@柚子Ycc 对哦,写着急写错了 ~
      • 四爷在此:现在确实大项目都是ts ,写习惯了就好

      本文标题:React进阶(七)模板语言JSX与虚拟DOM

      本文链接:https://www.haomeiwen.com/subject/iydypftx.html