React.js点击获取自定义属性

来源:互联网 发布:怎么把淘宝客链接转换 编辑:程序博客网 时间:2024/06/13 13:06

获取React.js自定义属性必须data- ,比如data-index  然后用event.target.getAttribute("data-index")

或者console.log(this.refs.myInput.getAttribute("data-index"));获取

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Document</title><script src="../build/react.js"></script> <script src="../build/react-dom.js"></script><script src="../build/browser.min.js"></script><script src="../jquery.min.js"></script></head><body><div id="example" dongtao='1111'></div></body><script type='text/babel'>//console.log($('#example').attr('dongtao'))var MyComponent = React.createClass({    handleClick: function(event) {      // 使用原生的 DOM API 获取焦点            console.log(event.target)      console.log(event.target.getAttribute("data-index"))    //    console.log(this.refs.myInput.value);//    console.log(this.refs.myInput.id);    console.log(this.refs.myInput.getAttribute("data-dd"));//    console.log($('#dongtao').val());    },    render: function() {      //  当组件插入到 DOM 后,ref 属性添加一个组件的引用于到 this.refs      return (        <div>          <input type="text" ref="myInput" id='dongtao' data-dd='ddd'/>          <input            type="button"            value="点击"            id="id"            data-index="dongtao"            onClick={this.handleClick}          />        </div>      );    }});ReactDOM.render(  <MyComponent />,  document.getElementById('example'));</script></html>


React 点击删除列表中对应项(React 获取DOM中自定义属性)

点击删除按钮,删除列表中对应项本来是React比较基础的应用,可是应用情况变得复杂了以后,我还真想了一会儿才搞定。

简化一下应用场景:点击新增按钮,增加一条输入框,点击输入框旁边的按钮,删除该输入框(不能删错了啊)。

  1. 先说第一种方法

问题刚上手,首先规划级别:一个输入框和对应删除按钮为一个子组件,整体为父组件即可方便处理。

注意的点:生成的一坨输入框是一个数组,为了准确删掉对应项,生成时要编号。点击删除按钮要反馈对应编号,然后进行删除。

现在的逻辑是:整个待展示列表(由子组件组成的数组)是个state,添加按钮会增加一个元素到这个state里面,添加的方法如下:

复制代码
add(){        var lists=this.state.lists;        lists.push(<List key={this.state.lists.length} index={this.state.lists.length} delete={this.delete}/>);        this.setState({lists:lists})    }
复制代码

注意一点,这个index属性是固定的,子组建生成后就固定了,这就为你未来挖了一个坑。

删除按钮当然就是从这个state列表里删除对应元素了,问题一来了,我怎么知道是第几个元素?一拍脑袋这还不简单,event.target 获取点击的标签,在标签上写个index属性告诉delete方法是第几个元素不就得了?试了发现不行,看看文档,event.target确实获取dom元素没毛病,但是index这个属性原生dom根本不承认啊,怎么办?data-index就行了,前面加 data- 就是dom承认的自定义属性了。

写完了又想起了两个方法,一个是在删除按钮绑定删除事件的时候,.bind(this,index),index是你准备删掉的是第几个或者表示出来你要删哪个就行。另一个是搞个闭包,就能把index参数传进去了(事件绑定一个立即执行的方程传入参数,该方程返回目标方程)。

第一个问题解决,删除的方法如下:

复制代码
delete(e){        var index=e.target.getAttribute("data-index");        var lists=this.state.lists;        lists.splice(index,1);        this.setState({lists:lists})    }
复制代码

data-index告诉你要删除第几个元素,然后把它从state里踢出去就行了。这回掉进了一个真正意义上的坑:有时候删的不是对应的元素!乱套了!

好吧,我沉思了5分钟,想到了为什么:生成列表的时候index已经固定,但删除列表的时候我们只告诉他删除的是第index项!问题严重了,举个例子,有两项,index 0和1 你点0,好吧第0项删掉了,你再点1,疑?没反应了,因为你打算删除第1项,而列表中目前只有第0项(就是原来的第一项,原来的第0项删除后他就成了第0项)!这会导致各种乱套,考虑到生成列表的index是列表长度表示的就更乱了。

解决方式:delete方法里修改一行:

lists.splice(index,1,"");

好了,删除的元素我用空字符串代替,这样顺序和删除的项,还有以后添加的项的index都不会乱了,给自己点赞。到这里第一种方法实现了目标。

Code pen 地址:http://codepen.io/huanqingli/pen/dNyQez

完整代码:

复制代码
class List extends React.Component {    render() {        return (<div><input type="text" defaultValue={this.props.index}/>            <span onClick={this.props.delete} data-index={this.props.index}>X</span></div>)    }}class Lists extends React.Component {    constructor(props) {        super(props);        this.add=this.add.bind(this);        this.delete=this.delete.bind(this);        this.state={            lists:[]        }    }     add(){        var lists=this.state.lists;        lists.push(<List key={this.state.lists.length} index={this.state.lists.length} delete={this.delete}/>);        this.setState({lists:lists})    }     delete(e){        var index=e.target.getAttribute("data-index");        var lists=this.state.lists;        console.log(index)        lists.splice(index,1);        this.setState({lists:lists})           }     render() {        return (<div>            <span onClick={this.add}>添加</span>            {this.state.lists}            </div>)    }}ReactDOM.render(    <Lists/>,    document.getElementById('lists'));
复制代码

这种方法有利有弊,所以我找到了第二种方法,具体情况择优使用。

  1. 第二种方法。总体来讲推荐这种方法。

