小案例代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>work7</title> <script src="../js/react.development.js"></script> <script src="../js/react-dom.development.js"></script> <script src="../js/prop-types.js"></script> <script src="../js/babel.min.js"></script> <script type="text/babel"> /* 问题1:数据保存哪个组件? 如果数据是某个组件需要,就直接给该组件,如果是某些组件需要,就给共同的父亲 问题2:在子组件中改变父组件的状态? 子组件中不能直接改变父组件的状态 状态在哪个组件更新状态的行为就应该定义在哪个组件 解决方案:父组件定义函数,传递给子组件,子组件调用 组件化编写功能的流程: 1.拆分组件(定义n个组件) 2.实现静态组件(给组件内实现render,没有动态数据,没有交互) 3.实现动态组件 1).实现初始化数据动态显示 2).实现交互功能 */ class App extends React.Component{ constructor(props){ super(props) this.state={ //初始化数据 todos:['DO','dujingxiu','eee'] } this.addTodo=this.addTodo.bind(this) } addTodo(todo){ //方法也是一种数据 //更新数据必须更新状态 const {todos}=this.state todos.unshift(todo) //更新状态 this.setState({todos}) } render(){ const {todos}=this.state return( //return 里面只能有一个根标签 <div> <h1>Simple TODO List</h1> <Add count={todos.length} addTodo={this.addTodo}/> <List todos={todos}/> </div> ) } } class Add extends React.Component{ constructor(props){ super(props) this.add=this.add.bind(this) } add(){ //1.读取输入的数据 const todo=this.todoinput.value.trim() //2.检查合法性 if(!todo){ //如果字符串为空 return }else{ //3.添加内容 this.props.addTodo(todo) //4.清除输入 this.todoinput.value='' } } render(){ return( <div> <input type="text" ref={input=>this.todoinput=input}/> <button onClick={this.add}>add{this.props.count+1}</button> </div> ) } } class List extends React.Component{ render(){ const {todos}=this.props return ( <ul> {todos.map((todo,index)=><li key={index}>{todo}</li>)} </ul> ) } } List.propTypes={ todos:PropTypes.array.isRequired } Add.propTypes={ count:PropTypes.number.isRequired, addTodo:PropTypes.func.isRequired } ReactDOM.render(<App />,document.getElementById("example")) </script> </head> <body> <div id="example"></div> </body> </html>
收集表单数据:
代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>work8</title> <script src="../js/react.development.js"></script> <script src="../js/react-dom.development.js"></script> <script src="../js/prop-types.js"></script> <script src="../js/babel.min.js"></script> <script type="text/babel"> class LoginForm extends React.Component{ constructor(props){ super(props) this.state={ pwd:'' } this.handleSubmit=this.handleSubmit.bind(this) this.handleChange=this.handleChange.bind(this) } handleSubmit(event){ //阻止事件的默认行为,这里事件的默认行为是 提交 event.preventDefault() const name=this.nameInput.value const {pwd}=this.state alert(`准备提交的用户名为:${name};密码为:${pwd}`) } //onChange事件:这个方法在原生中input的onChange是在失去焦点的时候触发,而在react的onChange是输入内容就会调用方法 handleChange(event){ //读取输入的值 const pwd=event.target.value //更新pwd的状态 this.setState({pwd}) } render(){ return( <form action="/test" onSubmit={this.handleSubmit}> 用户名:<input type="text" ref={input=>this.nameInput=input}/> 密码:<input type="password" value={this.state.pwd} onChange={this.handleChange}/> <input type="submit" value="登录"/> </form> ) } } ReactDOM.render(<LoginForm/>,document.getElementById("example")) </script> </head> <body> <div id="example"></div> </body> </html>
包含表单的组件分类:
受控组件:表单项输入数据能自动收集成状态(例如上面的密码框)
非受控组件:需要时才动手读取表单输入框中的数据(例如上面的姓名框)