• taro3.x父组件更新,子组件同步更新问题解决


    子组件sandCommon:

    import React, { useEffect, useState } from 'react'
    import Taro from '@tarojs/taro'
    import {
        View,
        MovableArea,
        MovableView,
        Image,
        Text,
        Label,
        CheckboxGroup,
        Checkbox
    } from '@tarojs/components'
    import classnames from 'classnames'
    import { includes, find } from 'lodash'
    
    import api from '@services/api'
    import app from '@services/request'
    import './common.scss'
    
    interface ISandState {
        value: string
        text: string
        checked: boolean
    }
    
    const INIT_SAND_STATE: ISandState[] = [
        {
            value: '1',
            text: '在售',
            checked: true
        },
        {
            value: '2',
            text: '待售',
            checked: true
        },
        {
            value: '3',
            text: '售完',
            checked: true
        }
    ]
    
    interface IShowState {
        show: boolean
        text: string
    }
    
    const INIT_SAND_DATA = {
        sandBuilding: []
    }
    
    const INIT_SHOW_STATE = { show: true, text: '收起' }
    
    interface IProps {
        houseId: string,
        outerWidth?: number,
        outerHeight: number,
        currentBuilding?: any,
        setCurrentBuilding: (any) => void,
        updateSandBuilding: (any) => void
    }
    
    const SandCommon = (props: IProps) => {
        const { houseId, outerHeight, currentBuilding = {} } = props
        const [movableView, setMovableView] = useState<any>({})
        const [showState, setShowState] = useState<IShowState>(INIT_SHOW_STATE)
        const [sandState, setSandState] = useState<ISandState[]>(INIT_SAND_STATE)
        const [sandData, setSandData] = useState<any>(INIT_SAND_DATA)
        const [sandBuilding, setSandBuilding] = useState<any>(INIT_SAND_DATA.sandBuilding)
        const [current, setCurrent] = useState<any>({})
        const safeArea = Taro.getSystemInfoSync().safeArea
        const outerWidth = props.outerWidth ? props.outerWidth : safeArea.width
    
        useEffect(() => {
            fetchSand()
        }, [houseId])
    
        useEffect(() => {
            setCurrent(currentBuilding)
        }, [currentBuilding])
    
        const handleSandImageLoad = (e: any) => {
            setMovableView({
                 e.detail.width,
                height: e.detail.height
            })
        }
    
        const fetchSand = () => {
            app.request({
                url: app.areaApiUrl(api.getHouseSand),
                data: {
                    id: houseId
                }
            }).then((result: any) => {
                setSandData(result)
                showSandBuilding(INIT_SAND_STATE, result.sandBuilding)
                props.updateSandBuilding(result.sandBuilding)
            })
        }
    
        const toggleShowState = () => {
            setShowState({
                show: !showState.show,
                text: showState.show ? '展开' : '收起'
            })
        }
    
        const handleCheckboxChange = (e: any) => {
            const values = e.detail.value
            for (const item of sandState) {
                if (includes(values, item.value)) {
                    item.checked = true
                } else {
                    item.checked = false
                }
            }
            setSandState(sandState)
            showSandBuilding(sandState, sandData.sandBuilding)
        }
    
        const showSandBuilding = (sandState, allSandBUilding) => {
            let sandBuilding: any[] = []
            for (const item of allSandBUilding) {
                const target = find(sandState, { value: item.sale_status })
                if (target.checked) {
                    sandBuilding.push(item)
                }
            }
            setSandBuilding(sandBuilding)
        }
    
        const switchCurrent = (item: any) => {
            props.setCurrentBuilding(item)
        }
    
        return (
            <View className="sand-card" style={{  '100%', height: outerHeight }}>
                <MovableArea className="sand-area">
                    <MovableView
                        x={(outerWidth - movableView.width) / 2}
                        y={(outerHeight - movableView.height) / 2}
                        style={movableView}
                        className="sand-view"
                        direction="all"
                        animation={false}
                    >
                        <Image
                            className="sand-image"
                            src={sandData.fang_sand_pic}
                            onLoad={handleSandImageLoad}
                        />
                        {
                            sandBuilding.map((item: any, index: number) => (
                                <View
                                    key={index}
                                    style={item.style}
                                    className={classnames('sand-item', `sale-status-${item.sale_status}`, current.id === item.id && 'actived')}
                                    onClick={() => switchCurrent(item)}
                                >
                                    <Text>{item.name}</Text>
                                    <Text className="triangle-down"></Text>
                                </View>
                            ))
                        }
                    </MovableView>
                </MovableArea>
                <View className="sand-state">
                    <CheckboxGroup
                        onChange={handleCheckboxChange}
                        className={classnames('sand-state-box', !showState.show && 'hide')}
                    >
                        {
                            sandState.map((item: any, index: any) => (
                                <Label
                                    key={index}
                                    for={index}
                                    className={classnames('check-label', `sale-status-${item.value}`)}
                                >
                                    <Checkbox
                                        id={index}
                                        className="check-box"
                                        value={item.value}
                                        checked={item.checked}
                                    >
                                    </Checkbox>
                                    <Text className="check-text">{item.text}</Text>
                                </Label>
                            ))
                        }
                    </CheckboxGroup>
                    <View className="sand-state-btn" onClick={toggleShowState}>{showState.text}</View>
                </View>
            </View>
        )
    }
    export default SandCommon

    使用useMemo + useEffect监听props更新的字段:

     useEffect(() => {
            fetchSand()
        }, [houseId])监听houseId发生变化重新渲染
    const getSandCommonComponent = useMemo(() => {
            return (
                <SandCommon
                    houseId={houseData.id}
                    outerHeight={200}
                    currentBuilding={{}}
                    setCurrentBuilding={toHouseSand}
                    updateSandBuilding={() => { }}
                />
            )
        }, [houseData.id])
    const { currentBuilding = {}} = props
    
        useEffect(() => {
            setCurrent(currentBuilding)
        }, [currentBuilding])监听currentBuilding发生变化重新渲染
    
    

    父组件HouseSand:

    import React, { useEffect, useMemo, useState } from 'react'
    import Taro from '@tarojs/taro'
    import {
        View,
        Text,
        ScrollView
    } from '@tarojs/components'
    import classnames from 'classnames'
    
    import api from '@services/api'
    import app from '@services/request'
    import NavBar from '@components/navbar'
    import SandCommon from '@house/pages/new/sand/common'
    import '@styles/common/house.scss'
    import '@house/styles/common.scss'
    import './index.scss'
    
    const INIT_SAND_BUILDING = []
    
    const HouseSand = () => {
        const INTI_CURRENT = { id: '167' }
        const [sandBuilding, setSandBuilding] = useState<any>(INIT_SAND_BUILDING)
        const [roomData, setRoomData] = useState<any[]>([])
        const [current, setCurrent] = useState<any>(INTI_CURRENT)
    
        useEffect(() => {
            fetchRoom()
        }, [current.id])
    
        const safeArea = Taro.getSystemInfoSync().safeArea
    
        const fetchRoom = () => {
            app.request({
                url: app.areaApiUrl(api.getHouseSandRoom),
                data: {
                    id: current.id
                }
            }).then((result: any) => {
                setRoomData(result)
            })
        }
    
        const handleRoomCheck = (item: any) => {
            console.log(item)
        }
    
        const getSandCommonComponent = useMemo(() => {
            return (
                <SandCommon
                    outerWidth={safeArea.width}
                    outerHeight={300}
                    currentBuilding={current}
                    setCurrentBuilding={(currentBuilding) => setCurrent(currentBuilding)}
                    updateSandBuilding={(sandBuilding) => setSandBuilding(sandBuilding)}
                ></SandCommon>
            )
        }, [current])
    
        return (
            <View className="sand">
                <NavBar title="楼盘沙盘图"></NavBar>
                <View className="sand-wrapper">
                    {getSandCommonComponent}
                    <View className="sand-content">
                        <View className="sand-info">
                            <ScrollView
                                className="sand-info-header"
                                scrollX
                                scrollIntoView={`view_${current.id}`}
                            >
                                <View className="sand-list">
                                    {
                                        sandBuilding.map((item: any, index: number) => (
                                            <View
                                                key={index}
                                                id={`view_${item.id}`}
                                                className={classnames('sand-item', current.id === item.id && 'actived')}
                                                onClick={() => setCurrent(item)}
                                            >{item.name}
                                            </View>
                                        ))
                                    }
                                </View>
                            </ScrollView>
                            <View className="sand-info-detail">
                                <View className="sand-info-detail-content view-content">
                                    <View className="detail-item">
                                        <Text className="label">规划户数:</Text>
                                        <Text>{current.plan_households}</Text>
                                    </View>
                                    <View className="detail-item">
                                        <Text className="label">楼层:</Text>
                                        <Text>{current.storey_height}</Text>
                                    </View>
                                    <View className="detail-item">
                                        <Text className="label">梯户配比:</Text>
                                        <Text>{current.elevator_number}梯{current.elevator_households}户</Text>
                                    </View>
                                </View>
                                <View className="sand-info-detail-room mt20">
                                    <View className="room-header">
                                        <Text className="title">户型</Text>
                                    </View>
                                    <View className="room-list">
                                        {
                                            roomData.length > 0 ?
                                                roomData.map((item: any, index: number) => {
                                                    const itemData = item.fangHouseBuildingRoom
                                                    return (
                                                        <View key={index} className="room-item">
                                                            <Text className="item-text">{itemData.name}</Text>
                                                            <Text className="item-text">{itemData.room}室{itemData.office}厅{itemData.toilet}卫</Text>
                                                            <Text className="item-text">{itemData.building_area}㎡</Text>
                                                            <Text className="item-btn" onClick={() => handleRoomCheck(itemData)}>查看</Text>
                                                        </View>
                                                    )
                                                }) :
                                                <View className="room-item">
                                                    <Text className="item-text">暂无数据</Text>
                                                </View>
                                        }
                                    </View>
                                </View>
                            </View>
                        </View>
                    </View>
                </View>
            </View>
        )
    }
    
    export default HouseSand

    当current发生变化后更新子组件:

        const getSandCommonComponent = useMemo(() => {
            return (
                <SandCommon
                    outerWidth={safeArea.width}
                    outerHeight={300}
                    currentBuilding={current}
                    setCurrentBuilding={(currentBuilding) => setCurrent(currentBuilding)}
                    updateSandBuilding={(sandBuilding) => setSandBuilding(sandBuilding)}
                ></SandCommon>
            )
        }, [current])

    子组件样式:

    .sand-card {
        position: relative;
    
        .sand-state {
            display: flex;
            justify-content: center;
            align-items: center;
            position: absolute;
            right: 30px;
            bottom: 30px;
    
            &-box {
                flex: auto;
                height: 60px;
                line-height: 60px;
                font-size: $font-basic;
                padding: 0 40px 0 20px;
                margin-right: -30px;
                border-radius: 30px;
                background-color: rgba($color: $white, $alpha: 0.9);
                transition: 0.3s;
    
                &.hide {
                    width: 0;
                    padding: 0;
                    overflow: hidden;
                }
    
                .check-label {
                    margin: 0 10px;
                    padding: 2px 16px;
                    border-radius: 20px;
                    .check-box {
                        vertical-align: 2px;
                        .wx-checkbox-input {
                            width: 30px;
                            height: 30px;
                        }
                    }
                    .check-text {
                        color: $white;
                    }
                }
            }
    
            &-btn {
                width: 90px;
                height: 90px;
                line-height: 90px;
                font-size: $font-basic;
                border-radius: 50%;
                text-align: center;
                background-color: $white;
                color: $title-color;
            }
        }
    
        .sand-area {
            width: 100%;
            height: 100%;
            overflow: hidden;
            background-color: $bg-color;
    
            .sand-view {
                .sand-image {
                    width: 100%;
                    height: 100%;
                }
    
                .sand-item {
                    position: absolute;
                    font-size: $font-basic;
                    padding: 10px 16px;
                    border-radius: $border-radius-base;
                    color: $white;
    
                    .triangle-down {
                        position: absolute;
                        top: 54px;
                        left: 16px;
                        display: block;
                        border-style: solid;
                        border-width: 16px 16px 0;
                    }
    
                    &.actived {
                        background-color: $primary-color;
                        color: $white;
    
                        .triangle-down {
                            border-color: $primary-color transparent transparent;
                        }
                    }
                }
            }
        }
    }
  • 相关阅读:
    HTML+CSS笔记 CSS进阶续集
    HTML+CSS笔记 CSS进阶
    HTML+CSS笔记 CSS入门续集
    HTML+CSS笔记 CSS入门
    test
    Python Paramiko模块安装和使用
    RedHat升级Python到2.7.6
    python数据库操作常用功能使用详解(创建表/插入数据/获取数据)
    5、使用EF对后台SysSample数据增删改查
    4、创建SQL数据库,添加EF实体数据模型
  • 原文地址:https://www.cnblogs.com/Nyan-Workflow-FC/p/13744040.html
Copyright © 2020-2023  润新知