bunny笔记|React基础篇(Demo:实现学生信息录入系统
第一章 基础篇-快速入门
![](https://img.haomeiwen.com/i2404850/15dd9ef264d34fce.png)
- 学习react的必要性
- 使用组件化开发方式,符合现代Web开发的趋势,企业前后端项目分离,react是首选
- 技术成熟,社区完善,配件齐全,适用于大型web项目(生态系统健全)
- 由Facebook专门的团队维护,技术可靠
- ReactNative -Leam once,write anywhere:Build mobile apps with React
- 使用方式简单,性能非常高,支持服务端渲染
- React使用前端技术非常全面,有利于整体提高技术水平,此外,有利于求职和晋升,有利于参与潜力大的项目
- react生态圈的概念认知
- react具备的特点:
1)使用JSX语法创建的组件,实现组件化开发,为函数的UI编程方式打开了大门;
2)性能高:通过diff算法 和 虚拟DOM实现函数视图的高效渲染和更新;
3)JSX-->HTML ,JSX-->native ios 或 android中的组件(XML) ,JSX-->VR/AR ,JSX--TO-->EveryThing, 声明式、组件化、一次学习,随处编写(无论你现在使用什么技术栈,在无需重写现有代码的前提下,通过引入 React 来开发新功能。React 还可以使用 Node 进行服务器渲染,或使用 React Native 开发原生移动应用。
)
- React核心:
1)虚拟DOM(1.==概念==:react将DOM抽象为DOM,虚拟DOM其实就是用一个对象来描述DOM,通过对比前后两个对象的差异,最终只把变化的部分重新渲染,提高渲染的效率;
2.==为什么要用虚拟DOM==:当DOM发生更改时需要遍历DOM对象的属性,而原生DOM可便利多达200多个,而且大部分属性与渲染无关,导致更新页面代价太大。
3.==虚拟DOM的处理方式==:
- 用JS对象结构表示DOM树的结构,然后用这个树构建一个真正的DOM树,插到文档当中(一次性)。
- 当状态变更的时候,重新构造一棵新的对象树,然后用新的树和旧的树进行比较,记录两棵树的差异。
- 把记录的差异应用到步骤1 所构建的真正的DOM树上,视图就更新了。);
2)Diff算法(1.==概念==:最小化页面重绘。(当我们使用react在render()函数创建了一棵react元素树,在下一个state或者props更新的时候,render()函数会创建一棵树的react的元素树。react将对比这两棵树的不同之处,计算出如何高效的更新UI(只更新变化的地方),此处所采纳的算法就是diff算法。)(2.==其它==:项目中具体了解)
-
react使用初体验
1.实现demo(类库引入、代码编写、配置react-develop-tools开发调试工具)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<div id="app"></div>
<script src="../js/react.development.js"></script>
<script src="../js/react-dom.development.js"></script>
<script src="../js/babel.min.js"></script>
<script type="text/html">
// 1.获取页面真实的容器元素
const containerDiv = document.getElementById('app');
// 2. jsx语法创建虚拟DOM对象
const vDom = <div>你好!</div>;
// 3. 将虚拟DOM渲染到页面元素上去
ReactDOM.render(vDom, containerDiv);
</script>
</body>
</html>
-
react使用JSX语法
- 安装React Developer Tools插件(将react-dev-tool.crx文件谷歌扩展程序中,若报错:程序包无效:“CRX_HEADER_INVALID”,是由于格式不对无法正常解析,可将文件后缀名修改为.zip或.rar,如react-dev-tool.zip再解压即可,亲测有效。)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="app1"></div>
<div id="app2"></div>
<!--
往容器中插入一个span标签, class为: "it-like", 内容为: "学习React"。
两种实现方式: a) 通过典型js方式; b) JSX方式?
-->
<script src="../js/react.development.js"></script>
<script src="../js/react-dom.development.js"></script>
<script src="../js/babel.min.js"></script>
<script>
// a) 通过典型js方式
// 1. 创建变量
let myClass = 'it-like';
let myContent = '学习React';
// 2. 创建DOM
const vDOM = React.createElement('span', {className: myClass}, myContent);
// 3. 将虚拟DOM渲染到页面元素上去
ReactDOM.render(vDOM, document.getElementById('app1'));
</script>
<script type="text/babel">
// b) JSX方式
const vDom1 = <span className={myClass.toUpperCase()}>{myContent}</span>;
ReactDOM.render(vDom1, document.getElementById('app2'));
</script>
</body>
</html>
html中实现React的应用:方式1-传统引入js的方式; 方式2-JSX方式。
总结:1.JSX只是高级语法糖,最终执行时还是会被转成原生js,通过babel等方式;
2.更加语义化,更加直观,代码可读性更高;
3,性能相对原生方式更好一些。
- react多重节点嵌套
JSX常见的页面操作方式:
主体:1).多重标签嵌套,2).js中的变量表达式要写在{}里,3).内联样式通过对象方式引入,4).数组遍历
- react样式和表达式使用 react使用JSX遍历
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>React 练习</title>
</head>
<body>
<div id="app">
</div>
<script src="../js/react.development.js"></script>
<script src="../js/react-dom.development.js"></script>
<script src="../js/babel.min.js"></script>
<script type="text/html">
// a. 多重标签嵌套
ReactDOM.render(
<div>
<h2>多层标签嵌套</h2>
<img src="img/logo.jpg" alt="学习React" width="300" />
<p>测试!</p>
</div>
, document.getElementById('app'));
</script>
<script type="text/html">
// b. js中的变量, 表达式要写在{}内
const str = '学习React';
ReactDOM.render(
<div>
<span>{str}</span>
<p>100 + 20 * 2 /5 *3 = {100 + 20 * 2 /5 *3}</p>
</div>
, document.getElementById('app'));
</script>
<script type="text/babel">
// c. 内联样式通过对象方式引入
const myStyle = {
backgroundColor: 'purple',
color: 'yellow',
fontSize: 30
};
ReactDOM.render(
<div>
// 注释
/*注释*/
{/*真正的JSX注释*/}
<h2>来点颜色</h2>
<div style={myStyle}>客官,颜色来了!</div>
</div>
, document.getElementById('app'));
</script>
<script type="text/html">
// 1. 数据
/**/
const dataArr = [
{name: '张三', age: 38},
{name: '谢锋', age: 40},
{name: '刘华', age: 48},
{name: '学习React学员', age: 2}
];
// 2. 创建虚拟DOM
const vDOM = (
<ul>
{
dataArr.map((data, index) =>
<li key={index}>{index + 1} --- 姓名: {data.name} --- 年龄:{data.age}岁</li>
)
}
</ul>
);
ReactDOM.render(
vDOM
, document.getElementById('app'));
</script>
</body>
</html>
- react中使用JSX使用总结
总结:
1.JSX中添加属性时,使用className代替class,像label中的 for属性,使用htmlFor代替;
2.JSX创建DOM的时候,所有的节点,必须有唯一的根元素进行包惠:
3.JSX语法中,标签必须成对出现,如果是单标签,则必须自闭合
4.在JSX中可以直接使用JS代码,直接在JSX中通过)中间写JS代码即可,
5在JSX中只能使用表达式,不能出现语句:
6.在JSX中注释语法:1/中间是注释的内容/
- react中定义组件-构造 -传递参数 -class关键字 state的认知 以及与props的使用区别 -ref的使用等
React中的组件/模块,组件化/模块化
一个应用/版块/页面中用于实现某个局部的功能(包括html,js,css等)
1)组件 把这些局部功能组装到一起就形成了完整的一个大的功能
主要目的在于:复用代码,提高项目运行效率。
2)组件化 如果一个应用是用多组件的方式进行综合开发的,那么这个应用就是一个组件化应用。
多个组件形成模块,或者是一个提供特定功能的js文件,主要特点在
3)模块 于耦合性低,可移植性高,执行效率好。
如果一个应用都是用模块的形式来构建的,那么这个应用就是模块
4)模块化 化应用。
React中组件的创建方式:1)构造函数创建组件; 2)class关键字创建组件 ;
3)区别:
使用构造函数来创建组件时,如果要接收外界传递的数据,需要在构造函数的参数列表中使用props来接收;
必须要向外return一个合法的JSX创建的虚拟DOM;
Demo:简单组件/带参数组件/复合组件。
class关键字创建组件
<script>
class Liao extends React.Component{
render(){
return ()
}
ReactDOM.render();
</script>
例:
<script type="text/babel">
class Liao extends React.Component{
render(){
return (
<div>
<h2>我叫:{this.props.name}, 性别:{this.props.gender}, 我有3个学科:{this.props.colleges}</h2>
</div>
)
}
}
ReactDOM.render(
<Liao name="学习React学员" gender="女" colleges={["h5 ", "Java ", "Python"]}/>,
document.getElementById('app')
);
</script>
区别:1)构造函数创建的组件叫:无状态组件;2)class关键字创建的组件叫:有状态组件;3)有状态组件与无状态组件的本质区别在于是否有state(状态)属性。
什么是state?
React把组件看成是一个状态机(State Machines),通过状态(State)去操作状态机。
在开发中,通过与用户的交互,实现不同的状态,然后渲染UI,让用户界面和数据保持一致。
在React中只需要更新组件的state,然后根据新的state重新渲染用户界面(不需要操作DOM)
state的使用方式?
class Liao extends React.Component{
constructor(props){}
render(){}
dealClick(){}
}
ReactDOM.render();
例:
<script>
// 1. 创建组件类
class Liao extends React.Component{
constructor(props){
super(props);
// 2. 初始化状态
this.state = {
name: '周杰伦',
gender: '男',
intro: '七里香'
};
// this.dealClick = this.dealClick.bind(this);
}
render(){
const {name, gender, intro} = this.state;
return (
<div>
<h3>我叫:{name}, 性别:{gender}, 代表作:{intro}</h3>
<button onClick={()=>this.dealClick()}>换一个</button>
</div>
)
}
dealClick(){
// alert('点了'+ this);
this.setState({
name: '王菲',
gender: '女',
intro: '因为爱情'
});
}
}
// 2. 渲染到DOM容器
ReactDOM.render(
<Liao/>,
document.getElementById('app')
);
</script>
props和state总结:
1)在单组件中props一般用于接收外部传入的数据;而state则用于记录组件内部数据,而且是需要经常改变的数据
2)state是组件内部的状态(数据),不能够直接修改,必须要通过setState来改变值的状态,从而达到更新组件内部数据的作用
3)props更多是组件间传递数据的一种方式,props同样也可以传递state。由于React的数据流是自上而下的,所以是从父组件向子组件进行传递;另外组件内部的thisprops属性是只读的不可修改。
例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>React 练习</title>
</head>
<body>
<div id="app"></div>
<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. 组件类
class Dog extends React.Component{
constructor(props){
super(props);
// 狗: 姓名, 性别, 年龄, 狗友
// 2. 初始化state
this.state = {
age: 1, //年龄
dogFriends: [] // 狗友
}
}
// 3. 设置props属性的默认值
static defaultProps = {
name: '旺财',
gender: '公'
};
// 4. 设置props属性的类型
static propTypes = {
name: PropTypes.string.isRequired,
gender: PropTypes.string.isRequired
};
render(){
const {name, gender} = this.props;
const {age, dogFriends} = this.state;
return (
<div>
<p>狗名:{name}, 性别:{gender}</p>
<p>我今年{age}岁了</p>
<p>我有很多狗友:</p>
<ul>
{dogFriends.map((friend, index)=>(
<li key={index}>{friend}</li>
))}
</ul>
<button onClick={()=>this.addYear()}>增一岁</button>
</div>
)
}
addYear(){
// 1. 增加狗友
let tempArr = this.state.dogFriends;
tempArr.push('狗友'+Math.floor(Math.random()*100));
// this.props.name = '哈哈哈';
/* this.setProps({
name: '哈哈哈哈'
});*/
// 2. 更新状态
this.setState({
age: this.state.age + 1,
dogFriends: tempArr
})
}
}
ReactDOM.render(
<Dog/>,
document.getElementById('app')
);
</script>
</body>
</html>
ref的使用:
1)定义:Refs提供了一种方式,用于访问在render方法中创建的DOM节点或 React元素。
2)使用场景:a)处理焦点、文本选择或媒体控制。 b)触发强制动画。
c)集成第三方DOM库。
3)注意:官方提示,如果可以通过声明式实现,则尽量避免使用refs。话外音:React无法控制局面的时候,就需要直接操作Refs了。
让输入框获得焦点?
4)案例使用 :核心代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>React 练习</title>
</head>
<body>
<div id="app"></div>
<script src="../js/react.development.js"></script>
<script src="../js/react-dom.development.js"></script>
<script src="../js/babel.min.js"></script>
<script type="text/babel">
class CustomTextInput extends React.Component {
constructor(props){
super(props);
// 绑定ref
this.myInput = React.createRef();
this.myBtn = React.createRef();
}
render(){
return (
<div>
<input ref={this.myInput} type="text" placeholder="请输入内容"/>
<input ref={this.myBtn} type="button" value="获取焦点" onClick={()=>this.focusTextInput()}/>
</div>
)
}
focusTextInput(){
// console.log(this.myInput);
this.myInput.current.focus(); // 获取焦点
console.log(this.myBtn);
}
}
ReactDOM.render(
<CustomTextInput/>,
document.getElementById("app")
);
</script>
</body>
</html>
基础篇-案例
案例1:
需求:用react实现一个学生信息录入系统用户页面,并用组件化思维实现添加和删除功能
(1)页面展示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Admin</title>
<style>
#app {
margin: 50px auto;
width: 600px;
}
fieldset {
border: 1px solid rgb(233, 156, 41);
margin-bottom: 20px;
}
fieldset input {
width: 200px;
height: 30px;
margin: 10px 0;
}
table {
width: 600px;
border: 2px solid rgb(233, 156, 41);
text-align: center;
}
thead {
background-color: rgb(233, 192, 130);
color: #fff;
}
</style>
</head>
<body>
<div id="admin"></div>
<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.父类
class Admin extends React.Component {
//渲染
render() {
return (
<div>
<Add />,
<List />
</div>
);
}
}
//2.子类-添加板块
class Add extends React.Component {
//渲染html元素
render() {
return (
<div>
<fieldset>
<legend>信息录入系统(React版)</legend>
<div>
<span>姓名: </span>
<input type="text" placeholder="请输入姓名" />
</div>
<div>
<span>年龄: </span>
<input type="text" placeholder="请输入年龄" />
</div>
<div>
<span>性别: </span>
<select>
<option value="男">男</option>
<option value="女">女</option>
</select>
</div>
<div>
<span>手机: </span>
<input type="text" placeholder="请输入手机号码" />
</div>
<button>新增学员</button>
</fieldset>
</div>
)
}
}
//3.子类-展示板块
class List extends React.Component {
//渲染html元素
render() {
return (
<div>
<table>
<thead>
<tr>
<td>姓名</td>
<td>性别</td>
<td>年龄</td>
<td>手机</td>
<td>删除</td>
</tr>
</thead>
<tbody>
<tr>
<td>周杰伦</td>
<td>男</td>
<td>38</td>
<td>18888888888</td>
<td>
<button>删除</button>
</td>
</tr>
</tbody>
</table>
</div>
)
}
}
//4.渲染到浏览器页面显示
ReactDOM.render(
<Admin />,
document.getElementById('admin')
)
(2)数据动态展示
- 在父类构造函数,并初始化state
constructor(props) {
super(props);
//初始化
this.state = {
studentArr: [
{ name: '小华', age: 30, gender: '男', phone: '18888889999' },
{ name: '小明', age: 30, gender: '男', phone: '18888889994' },
{ name: '小米', age: 20, gender: '女', phone: '18888889992' }
]
}
}
(数据在父类构造初始化状态,要传给子类展示,要在子类约束类型)
- 在子类List中设置属性的类型
//设置props中属性的类型
//.isRequired表示必传值
static propTypes = {
studentArr: PropTypes.array.isRequired
}
-
在父类渲染函数render()处理传值才能将state下的值传给子类
<List studentArr={this.state.studentArr } />
-
在子类List的渲染函数render()中遍历父类数组值
//获取传过来的参数
const { studentArr} = this.props
//处理传入的参数,注意要绑定key值
<tbody>
{
studentArr.map((stu, index) => (
<tr key={index}>
<td>{stu.name}</td>
<td>{stu.gender}</td>
<td>{stu.age}</td>
<td>{stu.phone}</td>
<td>
<button>删除</button>
</td>
</tr>
))
}
</tbody>
(3)实现删除
- 在父类方法下创建一个删除的方法
//删除功能
delFormData(index) {
//1.删除
const { studentArr } = this.state;
studentArr.splice(index, 1);
//2.删除后更新页面状态
this.setState({
studentArr
})
}
- 在子类List中设置属性的类型
//设置props中属性的类型
//.isRequired必传值
static propTypes = {
studentArr: PropTypes.array.isRequired,
delFormArr:PropTypes.func.isRequired
}
- 在父类渲染函数render()的方法中调用
<List studentArr={this.state.studentArr } delFormArr={this.delFormData}/>
- 在子类List的渲染函数render()中触发删除按钮
const { studentArr,delFormArr} = this.props
<td>
<button onClick={()=>delFormArr(index)}>删除</button>
</td>
- 在父类的构造函数下绑定this
//绑定删除的this
this.delFormData = this.delFormData.bind(this);
(4) 添加
- 在父类方法下创建一个删除的方法
//新增学员
addStudent(student){
//1.插入
const {studentArr} =this.state;
studentArr.unshift(student);
//2.更新数据
this.setState({
studentArr
})
}
- 在父类的构造函数下绑定this
//绑定this
this.addStudent = this.addStudent.bind(this);
- 在子类Add中设置属性的类型
//设置props中属性的类型
//.isRequired必传值
static propTypes = {
studentArr: PropTypes.array.isRequired,
delFormArr:PropTypes.func.isRequired
}
- 在子类中绑定ref以及onclick
constructor(props){
super(props);
//绑定ref
this.stuName = React.createRef();
this.stuAge = React.createRef();
this.stuGender = React.createRef();
this.stuPhone = React.createRef();
}
<fieldset>
<legend>信息录入系统(React版)</legend>
<div>
<span>姓名: </span>
<input ref={this.stuName} type="text" placeholder="请输入姓名" />
</div>
<div>
<span>年龄: </span>
<input ref={this.stuAge} type="text" placeholder="请输入年龄" />
</div>
<div>
<span>性别: </span>
<select ref={this.stuGender}>
<option value="男">男</option>
<option value="女">女</option>
</select>
</div>
<div>
<span>手机: </span>
<input ref={this.stuPhone} type="text" placeholder="请输入手机号码" />
</div>
<button onClick={() => this.dealWithClick()}>新增学员</button>
</fieldset>
- 在父类渲染函数render()的方法中调用
<Add addStudentArr={this.addStudent} />
完整源码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Admin</title>
<style>
#app {
margin: 50px auto;
width: 600px;
}
fieldset {
border: 1px solid rgb(233, 156, 41);
margin-bottom: 20px;
}
fieldset input {
width: 200px;
height: 30px;
margin: 10px 0;
}
table {
width: 600px;
border: 2px solid rgb(233, 156, 41);
text-align: center;
}
thead {
background-color: rgb(233, 192, 130);
color: #fff;
}
</style>
</head>
<body>
<div id="admin"></div>
<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.父类
class Admin extends React.Component {
constructor(props) {
super(props);
//初始化
this.state = {
studentArr: [
{ name: '小华', age: 30, gender: '男', phone: '18888889999' },
{ name: '小明', age: 30, gender: '男', phone: '18888889994' },
{ name: '小米', age: 20, gender: '女', phone: '18888889992' }
]
}
//绑定this
this.delFormData = this.delFormData.bind(this);
this.addStudent = this.addStudent.bind(this);
}
//删除功能
delFormData(index) {
//1.删除
const { studentArr } = this.state;
studentArr.splice(index, 1);
//2.删除后更新页面状态
this.setState({
studentArr
})
}
//新增学员
addStudent(student){
//1.插入
const {studentArr} =this.state;
studentArr.unshift(student);
//2.更新数据
this.setState({
studentArr
})
}
//渲染
render() {
return (
<div>
<Add addStudentArr={this.addStudent} />,
<List studentArr={this.state.studentArr } delFormArr={this.delFormData}/>
</div>
);
}
}
//2.子类-添加板块
class Add extends React.Component {
constructor(props){
super(props);
//绑定ref
this.stuName = React.createRef();
this.stuAge = React.createRef();
this.stuGender = React.createRef();
this.stuPhone = React.createRef();
}
// 设置props中属性的类型
static propTypes = {
addStudentArr: PropTypes.func.isRequired
};
//渲染html元素
render() {
return (
<div>
<fieldset>
<legend>信息录入系统(React版)</legend>
<div>
<span>姓名: </span>
<input ref={this.stuName} type="text" placeholder="请输入姓名" />
</div>
<div>
<span>年龄: </span>
<input ref={this.stuAge} type="text" placeholder="请输入年龄" />
</div>
<div>
<span>性别: </span>
<select ref={this.stuGender}>
<option value="男">男</option>
<option value="女">女</option>
</select>
</div>
<div>
<span>手机: </span>
<input ref={this.stuPhone} type="text" placeholder="请输入手机号码" />
</div>
<button onClick={() => this.dealWithClick()}>新增学员</button>
</fieldset>
</div>
)
}
//点击新增学员
dealWithClick(){
//1.读取用户输入的数据
const name = this.stuName.current.value;
const age = this.stuAge.current.value;
const gender =this.stuGender.current.value;
const phone = this.stuPhone.current.value;
// 2. 数据的校验
if (!name || !age || !gender || !phone) {
alert('输入的数据不能为空!');
return;
}
// 3. 添加数据
this.props.addStudentArr({ name, age, gender, phone });
// 4. 清除输入框中的数据
this.stuName.current.value = '';
this.stuAge.current.value = '';
this.stuGender.current.value = '男';
this.stuPhone.current.value = '';
}
}
//3.子类-展示板块
class List extends React.Component {
//设置props中属性的类型
//.isRequired必传值
static propTypes = {
studentArr: PropTypes.array.isRequired,
delFormArr:PropTypes.func.isRequired
}
//渲染html元素
render() {
//console.log(this.props.studentArr)
const { studentArr,delFormArr} = this.props
return (
<div>
<table>
<thead>
<tr>
<td>姓名</td>
<td>性别</td>
<td>年龄</td>
<td>手机</td>
<td>删除</td>
</tr>
</thead>
<tbody>
{
studentArr.map((stu, index) => (
<tr key={index}>
<td>{stu.name}</td>
<td>{stu.gender}</td>
<td>{stu.age}</td>
<td>{stu.phone}</td>
<td>
<button onClick={()=>delFormArr(index)}>删除</button>
</td>
</tr>
))
}
</tbody>
</table>
</div>
)
}
}
//4.渲染到浏览器页面显示
ReactDOM.render(
<Admin />,
document.getElementById('admin')
)
</script>
</body>
</html>
效果展示:
![](https://img.haomeiwen.com/i2404850/69c568944a943ba2.png)
案例2:
ref称为非受控组件方式。以下案例采用受控方式实现数据绑定。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Login</title>
<style>
#login {
margin: 50px auto;
width: 600px;
}
.containt {
margin: 0 auto;
border: 2px solid rgb(17, 17, 16);
float: left;
padding-top: 10px;
}
.userName {
padding-top: 10px;
padding-left: 10px;
}
.userPwd {
padding-top: 10px;
padding-left: 10px;
}
.login {
padding-top: 10px;
padding-bottom: 10px;
text-align: center;
}
</style>
</head>
<body>
<div id="login"></div>
<script src="../js/react.development.js"></script>
<script src="../js/react-dom.development.js"></script>
<script src="../js/babel.min.js"></script>
<script type="text/babel">
//1.创建登录类
class Login extends React.Component {
constructor(props) {
super(props);
//初始化状态
this.state = {
userName: '',
userPwd: ''
}
}
render() {
const { userName, userPwd } = this.state;
return (
<form action="" onSubmit={() => this.login()}>
<div className="containt">
<div className="userName">
<span>用户名:</span>
<input type="text" value={userName} onChange={(e) => this.userChange(e)} />
</div>
<div className="userPwd">
<span>密 码:</span>
<input type="password" value={userPwd} onChange={(e) => this.pwdChange(e)} />
</div>
<div className="login">
<input type="submit" value="登录" />
</div>
</div>
</form>
)
}
userChange(e) {
// 1. 读取输入的用户名
const userName = e.target.value;
console.log(userName);
// 2. 更新状态
this.setState({
userName
});
}
pwdChange(e) {
// 1. 读取输入的用户名
const userPwd = e.target.value;
console.log(userPwd);
// 2. 更新状态
this.setState({
userPwd
});
}
login() {
// 1. 取出数据
const { userName, userPwd } = this.state;
alert(`用户名:${userName},密码:${userPwd}`);
return;
}
}
//渲染(挂载)
ReactDOM.render(
<Login />,
document.getElementById('login')
)
</script>
</body>
</html>
效果:
![](https://img.haomeiwen.com/i2404850/eda69d9fad318ffd.png)