在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 問答/Java  HTML/ 遍歷元素集合并用addEventListener綁定事件,為什么只有最后一個元素

遍歷元素集合并用addEventListener綁定事件,為什么只有最后一個元素能執(zhí)行方法?

直接貼效果圖及代碼
上面的父組件,下面的是子組件。
照道理講,this.ripple.init(this[`item_${i}`])會把這兩個元素分別加上點擊事件,
然后點擊的時候分別響應,但為什么無論點哪個元素,只有最后一個元素有效果?

圖片描述

import React from 'react'

import Ripple from '../../component/Ripple/Ripple'

export default class Ripple_demo extends React.Component {
    constructor(props) {
        super(props)
        this.state = {}
    }

    componentDidMount = () => {
        for(let i = 0; i < this.dataSource.length; i++){
            this.ripple.init(this[`item_${i}`]);
        }
    }

    dataSource = [
        {label: 'test1'},
        {label: 'test2'},
    ];
    
    render() {
        return (
            <div className='Ripple_demo'>
                {
                    this.dataSource.map((item, i) => {
                        return (
                            <div style={{overflow: 'hidden', position: 'relative'}}>
                                <div ref={ref => this[`item_${i}`] = ref} style={{background: '#F96', height: 200}}>{item.label}</div>
                                <Ripple ref={ref => this.ripple = ref} wrapWidth={375} />
                            </div>
                        )
                    })
                }
            </div>
        )
    }
}
import React from 'react'

import './css/Ripple.css'

/* 點擊波紋 */
export default class Ripple extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            display: false, // 動畫是否開始
            left: 0,
            top: 0,
            opacity: 0,
        };
    }

    componentDidMount = () => {}

    init = element => {
        // element.addEventListener('transitionend', e => {
        //     this.setState({display: false});
        // }, false);
        
        element.addEventListener('click', e => {
            const {offsetX, offsetY} = e;
            const {wrapWidth = 150} = this.props;

            // 開始動畫
            this.setState({
                scale: wrapWidth,
                left: offsetX,
                top: offsetY,
                opacity: 1,
                display: true,
            }, () => {
                // 波紋淡出
                this.setState({opacity: 0});
                // 動畫結束后移除樣式 mark
                setTimeout(() => {
                    this.setState({display: false});
                }, 1000);
            });
        }, false);
    }

    render() {
        let {wrapWidth = 150} = this.props;
        let {display, scale, opacity, left, top} = this.state;

        // let transition = display ? 'transform 1s cubic-bezier(0.250, 0.460, 0.450, 0.940), opacity 1s cubic-bezier(0.250, 0.460, 0.450, 0.940)' : 'opacity .7s cubic-bezier(0.250, 0.460, 0.450, 0.940)';
        let style = {transform: `scale(${scale})`, opacity , left, top, width: 2, height: 2};

        return (
            <div className='Ripple' style={display ? style : null} />
        )
    }
}

好吧,自己解決了,但不知道是為什么
把render里的代碼改成下面這些就行了,就是init和遍歷放在一起而不是在componentDidMount中再遍歷一次
可能是因為對閉包的理解不夠深刻,componentDidMount遍歷元素綁定事件時始終綁定在最后一個元素上
先更著,容我仔細看看閉包再來結案

render() {
        return (
            <div className='Ripple_demo'>
                {
                    this.dataSource.map((item, i) => {
                        return (
                            <div style={{overflow: 'hidden', position: 'relative'}}>
                                <div ref={ref => this[`item_${i}`] = ref} style={{background: '#F96', height: 200}}>{item.label}</div>
                                <Ripple ref={ref => ref.init(this[`item_${i}`])} wrapWidth={document.body.clientWidth} />
                            </div>
                        )
                    })
                }
            </div>
        )
    }
回答
編輯回答
陪妳哭

你直接在<Ripple ref={ref => this.ripple = ref} wrapWidth={375} />上添加onClick事件就可以了。
然后在子組件中實現(xiàn)這個事件。這樣就自然區(qū)分開了。沒必要再通過addEventListener添加了。

2018年7月2日 01:26