react——ToDoList案例

        todolist案例是一个类似于笔记本的一个小案例,能做到添加输入内容到列表中,指定删除对应的列表数据,前提基础要会react,掌握react中的事件和获取dom元素的值,以及状态的获取和修改。案例中的样式是最简单的一种,学会了之后,大家可以按照自己想要的设计风格修改,也可以扩展内容,如统计列表中展示的条数等。案例中需要注意的是深拷贝问题

todolist案例视频

一、思路

1、获取输入框中的内容。这里有好几种方式,我这里采取的是ref方式来获取react之ref_夏*想想的博客-CSDN博客

2、点击add添加输入框内容至列表中react——事件绑定_夏*想想的博客-CSDN博客,成功添加后清空输入框中的内容

3、点击del,对应删除列表中的数据

二、实践

代码中已经详细的注释解析了,就不在这里赘述了

import React, { Component } from 'react'
import './todolist.css'
// 简单得todolist
export default class ToDoList extends Component {
    /* 
    todolist实现思路:
      ​
        1、获取输入框中的内容。这里有好几种方式,我这里采取的是ref方式来获取

        2、点击add添加输入框内容至列表中,成功添加后清空输入框中的内容

        3、点击del,对应删除列表中的数据

    */
    // 1、获取input中输入的值
    myRef = React.createRef()

    // 2、存储输入后点击add的值
    state = {
        // 准备一个数组用于存放输入框中的内容
        list: [{ id: 1, text: '11' }, { id: 2, text: '21' }],
    }
    // add事件
    addFn = () => {
        // 3、每次点击后追加到list列表中
        var newList = [...this.state.list]
        newList.push({
            id: Math.random() * 1000000,//随机id
            text: this.myRef.current.value//ref绑定获取到单前输入的内容
        })
        // 修改追加后的数组
        this.setState({
            list: newList
        })
        // 4、清空输入框内容
        this.myRef.current.value = ""
    }
    // del事件
    delFn = (index) => {
        var newList = this.state.list.concat()
        // 通过传入的index,来指定删除
        newList.splice(index, 1)
          // 修改删除后的数组
        this.setState({
            list: newList
        })
    }
    render() {
        return (
            <div className='todolist'>
                <div className='form'>
                    <input ref={this.myRef} />
                    <button onClick={this.addFn}>add</button>
                </div>
                <ul>
                    {/* 通过map循环来生成对应的列表 */}
                    {
                        this.state.list.map((item, index) => (
                            <li key={item.id}>
                                <p>{item.text}</p>
                                <button onClick={this.delFn.bind(this, index)}>del</button>
                            </li>
                        ))
                    }
                </ul>
            </div>
        )
    }
}

三、思考

        修改状态时的setState是异步的,我们对数组进行操作时,大部分数组方法会修改到原数组,因此建议先将数组深拷贝一次,修改后再重新赋值。深拷贝的方法有:

(一)解构数组中的每一项,再重新赋值,如案例中的...

(二)序列化

 JSON.parse(JSON.stringify(数组)),有局限性,如对象里有函数, undefind, data对象此方法不行

import React, { Component } from 'react'
export default class App9 extends Component {
    state = {
        arr: ["张飞", "赵云", "刘备"]
    }
    render() {
        return (
            <div>
                <ul>
                    {
                        this.state.arr.map((item, index)=>{
                            return <li key={index}>{item}</li>
                        })
                    }
                </ul>
                <button onClick={this.addFn.bind(this)}>追加一项到arr的最后</button>
                <button onClick={this.chanFn.bind(this)}>修改arr的最后一项</button>
            </div>
        )
    }
    // 追加一项到arr的最后
    // 修改state的方式只能是setState
    // 数组的push方法会修改原数组
    // this.state.arr.push() 会造成直接修改了state中的arr
    // 修改数组,不能直接修改this.state.arr
    
    addFn(){
        // 如果我声明一个变量,等于this.state.arr,并且让这个变量和this.state.arr完全脱离关系[深拷贝]
        let newArr = JSON.parse(JSON.stringify(this.state.arr));
        // 往newArr中push一项
        newArr.push('关羽');
        // 把最新的newArr赋值给arr
        this.setState({
            arr: newArr
        })
    }
    // 修改最后一项
    chanFn(){
        // 如果我声明一个变量,等于this.state.arr,并且让这个变量和this.state.arr完全脱离关系[深拷贝]
        let newArr = JSON.parse(JSON.stringify(this.state.arr));
        //修改最后一项
         newArr.splice(3,1,'如花');
        // 把最新的newArr赋值给arr
        this.setState({
            arr: newArr
        })
    }
}

(三)递归

比较费手和脑子

const obj = {
  name: 'zs',
  family: {
    father: 'zs',
    mother: 'ls'
  },
  hobby: ['打游戏', '喝奶茶', '熬夜']
}
const newObj = {}
 
function deepClone(target, old) {
  for (const key in old) {
    if (old[key] instanceof Array) {
      // 判断是否为数组
      // TODO...
      // deepCopy 深拷贝; 深复制; 深层复制;
      target[key] = []
      deepClone(target[key], old[key])
    } else if (old[key] instanceof Object) {
      // 判断是否为对象
      // TODO...
      target[key] = []
      deepClone(target[key], old[key])
    } else {
      // TODO...
      target[key] = old[key]
    }
  }
}
deepClone(newObj, obj)
 
// 用来检验是否深拷贝成功
obj.family.father = '王五'
obj.hobby[0] = '睡觉'
console.log(obj);
console.log(newObj);

(四)借助插件lodash

// 引入lodash
const _ = require('lodash')
 
const obj = {
  name: 'zs',
  family: {
    father: 'zs',
    mother: 'ls'
  },
  hobby: ['打游戏', '喝奶茶', '熬夜']
}
 
// TODO...
// 使用lodash
const newObj = _.cloneDeep(obj)
 
// 下面代码不要动, 用来检验是否深拷贝成功
obj.family.father = '王五'
obj.hobby[0] = '睡觉'
console.log(obj);
console.log(newObj);

猜你喜欢

转载自blog.csdn.net/m0_55173487/article/details/128457697