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


followWinter
1.5k 声望82 粉丝

暂时没有