React入門0x014: Fragment

0x001 引出問題

讓我們先來看一個栗子:

class App extends React.Component {
    render() {
        return (
            <h1></h1>
            <h1></h1>
        )
    }
}

ReactDom.render(
    <App theme='dark'/>,
    document.getElementById('app')
)

上面的栗子中的render返回了兩個同級h1,編譯的時候將會看到一個報錯:

SyntaxError: index.js: Adjacent JSX elements must be wrapped in an enclosing tag.

jsx只能返回一個閉合的tag,比如

class App extends React.Component {
    render() {
        return <hr/>
    }
}

或者:

class App extends React.Component {
    render() {
        return 'helloworld'
    }
}

又或者:

class App extends React.Component {
    render() {
        return <div>
            <h1>title</h1>
            <p>content</p>
        </div>
    }
}

總的來說,只能返回一個根元素,但是實際中總會遇到奇特的場景,希望可以返回多個,栗子:

class Td extends React.Component {
    render() {
        return (
            <td>1</td>
            <td>2</td>
        )
    }
}

class Table extends React.Component {
    render() {
        return <table>
            <tr>
                <Td/>
            </tr>
        </table>
    }
}

很明顯,會有語法錯誤,修復:

class Td extends React.Component {
    render() {
        return (<div>
            <td>1</td>
            <td>2</td>
        </div>)
    }
}

查看效果:

clipboard.png
多了一級,那真的沒辦法了嗎?當然有了,就是Fragment

0x002 Fragment

class Td extends React.Component {
    render() {
        return (<>
            <td>1</td>
            <td>2</td>
        </>)
    }
}

將跟元素替換成<>...</>就行啦

clipboard.png

當然,這是一個縮寫,完整的寫法應該是:

class Td extends React.Component {
    render() {
        return (<React.Fragment>
            <td>1</td>
            <td>2</td>
        </React.Fragment>)
    }
}
  • <React.Fragment></React.Fragment>效果和<></>是一致的但是有一點區別就是React.Fragment是可以有屬性的,而<></>無法擁有屬性。
  • <React.Fragment></React.Fragment> 只有一個屬性,那就是key

0x003 栗子

可展開收縮的表格

  • 源碼
class Tr extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            extend: false
        }
    }

    render() {
        const {extend} = this.state
        const {data} = this.props
        return (
            <>
                <tr>
                    <td onClick={() => this.handleExtend()}>
                        <button className='btn btn-primary'>{extend ? '展開' : '收起'}</button>
                    </td>
                    <td>{data.name}</td>
                    <td>{data.age}</td>
                </tr>
                {
                    extend ? <tr>
                        <td colSpan='3'>{data.detail}</td>
                    </tr> : null
                }
            </>
        );
    }

    handleExtend() {
        this.setState({
            extend: !this.state.extend
        })
    }
}

class Table extends React.Component {
    constructor() {
        super()
        this.state = {
            users: [
                {
                    name: '張三',
                    age: '11',
                    detail: '我很開心'
                },
                {
                    name: '李四',
                    age: '22',
                    detail: '我也很開心'
                },
                {
                    name: '王五',
                    age: '33',
                    detail: '我比張三和李四更開心'
                }
            ]
        }
    }

    render() {
        const {users} = this.state
        return (
            <table className='table'>
                {
                    users.map((u, i) => <Tr data={u} key={i}/>)
                }
            </table>
        );
    }
}

ReactDom.render(
    <Table/>,
    document.getElementById('app')
  • 效果

圖片描述

  • dom

clipboard.png

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章