todoList (React版)

一、利用组件化原理编写TodoList功能

  1. 利用map()方法对数组进行映射时,需要对重复显示的内容添加key属性,取值为具有唯一性的索引值。
  2. 对文本框中的数据进行双向绑定:
//JSX:

<input value={this.state.inputValue} onChange={this.inputChange.bind(this)} />

inputChange(event){
	console.log(event.target.value);    //得到用户在文本框中输入的内容
	this.setState({
		inputValue:event.target.value
	})
}
  1. 在JSX中为HTML元素设置类名,应该使用className属性,而不是class属性。
  2. 如何在JSX代码中指定的事件里传递参数:
<span className="delete" onClick={this.deleteItem.bind(this,index)}></span>
//该案例引入了:<link rel="stylesheet" href="style/bootstrap.css">
//如果使用了Bootstrap,则不要使用.close类名
  1. 利用Bootstrap进行页面样式的改写
.container
.row
    .col-md-12
    
文本框与按钮:
.input-group
 input.form-control   //文本框
 .input-group-btn
    button.btn.btn-primary    //按钮
  1. 如何为HTML元素设置内联样式:
<li style={{marginBottom:10px’}}><span>&times;</span>{item}</li>

二、将组件进行拆分

  1. 父组件向子组件传递数据:通过HTML属性来进行传递的。
    子组件接收父组件传递的参数:this.props.属性名
    父组件向子组件传递的数据属于单向传递,在子组件中不能修改父组件传递过来的数据。
  2. 子组件向父组件传递数据:通过父组件中的自定义事件来进行传递。
    子组件中如何调用父组件的自定义事件:this.props.自定义事件名

效果图
在这里插入图片描述

完整代码:

<div id="app"></div>
//组件TodoItem(子组件)
class TodoItem extends  React.Component{
    //删除待办事宜
    deleteItem(index){
        this.props.onCustom(index);
    }
    render(){
        return(
            <div>
                <li key={this.props.index}>
                    <span className="delete" onClick={this.deleteItem.bind(this,this.props.index)}>&times;</span>
                    {this.props.title}
                </li>
            </div>
        )
    }
}

//组件TodoList(父组件)
class TodoList extends React.Component{
    constructor(props){
        super(props);
        this.state = {
            inputValue:'',
            mylist:['早上7:30吃饭','早上8:30上班','中午12:00休息']
        }
    }
    //添加待办事宜,文本框change事件
    inputChange(event){
        this.setState({
            inputValue:event.target.value
        })
    }
    //按钮点击事件
    addClick(){
        if(this.state.inputValue == ''){
            alert('请输入待办事宜')
        }else{
            let mylist = [...this.state.mylist,this.state.inputValue];
            this.setState({
                mylist,
                inputValue:''
            })
        }
    }
    //删除待办事宜
    closeItem(index){
        let mylist = [...this.state.mylist];
        mylist.splice(index,1);
        this.setState({
            mylist
        })
    }
    render(){
        return (
            <div>
                <div className="container">
                    <div className="row"><h2>ToDoList (React版) <span style={{fontSize:'16px'}}>练习</span></h2></div>
                    <div className="row">
                        <div className="input-group">
                            <input className="form-control" type="text" value={this.state.inputValue} placeholder='请添加待办事宜'
                            onChange={this.inputChange.bind(this)}/>
                            <div className="input-group-btn">
                                <button className="btn btn-success" onClick={this.addClick.bind(this)}>添加待办事宜</button>
                            </div>
                        </div>
                    </div>
                    <div className="row" style={{marginTop:'20px'}}>
                        <ul className="mylist">
                            {
                                this.state.mylist.map((item,index)=>{
                                    return <TodoItem title={item} index={index} key={index} onCustom={this.closeItem.bind(this,index)}></TodoItem>
                                })
                            }
                        </ul>

                    </div>
                </div>
            </div>
        )
    }
}

ReactDOM.render(
    <TodoList></TodoList>,
    document.getElementById('app')
)

三、代码优化

1. 事件中的this指向

我们在开发时希望this永远指向this所在的组件(类中)中

  1. 第一种解决方案
    在组件的构造函数中,对所有的事件方法进行重写,这样在使用这些事件方法时就不需要再重新指定this指向了。
