React Fragments – wrapper div终结者

栏目: 服务器 · 发布时间: 7年前

内容简介:hi,大家好,我是Ken,目前就职于GetStream.io,为用户提供个性化可定制的feed流服务。在过去的几个月里,我一直在开发Winds 2.0,一个开源的RSS阅读器和博客订阅应用。用Node.js, Electron, Redux and React开发,并且截止发文(2018-7-11),在Github上已经拥有了超过5000个star。如果你想看看整个项目,可以访问getstream.io/winds/,或者查看在Winds中,我们在一些特定的情况需要用到
React Fragments – wrapper div终结者
原文: getstream.io/blog/react-…

hi,大家好,我是Ken,目前就职于GetStream.io,为用户提供个性化可定制的feed流服务。

在过去的几个月里,我一直在开发Winds 2.0,一个开源的RSS阅读器和博客订阅应用。用Node.js, Electron, Redux and React开发,并且截止发文(2018-7-11),在Github上已经拥有了超过5000个star。如果你想看看整个项目,可以访问getstream.io/winds/,或者查看 github.com/GetStream/w… 上的源代码。

在Winds中,我们在一些特定的情况需要用到 React Fragments 。React Fragments是一个去年年底React v16.2.0发布的简洁小功能——它真的非常小,但是只要你了解了它,就可以在遇到一些非常具体的布局和样式情况时避开很多的麻烦。

Okay, 什么是React Fragment?

让我们稍微回顾一下 - 我确信每个React开发人员都会在他们职业生涯的某个阶段遇到这种情况(或者即将遇到):

class App extends React.Component {
    render() {
        return (
            <p>I would</p>
            <p>really like</p>
            <p>to render</p>
            <p>an array</p>
        );
    }
}
复制代码

看起来挺不错,但是当我们通过JSX转换器 运行它时......

