如何在react.js中获取li元素的'e.key'?

时间:2017-07-18 09:31:21

标签: javascript reactjs

如何在react.js中获取li元素的'e.key'?

  

我无法获得事件目标e.key,这有什么问题?

任何人都可以帮我解决这个问题吗?

在线游戏链接!

https://jscomplete.com/repl

// import React, {Component} from 'react';
// import PropTypes from 'prop-types';

class RMT extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            data: this.props.data || []
        };
    }
    // 递归调用
    markNode = (data) => {
        let nodes;
        if (Object.prototype.toString.call(data) == "[object Array]") {
            nodes = data.map(
                (item) => {
                    let node = (
                        <li
                            key={this.count++}
                            style={{color: 'red'}}
                            onClick={(e) => this.props.onClick(e)}
                            >
                            <span>{item.text}</span>
                        </li>
                    );
                    if (item.children && item.children.length) {
                        node = (
                            <li
                                key={this.count++}
                                style={{color: 'green', marginLeft: '10px'}}
                                onClick={(e) => this.props.onClick(e)}
                                >
                                <span>{item.text}</span>
                                {this.markNode(item.children)}
                            </li>
                        );
                    }
                    return node;
                }
            );
        }
        return (
            <ul style={{border: '1px solid red'}} onClick={this.props.onClick}>
                {nodes}
            </ul>
        );
    };
    render() {
        this.count = 0;
        return(
            this.markNode(this.state.data)
        );
    }
}

export {RMT};
export default RMT;

class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            // 
        };
    }
    onClick = (e) => {
        // 阻止事件的默认行为,防止事件冒泡!
        e.preventDefault();
        e.stopPropagation();
        // alert(`e`, e.key);
        console.log('e.key', e.key);
        console.log('e.text', e.text);
        console.log('e.innerHTML', e.innerHTML);
        console.log('e.innerText', e.innerText);
    };
    render () {
        const datas = [
            {
                text: 'root',
                children: [
                    {
                        text: 'chlid1',
                        children: [
                            {
                                text: 'chlid3'
                            }
                        ]
                    }
                ]
            }
        ];
        return (
            <div>
                <RMT data={datas} onClick={this.onClick}/>
            </div>
        );
    }
}

export default App;

ReactDOM.render(
    <div>
        <App />
    </div>
    , mountNode
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

4 个答案:

答案 0 :(得分:1)

我认为你无法在反应中访问key属性。如果您需要传递该值,则可以使用其他道具名称,例如indexKey或其他任何内容。

答案 1 :(得分:1)

这里需要注意的一些事情,希望能指出正确的方向:

1)你提到的key含糊不清。在React中,组件key无法公开访问,这是设计使然。但是,当您记录e.key时,您可能正在尝试访问事件本身的键盘键 - 但这不会出现在鼠标事件上,只会出现键盘事件。

2)注销值的onClick处理程序的行为方式与标准DOM事件完全不同,事件实际上来自React自己的内部综合事件系统,并且你的处理程序(即this)是词法绑定的类,而不是标准DOM事件,其中作用域是触发它的元素(你的App.onClick由箭头函数词法绑定到App)的实例

你仍然可以访问被包装的事件,以及由Reacts自己的合成事件属性引起它的DOM节点......

onClick = (e) => { // types are... e: SyntheticEvent<MouseEvent> , this: App
    e.preventDefault()
    e.stopPropagation()
    // you can access the native DOM event this wraps via the `nativeEvent` to call methods or access event properties that React does not proxy. This is not recommended though as React has done a lot of work to consolidate any browser quirks, which accessing native event like this would negate, so you'ld have to handle that yourself
    e.nativeEvent.stopImmediatePropagation()

    // access the actual DOM node that triggered the event via `target`
    console.log(e.target.innerHTML);
    // access the DOM node that the event is currently the current event phase is acting upon via `currentTarget`
    console.log(e.target.innerHTML);

    // if you REALLY need some data to be available via the DOM itself, then you can it via the DOM node's `data` attributes (ie data-nic-cage={someString}, and access it like so...
    console.log(e.target.dataset.nicCage)
}

3)分配key时,您正在递增this.count,这意味着后续渲染中没有2个密钥相同。你的渲染函数是不纯的,并且会导致React无法将后续渲染的子组件与当前子组件协调,而是总是卸载然后重新安装新的组件会导致不必要的重新渲染并丢失子状态 - 损害性能,并可能引入错误儿童组成部分。除非它对你有更大的意义(即强制恢复),你可以只传递地图索引(尽管稳定的id会更好,但我不能在item看到任何合适的内容)。

