登录 ×

梨花寨前端技术交流平台!

html,css,js,html5,css3等

recat示例 - 数据驱动模板及交互获取数据完整流程

2013-01-14 11:28:33 | 浏览量:510 react webpack es6

前几天在做项目中遇到一个问题,卡了半天时间,想想这个可能大家很容易踩坑,就些出来分享下。

需要是这样的,这是一个Form表单中的一项,为衣服添加尺寸和衣服属性,根据库存情况,不同衣服需要的项是不一样的,也就是需要可以动态创建项。

点击加号,新增一行。

如果使用传统方式实现话,引入jquery,给加号按钮元素加onClick事件,执行clone操作;

这里讲给予react框架来开发,以数据驱动模版,避免直接操作Dom。

首先定义state,整体是个数组,每一项是一个map,其它尺寸(size),颜色(color)是其中的的key值。默认应该显示一列,可以在constructor中设置state如下:

this.state = {
    // selet项初始化数据
    selectData: [{ size: 175, color: 'white' }]
}

给予selsetData来渲染Dom,注意设置select的默认值时,使用value,需配合使用onChange.

160165170175180185

实现用户选择Select功能:

react需要手动处理的,触发事件后,获取选择的值,改动对应state值。因为是数组,要根据数组下标index来找到对应的数据,这里的index在渲染的时候以data-index属性加入到select元素中。在改数据时可以判断下type,区别下size和color两个元素,这样可以公用。

setSelectData = (e) => {
     let value = e.target.value;
     var index = parseInt(e.target.getAttribute("data-index"));
     let type = e.target.getAttribute("data-type");

     var lists = this.state.selectData;
     var presentItem = lists[index];

     if (type == 'size') {
         presentItem.size = parseInt(value);
     } else if (type == 'color') {
         presentItem.color = value;
     }

     this.setState({ selectData: lists })
}

实现新增选择项功能:

根据index拷贝对应数据,插入到数组(selectData)中index的下一位,然后将新的数组数据set下。数据更新后,dom即会新增一列对应数据。

addItem = (e) => {
   var index = parseInt(e.target.getAttribute("data-index"));
   var listsNew = this.state.selectData;
   var presentItem = listsNew[index];
   listsNew.splice(index, 0, presentItem)
   this.setState({ selectData: listsNew })
}

这里实现新增项的功能是实现了,不过会带来一个bug,效果如下:

显然这不是我们像要的效果,新增的项相互关联,互相影响。经排除是引用类型数据操作没考虑深拷贝引起的问题。在新增是,拷贝对应项目的数据,只是复制了引用地址,而非实际的数据,这样在用户选择动态增加的项时,改变的数据都是当时被拷贝的原始数据。所以基于原色数据渲染除所有项目都展示一样的。

找到原因就好解决了,写一个深拷贝的方法,在新增项的函数时拷贝数据时调用下就可以。

addItem = (e) => {
   var index = parseInt(e.target.getAttribute("data-index"));
   var listsNew = Common.deepClone(this.state.selectData);
   var presentItem = Common.deepClone(listsNew[index]);//深拷贝
   listsNew.splice(index, 0, presentItem)
   this.setState({ selectData: listsNew })
}

深拷贝函数代码:

 deepClone(data) {
        let type = this.getType(data);
        let obj;
        if (type === 'array') {
            obj = [];
        } else if (type === 'object') {
            obj = {};
        } else {
            // 不再具有下一层次
            return data;
        }
        if (type === 'array') {
            for (let i = 0, len = data.length; i < len; i++) { obj.push(this.deepClone(data[i])); } } else if (type === 'object') { for (let key in data) { obj[key] = this.deepClone(data[key]); } } return obj; }


这样更改下就正常了,效果如下:

示例代码在github上: https://github.com/lihuazhai/frontEndCourse/tree/master/other/src/page/selectList

需求及问题提交:

点击图片更换数字

0.6080s