在state里保存要展示的数据,在render里动态生成子组件组,然后添加删除都是操作保存数据的state,render里的子组件会自动刷新。这种方式应该是更贴近React思路的,用数据展现界面。如果你要展现一组数据,这种方法很自然,但如果展现的是一个动态的表单,稍微麻烦一点,但也可以做,而且我依然推荐用这种方式。

这种方法做个todolist就很简单,这里依然做上文的例子,稍微麻烦一点,也会理解的更深入一点。

整体结构和第一种方法一样,只不过这次state里面不是子组件,先用空字符串组成的数组代替,仅仅是为了render的时候知道有几个子组件而已。添加的时候也要push空字符串,等输入框输入数据后,更新state中的内容,做到数据和界面同步。

render子组件的部分:

{this.state.lists.map(function (item,index) {                return <List key={index} index={index} delete={this.delete}/>            }.bind(this))}

添加的方法变成:

复制代码
add(){        var lists=this.state.lists;        lists.push("");        this.setState({lists:lists})    }
复制代码

这就能跑了,这有个小坑,稍有不慎你发现你怎么删都是删列表的最后一项,其实数据操作没问题,关键是这个存在感比较低的key,必须特定项有给定的key你用动态的index他就懵了,不知道删哪个了,他就吧最后一个删了。废话不多说(该程序因为key键取值的问题有一个小问题)

Code pen 地址:http://codepen.io/huanqingli/pen/xgxNYN

整体代码:

复制代码
  1 class List extends React.Component {  2   3     constructor(props){  4   5         super(props);  6   7         this.upData=this.upData.bind(this);  8   9     } 10  11     12  13     upData(e){ 14  15         this.props.upData(this.props.index,e.target.value) 16  17     } 18  19   20  21     render() { 22  23         return (<div><input type="text" onBlur={this.upData} defaultValue={this.props.item?this.props.item:""}/> 24  25             <span onClick={this.props.delete} data-index={this.props.index}>X</span></div>) 26  27     } 28  29 } 30  31 class Lists extends React.Component { 32  33     constructor(props) { 34  35         super(props); 36  37         this.add=this.add.bind(this); 38  39         this.delete=this.delete.bind(this); 40  41         this.upData=this.upData.bind(this); 42  43         this.state={ 44  45             lists:[] 46  47         } 48  49     } 50  51   52  53     add(){ 54  55         var lists=this.state.lists; 56  57         lists.push(""); 58  59         this.setState({lists:lists}) 60  61     } 62  63   64  65     delete(e){ 66  67         var index=e.target.getAttribute("data-index"); 68  69         var lists=this.state.lists; 70  71         lists.splice(index,1); 72  73         this.setState({lists:lists}) 74  75     } 76  77   78  79     upData(i,x){ 80  81         var lists=this.state.lists; 82  83         lists[i]=x; 84  85         console.log(lists); 86  87         this.setState({lists:lists}); 88  89     } 90  91   92  93     render() { 94  95         return (<div> 96  97             <span onClick={this.add}>添加</span> 98  99             {this.state.lists.map(function (item,index) {100 101                 return <List key={item?item:index} index={index} delete={this.delete} upData={this.upData}  item={item}/>102 103             }.bind(this))}104 105             </div>)106 107     }108 109 }110 111  112 113 ReactDOM.render(114 115   <Lists />, document.getElementById('lists')116 117 )
复制代码

 

这种方法经常也会有点小坑,也比较好解决。

总结:两种方法各有利弊,推荐第二种,符合REACT设计思路,但第一种有时候解决问题很方便。





0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 华为7x金属外壳掉漆了怎么办 华为麦芒6连接蓝牙音响卡顿怎么办 华为芒麦6恢复出厂设置怎么办 华为麦芒4下拉通知栏没反应怎么办 怎么看华为麦芒6信号差怎么办 华为手机锁屏密码忘了怎么办 苹果手机进水后手机卡无服务怎么办 摩拜单车绑定的手机号注销了怎么办 摩拜单车注册的手机号注销了怎么办 摩拜单车注册手机号换了怎么办 被手机店骗话费送合约机怎么办 机蜜租赁的手机丢了怎么办 合约机返话费手机掉了怎么办 手机摔坏了开不了机怎么办 华为魅特10屏幕锁住了怎么办 电信送的路由器只有一个端口怎么办 苹果手机5c屏幕死机了怎么办 日版苹果手机显示无服务怎么办 iphone有锁4g变3g怎么办 耳机胶套脱落掉入耳朵怎么办 苹果笔记本电用完了开机了怎么办 华为荣耀5x锁屏密码忘了怎么办 华为荣耀锁屏密码忘了怎么办 华为手机屏锁密码忘了怎么办 华为荣耀9青春版相机很模糊怎么办 华为荣耀7手机照相忽然模糊怎么办 苹果5s进水开不了机怎么办 红米4a玩王者荣耀卡怎么办 老是显示媒体存储以停止运行怎么办 支付宝邮二维码地址留错了怎么办 华为畅享5s太卡怎么办 金立手机导航gps信号弱怎么办 贴了膜后边缘有气泡怎么办 魅族mx5刷机失败然后黑屏怎么办 魅族手机无线网玩王者卡怎么办 魅族手机玩王者荣耀卡怎么办 魅族手机导航gps信号弱怎么办 魅族手机4g信号差怎么办 魅族手机下面一排键失灵怎么办 魅族手机冲不进去电怎么办 苹果账号付款了又让付款怎么办