data.map((item, i) => <li key={i} /*other props*/ />)

答案 2 :(得分:0)

您需要在App组件

中绑定您的函数onClick
    class App extends React.Component {
        constructor(props) {
            super(props);
            this.state = {
                // 
            };
            this.onClick = this.onClick.bind(this);
        }

答案 3 :(得分:0)

这是一个演示,表明在react.js您无法直接访问e.key

                <Message
                    key={index}
                    indexkey={index}
                    text={message.text}
                    color={message.color}
                    xyzClick={this.props.xyzClick}
                />
                this.props.indexkey = {this.props.indexkey}
  

在线游乐场!

https://jscomplete.com/repl

enter image description here

// props is an object!


// message.text => array of objects
class MessageList extends React.Component {
    getChildren = () => {
        //
    }
    render() {
        const children = this.props.messages.map(
            (message, index) => {
                //console.log(`message = `, message);
            		console.log(`index = `, index);
                //console.log(`typeof index = `, typeof index);
                let xindex = 'id_' + index; 
                console.log(`xindex = `, xindex);
                //console.log(`typeof xindex = `, typeof xindex);
                return(
                    <Message
                        key={index}
                        text={message.text}
                        color={message.color}
                        xyzClick={this.props.xyzClick}
                    />
                );
            }
        );
        const styles = {
        		css1: {
            		color: 'red'
            },
            css2: {
            		color: '#0f0'
            }
        }
      	return(
            <div>
                children = {children}
                <hr />
                <div>
                    BAD: <br />
                    {/* this.props = {this.props} */}
                    <div style={styles.css1}>
                        this.props.children = {this.props.color}
                    </div>
                    {/* this.props.arr = {this.props.arr} */}
                    {/* this.props.obj = {this.props.obj} */}
                    <br />
                    <p style={styles.css2}>
                        Object Error, need using map items to item
                    </p>
                </div>
            </div>
        );
    }
}

// text={message.text} => message object
class Message extends React.Component {
    render() {
    		//console.log(`this.props.text = `, this.props.text);
        //console.log(`this.props.key= `, this.props.key);
        let style = `
        		color: red;
            font-size: 23px;
        `;
        if(this.props.key === undefined){
        		//alert(`smg!`);
            console.log(`%c this.props.key= \n`, style, this.props.key);
        }
        return (
            <div>
                <hr />
                this.props.key = {this.props.key}
                <br />
                this.props.text = {this.props.text}
                <br />
                this.props.color = <span style={{backgroundColor: this.props.color}}>{this.props.color}</span>
                <br />
                <Button color={this.props.color} xyzClick={this.props.xyzClick}>
                    <span style={{color: '#fff'}}>Delete</span>
                </Button>
            </div>
        );
    }
}

// props.children === <span style={{color: '#fff'}}>Delete</span> ??? 
class Button extends React.Component {
    render() {
        return (
            <button
                style={{background: this.props.color}} 
                onClick={(e) => this.props.xyzClick(e)} 
                >
                {this.props.children}
            </button>
        );
    }
}




const text = [
    {
    text: "text 1",
    color: "red"
    },
    {
    text: "text 2",
    color: "blue"
    },
    {
    text: "text 3",
    color: "grey"
    },
    {
    text: "text 4",
    color: "green"
    },
    {
    text: "text 5",
    color: "#f0f"
    }
];
const color = "green";
const ArrayTest = [1, 2, 3];
const ObjectTest = {"key": "value"};

class App extends React.Component{
    constructor(props){
        super(props);
        this.state  = {
            showSate: false
        };
    }
    setModalVisible = (value) => {
        console.log(`showSate`, this.state.showSate);
        console.log(`value`, value);
        this.setState({
            showSate: value
        });
        // 状态更新可能是异步的
        setTimeout(() => {
        		console.log(`showSate`, this.state.showSate);
        });
    };
  	XC = (e) => {
      	let m = e.toString();
      	console.log(e, m);
      	return alert(`e.toString(); =\n`, m);
  	};
  render(){
      return(
          <div>
               <div>
                   <button onClick={() => console.log(`smg`)}>
                       onClick
                   </button>
                   <button onClick={()=>this.setModalVisible(true)}>
                       showModal{this.state.showSate}
                   </button>
               </div>
               <MessageList
                   messages={text}
                   color={color}
                   arr={ArrayTest}
                   obj={ObjectTest}
                   xyzClick={this.XC}/>
          </div>
      );
    }
};



export default App;

ReactDOM.render(
    <App />,
    mountNode
);



/********************************* new version *************************************/

// props is an object!


// message.text => array of objects
class MessageList extends React.Component {
    getChildren = () => {
        //
    }
    render() {
        const children = this.props.messages.map(
            (message, index) => {
                //console.log(`message = `, message);
            		console.log(`index = `, index);
                //console.log(`typeof index = `, typeof index);
                let xindex = 'id_' + index; 
                console.log(`xindex = `, xindex);
                //console.log(`typeof xindex = `, typeof xindex);
                return(
                    <Message
                        key={index}
                        indexkey={index}
                        text={message.text}
                        color={message.color}
                        xyzClick={this.props.xyzClick}
                    />
                );
            }
        );
        const styles = {
        		css1: {
            		color: 'red'
            },
            css2: {
            		color: '#0f0'
            }
        }
      	return(
            <div>
                children = {children}
                <hr />
                <div>
                    BAD: <br />
                    {/* this.props = {this.props} */}
                    <div style={styles.css1}>
                        this.props.children = {this.props.color}
                    </div>
                    {/* this.props.arr = {this.props.arr} */}
                    {/* this.props.obj = {this.props.obj} */}
                    <br />
                    <p style={styles.css2}>
                        Object Error, need using map items to item
                    </p>
                </div>
            </div>
        );
    }
}

// text={message.text} => message object
class Message extends React.Component {
    render() {
    		//console.log(`this.props.text = `, this.props.text);
        //console.log(`this.props.key= `, this.props.key);
        let style = `
        		color: red;
            font-size: 23px;
        `;
        if(this.props.key === undefined){
        		//alert(`smg!`);
            console.log(`%c this.props.key= \n`, style, this.props.key);
        }
        return (
            <div>
                <hr />
                this.props.key = {this.props.key}
                <br />
                this.props.indexkey = {this.props.indexkey}
                <br />
                this.props.text = {this.props.text}
                <br />
                this.props.color = <span style={{backgroundColor: this.props.color}}>{this.props.color}</span>
                <br />
                <Button color={this.props.color} xyzClick={this.props.xyzClick}>
                    <span style={{color: '#fff'}}>Delete</span>
                </Button>
            </div>
        );
    }
}

// props.children === <span style={{color: '#fff'}}>Delete</span> ??? 
class Button extends React.Component {
    render() {
        return (
            <button
                style={{background: this.props.color}} 
                onClick={(e) => this.props.xyzClick(e)} 
                >
                {this.props.children}
            </button>
        );
    }
}




const text = [
    {
    text: "text 1",
    color: "red"
    },
    {
    text: "text 2",
    color: "blue"
    },
    {
    text: "text 3",
    color: "grey"
    },
    {
    text: "text 4",
    color: "green"
    },
    {
    text: "text 5",
    color: "#f0f"
    }
];
const color = "green";
const ArrayTest = [1, 2, 3];
const ObjectTest = {"key": "value"};

class App extends React.Component{
    constructor(props){
        super(props);
        this.state  = {
            showSate: false
        };
    }
    setModalVisible = (value) => {
        console.log(`showSate`, this.state.showSate);
        console.log(`value`, value);
        this.setState({
            showSate: value
        });
        // 状态更新可能是异步的
        setTimeout(() => {
        		console.log(`showSate`, this.state.showSate);
        });
    };
  	XC = (e) => {
      	let m = e.toString();
      	console.log(e, m);
      	return alert(`e.toString(); =\n`, m);
  	};
  render(){
      return(
          <div>
               <div>
                   <button onClick={() => console.log(`smg`)}>
                       onClick
                   </button>
                   <button onClick={()=>this.setModalVisible(true)}>
                       showModal{this.state.showSate}
                   </button>
               </div>
               <MessageList
                   messages={text}
                   color={color}
                   arr={ArrayTest}
                   obj={ObjectTest}
                   xyzClick={this.XC}/>
          </div>
      );
    }
};



export default App;

ReactDOM.render(
    <App />,
    mountNode
);