constructor(props){
	super(props);
	this.state={};    //组件的状态,相当于Vue中的数据区
	//对组件中使用的事件进行重写
	this.inputChange=this.inputChange.bind(this);
	this.addTodo=this.addTodo.bind(this);
	this.closeItem=this.closeItem.bind(this);
}
render(){
	return(
		<input type=“text” onChange={this.inputChange} />
	)
}
  1. 第二种解决方案
    使用箭头函数来书写事件代码
<input onChange={()=>this.inputChange(event)}>
<button onClick={()=>this.addTodo()}></button>
<TodoItem onCustom={()=>this.closeItem(index)} />
  1. 如果要在浏览器的控制台中看到组件实例,可以定义一个全局变量,在组件的构造函数中将this指向这个全局变量
let that;
	class TodoList extends React.Component{
		constructor(props){
			that=this;
		}
	}
2. 如何在JSX代码中设置必须存在的根节点

问题:如果用普通的div或HTML标记对做根节点,这个跟节点将被渲染到页面中。
解决:使用<React.Fragment></React.Fragment>做根节点。

3. 使用对象解构的方式对React对象的属性进行操作
const {Component,Fragment} = React;
class TodoList extends Component{
	render(){
		return (
			<Fragment></Fragment>
		)
	}
}
4. 子组件接收父组件传递的参数也可以使用对象解构的方式
const {text,index,onCustom} = this.props;
//具体的子组件方法中使用到哪个父组件属性就解构哪一个。

四、代码优化后结果

//组件TodoItem(子组件)
const {Component,Fragment} = React; //使用对象解构的方式对React对象的属性进行操作
class TodoItem extends  Component{
    //删除待办事宜
    deleteItem(index){
        //子组件接收父组件传递的参数也可以使用对象解构的方式
        //具体的子组件方法中使用到哪个父组件属性就解构哪一个。
        const {onCustom} = this.props;
        onCustom(index);
    }
    render(){
        const {title,index} = this.props;
        return(
            <Fragment>
                <li key={index}>
                    <span className="delete" onClick={()=>this.deleteItem(index)}>&times;</span>
                    {title}
                </li>
            </Fragment>
        )
    }
}

//组件TodoList(父组件)
class TodoList extends Component{
    constructor(props){
        super(props);
        this.state = {
            inputValue:'',
            mylist:['早上7:30吃饭','早上8:30上班','中午12:00休息']
        }
    }
    //添加待办事宜,文本框change事件
    inputChange(event){
        this.setState({
            inputValue:event.target.value
        })
    }
    //按钮点击事件
    addClick(){
        if(this.state.inputValue == ''){
            alert('请输入待办事宜')
        }else{
            let mylist = [...this.state.mylist,this.state.inputValue];
            this.setState({
                mylist,
                inputValue:''
            })
        }
    }
    //删除待办事宜
    closeItem(index){
        let mylist = [...this.state.mylist];
        mylist.splice(index,1);
        this.setState({
            mylist
        })
    }
    render(){
        return (
            <Fragment>
                <div className="container">
                    <div className="row"><h2>ToDoList (React版) <span style={{fontSize:'16px'}}>练习</span></h2></div>
                    <div className="row">
                        <div className="input-group">
                            <input className="form-control" type="text" value={this.state.inputValue} placeholder='请添加待办事宜'
                            onChange={()=>this.inputChange(event)}/>
                            <div className="input-group-btn">
                                <button className="btn btn-success" onClick={()=>this.addClick()}>添加待办事宜</button>
                            </div>
                        </div>
                    </div>
                    <div className="row" style={{marginTop:'20px'}}>
                        <ul className="mylist">
                            {
                                this.state.mylist.map((item,index)=>{
                                    return <TodoItem title={item} index={index} key={index} onCustom={()=>this.closeItem(index)}></TodoItem>
                                })
                            }
                        </ul>
                    </div>
                </div>
            </Fragment>
        )
    }
}

ReactDOM.render(
    <TodoList></TodoList>,
    document.getElementById('app')
)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值