响应式设计思想
在js中需要直接操作dom元素来控制页面,React的设计思想和以前直接操作dom是完全不同的,react是一个响应式的框架,它在做编程的时候,强调的是我们不要直接操作dom。
我们操作的是数据,通过数据的变化,react会自动感知到数据的变化,自动的帮你去生成dom。所以在写代码的时候,我们再也不用关注dom相关的操作了,我们只需要关注数据层的就可以了。
事件绑定
我们要实现的功能是:在输入框中输入文字后,点击旁边的提交按钮,就可以让输入内容以列表形式展示在下方,点击列表的任意一项,就将该项删除。
import React from 'react';
import {Fragment} from 'react'
import {logicalExpression} from "@babel/types";
import './index.css'
class TodoList extends React.Component{
constructor(props) { // 接收一个参数
super(props); // 调用父类Component的构造函数,调用一次
this.state = { // 组件的数据定义在“状态”中
inputValue: '', // input框中的内容
list: ['one','two'] // 列表中的每一项
}
}
render(){
return (
<Fragment>
/*
如果报错:
./src/TodoList.js
Line 13:7: Parsing error: Adjacent JSX elements must be wrapped in an enclosing tag.
Did you want a JSX fragment <>...</>?
报错原因: jsx语法要求组件最外层必须包裹一层元素,从react中引入的Fragment(其实是一个组件)就可以使得最外层包裹元素并在网页中不显示,
相当于占位符(方便于布局管理)
*/
<div>
{
//input 中的显示由this.state.inputValue的值来决定,原生事件绑定用onchange,react中用onChange,监听输入框的变化
}
<input
className="input"
value={this.state.inputValue}
onChange={this.handleInputChange.bind(this)}
/>
<button onClick={this.handleBtClick.bind(this)}>submit</button>
</div>
<ul>
{/*花括号表示里面是一个js表达式,数组中的map方法使list循环*/}
{/*index.js:1375 Warning: Each child in a list should have a unique "key" prop.这个警告告诉我们对数组做循环的时候,每个li标签都需要一个唯一的key值,一般不用index下标*/}
{
this.state.list.map((item,index)=>{
{/*对输入框中的字符串不转义,即输入'<h1>hello</h1>'时以h1标题的样式显示,使用dangerouslySetInnerHTML。花括号中的花括号表示是一个对象*/}
return (
<li
key={index}
onClick={this.handleItemDelete.bind(this,index)}
dangerouslySetInnerHTML={{__html:item}}
>
{/*把index传递给handleItemDelete方法*/}
{/*{item}*/}
</li>
)
})
}
</ul>
</Fragment>
);
}
handleInputChange(event) {
console.log(event); // 事件对象
console.log(event.target); // input 框对应的dom结点
console.log(event.target.value); // event.target是input 框对应的dom结点
console.log(this);// 当事件绑定函数为onChange={this.handleInputChange},this为undefined,此时this指向并没有定义。
// 修改代码onChange={this.handleInputChange}为onChange={this.handleInputChange.bind(this)},用组件的this去改变函数的指向
this.state.inputValue=event.target.value; // 报错TypeError: Cannot read property 'state' of undefined
//不能通过引用的形式改变state中的值,而需要使用React中的setState方法
this.setState({
inputValue: event.target.value
})
}
handleBtClick(e){
// 如果输入框为空,不做任何操作
if(this.state.inputValue===''){
return;
}
this.setState({
list: [...this.state.list,this.state.inputValue],
inputValue: ''
})
}
handleItemDelete(index){
// React中有一个概念---immutable :react规定,state 不允许我们做任何修改
const list = [...this.state.list]; // 把原来的state中的list拷贝到常量list中
list.splice(index,1);
this.setState({
list: list
})
}
}
export default TodoList;//该语法导出TodoList
注意:
- jsx语法要求组件最外层必须包裹一层元素,从react中引入的Fragment(其实是一个组件)就可以使得最外层包裹元素并在网页中不显示(方便于布局管理)
- 单行注释,把花括号写到注释上下两行里面
- react 中,类选择器的类名用className而不用class,防止与TodoList类的class关键字重名
this.state.inputValue=event.target.value;
是不允许的,不能通过引用的形式改变state中的值- …是es6中的展开运算符,把运算符后面的数据展开,生成一个新的数组,逗号后面追加新的数据,并存入新的list中.同时把input框的数据清空