Failed to compile.

    ./src/App.js
    Syntax error: Adjacent JSX elements must be wrapped in an enclosing tag (6:8)

        4 |         return (<p>I would
        5 |         </p>
        6 |         <p>
          |         ^
        7 |             really like
        8 |         </p>
        9 |         <p>
复制代码

JSX转换器 并不喜欢这样

这背后究竟发生了什么?JSX 把所有的 <div> s和 <MyComponent> s都放进 React.createElement() 中调用——当JSX转换器看到的(最外层如果)是多个元素而不是单个元素时,它就不知道到底要渲染哪个tag,更多: React.createElement in the React documentation

那么我们该怎么办?每次我们需要将几个元素包装在一起时都会这样做,——Pinky,用一个 div 包裹起来!就像web开发者从div被发明出来一直以来做的那样,在DOM中嵌套另外一个 div 也无伤大雅。

class App extends React.Component {
    render() {
        return (
            <div>
                <p>I would</p>
                <p>really like</p>
                <p>to render</p>
                <p>an array</p>
            </div>
        );
    }
}
复制代码

嗯,问题确实解决了。但事实证明,还有另一种方法可以在一个React组件里渲染出这一组内容——通过让 render 方法返回一个节点数组。

class App extends React.Component {
    render() {
        return [
            <p>I would</p>,
            <p>really like</p>,
            <p>to render</p>,
            <p>an array</p>
        ];
    }
}
复制代码

如果我们返回这样的一个元素数组,React将会转换并渲染它,而且没有 wrapper<div> (容器div)。 显得很整齐!

(还记得 JSX 转换器是如何将 <div><MyComponent> 转换并被 React.createElement() 调用的吗?在这种情况下,转换器只是将这些一个数组内的元素作为子元素直接附加到父元素,而不是当做没有父元素包含的元素数组。React v16.0.0引入了此功能。

因为这样,Dan Abramov和一些React团队的聪明人看到之后说,

“Okay,所以你可以用两种不同的方式来渲染一个元素数组 - 通过在DOM中引入一个额外的 <div> ,或者使用一些笨重的非JSX语法。这些都无法带来一个良好的编程体验。”

所以,在v16.2.0, React发布了React Fragments

okay,nowwhat’s a React Fragment?

这才是是使用React Fragment的正确方法:

class App extends React.Component {
    render() {
        return (
            <React.Fragment>
                <p>I would</p>
                <p>really like</p>
                <p>to render</p>
                <p>an array</p>
            </React.Fragment>
        );
    }
}
复制代码

看 - 我们写的就像 wrapper<div> 的方式一样,但在功能上与 数组渲染 方式相同,只不过是使用了看起来不错的JSX语法。 这样就可以将这些p元素呈现为数组,而不包含任何类型的 wrapper<div>

使用 React Fragments 还有另一种更简洁的语法:

class App extends React.Component {
    render() {
        return (
            <>
                <p>I would</p>
                <p>really like</p>
                <p>to render</p>
                <p>an array</p>
            </>
        );
    }
}
复制代码

可能在你的工具,linters,构建流程等等中,还没有起作用。但是发版说明中提到,这种语法的支持已经在开发中了,但是我注意到在 create-react-app 中还没有支持。

Okay,但什么时候才能使用它们呢?

在你需要摆脱 wrapper<div> 的时候。

就是这样 - 如果你发现自己处于一个 wrapper<div> 搞乱你的React组件布局的情况下,请使用React Fragment。

所以,就是当你想转换这个:

<div class="app">

    (...a bunch of other elements)

    <div> (my react component)
        <ComponentA></ComponentA>
        <ComponentB></ComponentB>
        <ComponentC></ComponentC>
    </div>
    
    (...a bunch more elements)

</div>
复制代码

到这样:

<div class="app">

    (...a bunch of other elements)

    <ComponentA></ComponentA>
    <ComponentB></ComponentB>
    <ComponentC></ComponentC>
    
    (...a bunch more elements)

</div>
复制代码

Example: 2×2 CSS grid

在Winds 2.0中,我们大量的使用了CSS Grid布局,这是博客或者RSS源网站很常见的布局。

React Fragments – wrapper div终结者

如果您还不了解CSS Grid布局,下面的代码可以让您快速了解CSS的布局

.grid {
    display: grid;
    grid-template-areas: 
        'topnav header' 
        'subnav content';
    grid-gap: 1em;
}
复制代码

Okay,让我们来解释一下:

  • 在左上角,我们有标志或者顶级导航位。
  • 在左下角,有子导航,可以响应全局和局部状态的一些变化,如“高亮”状态,tabs或折叠导航。
  • 在右侧,有一些需要在屏幕上显示的内容,在Winds中,有点类似于与文章列表或文章内容配对的RSS提要或文章标题。 这两个部分将是单一的React组件 - 两个组件的道具都会根据URL导航进行更改。

所有这些作用于全局的组件(redux + URL)和本地状态的交互都略有不同。 这个视图的结构使得我们有三个React组件互为兄弟:

<div className="grid">
    <TopNav />
    <SubNav />
    <ContentComponent />
</div>
复制代码

但是,我们希望实际呈现给页面的有四个元素:

<div class="grid">
    <div class="topnav"  />
    <div class="subnav"  />
    <div class="header"  />
    <div class="content" />
</div>
复制代码

这......就是没有React Fragments的问题。想象一下,我们正在创建2×2网格视图的两个右侧部分的组件,即 ContentComponent

class ContentComponent extends React.Component {
    render() {
        return (
            <div>
                <div className="header"/>
                <div className="content"/>
            </div>
        );
    }
}
复制代码

如果我们将渲染的内容包装在 <div> 中,那么我们将获得以下渲染输出:

<div class="grid">
    <div class="topnav"  />
    <div class="subnav"  />
    <div>
        <div class="header"  />
        <div class="content" />
    </div>
</div>
复制代码

这不起作用 - 它还会搞乱CSS的grid布局。 从浏览器的角度来看,网格中只有3个项目,其中一个还没有 grid-area 的样式。

还记得我们应该使用React Fragments吗? 每当我们想要摆脱 wrapper<div> 。 如果我们将 ContentComponent 包装在React Fragments中而不是 wrapper<div> 中:

class ContentComponent extends React.Component {
    render() {
        return (
            <React.Fragment>
                <div className="header"/>
                <div className="content"/>
            </React.Fragment>
        );
    }
}
复制代码

然后我们将看到另外一种渲染输出:

<div class="grid">
    <div class="topnav"  />
    <div class="subnav"  />
    <div class="header"  />
    <div class="content" />
</div>
复制代码

这就符合我们的预期了! 没有 wrapper<div> ,我们的4个元素从3个React组件渲染,浏览器看到所有元素具有正确的 grid area 样式,并且我们的CSS grid正确呈现。

很整齐! 现在怎么办?

React Fragments不是近期React版本中发布的最重要的功能,但它们在某些特定情况下非常有用。 只要了解React Fragments的存在,您就可以节省数小时的谷歌引起的头痛。这可以让我们以JSX-y方式呈现元素或者组件数组,这可以解决大量的表格、列表和CSSgrid的布局和样式问题!


以上所述就是小编给大家介绍的《React Fragments – wrapper div终结者》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Design for Hackers

Design for Hackers

David Kadavy / Wiley / 2011-10-18 / USD 39.99

Discover the techniques behind beautiful design?by deconstructing designs to understand them The term ?hacker? has been redefined to consist of anyone who has an insatiable curiosity as to how thin......一起来看看 《Design for Hackers》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具