好久没有用个人站了)刚才买了个新的域名.xyz,首年只要8块钱,明年可以再换一个!(为什么域名连续包年那么贵啊QAQ)回正文——最近肝毕设的进步神速,每天都Get了不少知识,打算每天把解决的问题记录一下!


切入正题。

React的组件类型

React 中包括两种组件,类组件和函数组件,形如:

class child extends React.Component {
    constructor(props){
        super(props);
        this.state = {
            myIndex : 1
        }
    }
}
import React, { useState } from "react";
const FCchild: React.FC = (props) =>{
    const [index,setIndex] = useState(1);
}

组件的State

这两种组件在创建时都有 props 属性,不同是 Component 组件还需要使用 this.props 来访问,而 Function 组件可以直接访问 props 。Component函数的 State 需要调用 this.setState() 函数,而 Function 组件调用该值在 useState 时的赋值函数 setIndex() 直接赋值。

这里有一个可能遇到的BUG,就是在函数组件中的类似 setIndex() 对简单值是适用的,但是对于 Object 的处理不像 this.setState() 函数会自动合并对象,如果你只修改了一个值,使用 {index:1} 的包装会将对象设置成只有这一个属性的对象,而不是修改这个属性(有点像MongoDB的修改逻辑)。因此对于 setObject() 只修改特定属性的情况只需要简单处理为 setObject({...FormerData,...ModifyData}) ,JS里形如这样的合并对象时的语法,处理冲突 key 时后面的对象会替换前面的对象。

传递参数

为什么先说State这个东西,因为这些值是每个组件内部的东西,组件之间通信就是把自己的 State 共享给另一个组件的情况,这种情况很多种,父To子、子To子、子To父,但是其核心都是传递这个State。由于每个 React 的组件最后都需要 return 一个 HTML,在组件的 HTML 中增加的属性就会成为组件的 props。React 主要使用这种方法进行参数传递。

刚才说过了两种组件的state和setState的方式,React根据这些方法来传递参数。先说结论:

  • 如果子组件需要调用父组件的参数,就在props上加父组件的state值;
  • 如果父组件需要调用子组件的参数,就在props上加父组件的setState方法,父组件来记录这个值;
  • 如果子组件需要调用子组件的参数,就在props上加父组件的state和setState,父组件来记录这个值;

这里仅局限于了传递参数的问题,但其实这个方法是广泛的。运用父组件做中介人,所有数据都存在父组件上,这样也比较方便管理(可能是我现在的拙见QWQ) 。

下面用毕设里Main页面的return做个例子。

return (
        <Card>
            <Layout>
            <Sider width={500}>
            <RenderSelecter />
                    <Divider dashed />
                    <SrcTable 
                        rowSelection={rowSelection}
                        onClickJumpToVex={onClickJumpToVex}
                        data={data}
                        setData={setData}
                        setSrc={setSrc}
                        initSelectedKey={initSelectedKey}
                        />
                    <Divider dashed />
            </Sider>
                <Content>
                    <Row>
                        <Col span={20}>
                        <ToolsHeader handleToolsChange={handleToolsChange}/>
                        </Col>
                        <Col span={4}>
                            <LoadAndSave />
                        </Col>
                    </Row>
                    <Divider dashed />
                    <Row>
                        <Image
                            selectedTool={selectedTool}
                            setData={setData}
                            initSelectedKey={initSelectedKey}
                            src={src}
                            setSrc={setSrc}
                        />
                    </Row>
                </Content>
            </Layout>
            
            <Row>
                <TreeVisualization
                    data={data}
                    onClickJumpToVex={onClickJumpToVex}
                    selectedMapKey={selectedMapKey}
                    selectedVertexKey={selectedVertexKey}
                />
            </Row>

        </Card>
)

我把涉及通信的方法都放在了父组件,这样能在父组件获得所有子组件的信息,也能方便信息之间互相同步。

渲染更新

有一些组件在props刷新时会自动更新,有一些则需要手动更新。

componentDidMount() 函数是在 HTML 元素挂载之后调用的,我利用它做了一些 d3 绘制的工作,但是我这个组件是自制的,按照 props.data 绘制出来的时候并不会自动重新绘制。

componentDidUpdate() 这个函数中,这个时候 props 出现了变化,利用这个方式可以进一步判断根据元件内存一份 state.data ,和父组件的 props.data 进行对比,如果出现变化则渲染。这样也可以防止过度更新。

0 条评论

发表评论

Avatar placeholder