React
第一章:入门案例HelloWorld
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!--准备容器 -->
<div id="test"></div>
<!-- 引入Staticfile CDN 的 React CDN 库 -->
<!--React核心库 -->
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<!--支持React操作Dom -->
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<!-- 生产环境中不建议使用 -->
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
<!--jsx语法-->
<script type="text/babel">
// 创建虚拟Dom
const VDOM = <h1>hello,world</h1>
// 渲染到页面
ReactDOM.render(VDOM,document.getElementById("test"))
</script>
</body>
</html>
第二章:虚拟Dom的两种创建方式
1.js语法创建(不推荐)
<body>
<!--准备容器 -->
<div id="test"></div>
<!-- 引入Staticfile CDN 的 React CDN 库 -->
<!--React核心库 -->
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<!--支持React操作Dom -->
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<!-- 生产环境中不建议使用 -->
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
<script type="text/javascript">
const VDOM = React.createElement('h1', {
id: "title"
}, "HelloWorld")
ReactDOM.render(VDOM, document.getElementById("test"))
</script>
</body>
2.jsx语法创建
<body>
<!--准备容器 -->
<div id="test"></div>
<!-- 引入Staticfile CDN 的 React CDN 库 -->
<!--React核心库 -->
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<!--支持React操作Dom -->
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<!-- 生产环境中不建议使用 -->
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
<script type="text/babel">
const VDOM =
<h1 id="title">hello,world</h1>
ReactDOM.render(VDOM,document.getElementById("test"))
</script>
</body>
第三章:组件分类
1.函数式组件(不推荐)
<body>
<!--准备容器 -->
<div id="test"></div>
<!-- 引入Staticfile CDN 的 React CDN 库 -->
<!--React核心库 -->
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<!--支持React操作Dom -->
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<!-- 生产环境中不建议使用 -->
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
<script type="text/babel">
//为了与HTML标签区分,函数式组件在创建时,函数名首字母要大写
/** 创建函数式组件*/ function Demo(){
return <h2> 函数定义组件</h2>
} /** 渲染到页面*/
ReactDOM.render(<Demo/>,document.getElementById("test"))
</script>
</body>
2.类式组件(推荐)
js类的复习
<script>
class Person{
// 构造器方法
constructor(name,age) {
// 构造器中的this是类的实例对象
this.name=name;
this.age=age;
}
// speak方法在类的原型对象上
// speak方法中的this是Person的实例
speak(){
console.log(`我叫${this.name},年龄${this.age}岁`)
}
}
const p1=new Person("tom",19);
console.log(p1)
p1.speak();
// 我叫tom,年龄19岁
//这里把p1实例上的原型链方法赋给x
const x=p1.speak;
// x直接调用不到speak方法
x()
// 更改函数中的this指向
p1.speak.call({a:1,b:2})
// 我叫undefined,年龄undefined岁
// 继承
class Student extends Person{
constructor(name,age,grade) {
super(name,age);
this.grade=grade;
}
speak(){
console.log(`我叫${this.name},年龄${this.age}岁,我读的是${this.grade}`)
}
}
// 子类可以继承父类的构造器
const s1=new Student("校长",15)
console.log(s1)
// Student {name: '校长', age: 15}
const s2=new Student("校长",15,"高一")
console.log(s2)
s2.speak()
// Student {name: '校长', age: 15, grade: '高一'}
</script>
类式组件
<body>
<!--准备容器 -->
<div id="test"></div>
<!-- 引入Staticfile CDN 的 React CDN 库 -->
<!--React核心库 -->
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<!--支持React操作Dom -->
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<!-- 生产环境中不建议使用 -->
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
<script type="text/babel">
/** 创建类式组件*/
// 必须继承Component,必须有render()函数
class MyComoonent extends React.Component{
// 三大核心属性 state、props、refs
// render在类的原型对象上,this指向类的实例对象
render(){
console.log(this)
return <h2>类定义组件</h2>
}
}
/** 渲染到页面*/
// React解析组件标签,发现该组件为类式定义,然后new出该组件的实例对象
ReactDOM.render(<MyComoonent/>,document.getElementById("test"))
</script>
</body>
组件三大核心属性-state
<body>
<!--准备容器 -->
<div id="test"></div>
<!-- 引入Staticfile CDN 的 React CDN 库 -->
<!--React核心库 -->
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<!--支持React操作Dom -->
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<!-- 生产环境中不建议使用 -->
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
<script type="text/babel">
/** 创建类式组件*/
// let that;
class MyComoonent extends React.Component{
// 三大核心属性 state
// constructor(props) {
// super(props);
// // 初始化状态
// this.state= {
// isHot:false,
// wind:"大风"
// }
// // that=this;
// // 解决changeWeather方法中this指向为空的问题
// // 在changeWeather的原型链上绑定this指向
// this.changeWeather=this.changeWeather.bind(this)
// }
//
//
// // changeWeather放在了类的原型对象上
// // onClick取不到changeWeather的值,因为该方法只能通过实例对象调用,需要加上static关键字
// changeWeather(){
// console.log("此处修改isHot的值")
// // 要使用实例对象调用该方法时,this才会指向类的实例,所以此处无法取到state的值
// console.log(this.state.isHot)
// //注意这里使用this娶不到state的值
//
// // React不支持直接更改,所以以下代码没有用
// // const isHot =this.state.isHot;
// // this.state.isHot=!isHot
//
// // 必须实体内置APIsetState进行状态更改
// const isHot =this.state.isHot;
// this.setState({isHot:!isHot})
//
// }
// 简写方式
state= {
isHot:false,
wind:"大风"
}
// 箭头函数没有自己this,会找外层函数的this
changeWeather=()=>{
console.log("此处修改isHot的值")
console.log(this)
const isHot =this.state.isHot;
this.setState({isHot:!isHot})
}
render(){
console.log(this)
// 不要直接写demo()调用函数,会直接将函数的返回值赋值给onClick
// 若点击事件方法写在了类中,需要用this才能调用到
return <h2 onClick={this.changeWeather}>今天天气很{this.state.isHot ? '炎热' : '凉爽'}</h2>
}
}
/** 渲染到页面*/
ReactDOM.render(<MyComoonent/>,document.getElementById("test"))
// 使用that在构造器里接收this指向可行,但不建议
// function changeWeather(){
// console.log("此处修改isHot的值")
// console.log(that)
// // 注意这里使用this娶不到state的值
// }
// const title =document.getElementById("title")
// title.addEventListener("click",()=>{
// console.log("标题被点击了")
// })
// const title =document.getElementById("title")
// title.οnclick= ()=>{
// console.log("标题被点击了")
// }
</script>
</body>
展开运算符
<script>
let arr1=[1,3,5,7,9]
let arr2=[2,4,6,8,10]
console.log(...arr1) //展开一个数组输出
let arr3=[...arr1,...arr2] //合并两个数组
console.log(...arr3)
// 当不知道具体有多少个参数时
function sum(...numbers){
return numbers.reduce((pre,cur)=>{
return pre+cur
})
}
console.log(sum(1,2,3,4))
let p={name:'TOM',age:18,sex:"男"}
// console.log(...p) 报错,展开运算符不能直接展开对象
// 改变p,p1也跟着改变
let p1=p;
// 使用花括号表示复制一个对象
let p2={...p}
p.name="jerry"
console.log(p1)
// {name: 'jerry', age: 18, sex: '男'}
console.log(p2)
// {name: 'TOM', age: 18, sex: '男'}
</script>
组件三大核心属性-props
类式组件使用props
<body>
<!--准备容器 -->
<div id="test"></div>
<div id="test1"></div>
<div id="test2"></div>
<!-- 引入Staticfile CDN 的 React CDN 库 -->
<!--React核心库 -->
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<!--支持React操作Dom -->
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<!-- 生产环境中不建议使用 -->
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
<!-- 对组件标签进行限制 -->
<script src=" https://cdn.staticfile.org/prop-types/15.6.1/prop-types.js"></script>
<script type="text/babel">
/** 创建类式组件*/
// let that;
class MyComoonent extends React.Component{
// 三大核心属性 props
// 简写方式
static propTypes={
// 目前这种写法已经被弃用
// name:React.PropTypes.String.isRequired,
//需要引入prop-type.js
name:PropTypes.string.isRequired,
age:PropTypes.number,
speak:PropTypes.func,
}
// 对props属性默认值进行限制
static defaultProps={
sex:"不男不女",
// age:18
}
render(){
console.log(this)
// 解构赋值
const {name,age,sex}=this.props
return (
<ul>
<li>姓名:{name} </li>
<li>年龄: {age} </li>
<li>性别: {sex} </li>
</ul>
)
// return (
// <ul>
// <li>姓名:{this.props.name} </li>
// <li>年龄: {this.props.age} </li>
// <li>性别: {this.props.sex} </li>
// </ul>
// )
}
}
// 对props属性属性类型进行限制
// MyComoonent.propTypes={
// // 目前这种写法已经被弃用
// // name:React.PropTypes.String.isRequired,
// //需要引入prop-type.js
// name:PropTypes.string.isRequired,
//
// age:PropTypes.number,
// speak:PropTypes.func,
// }
// // 对props属性默认值进行限制
// MyComoonent.defaultProps={
// sex:"不男不女",
// // age:18
// }
/** 渲染到页面*/
ReactDOM.render(<MyComoonent name="tom" age={18} sex="女" speak={speak}/>,document.getElementById("test"))
ReactDOM.render(<MyComoonent name="tom1" age={19} sex="女"/>,document.getElementById("test1"))
// ReactDOM.render(<MyComoonent name="tom2" age="183" sex="女"/>,document.getElementById("test2"))
const p={name:"TOM",age:18,sex:"男"}
// ReactDOM.render(<MyComoonent name={p.name} age={p.age} sex={p.sex}/>,document.getElementById("test2"))
// 上面写法的语法糖,注意此处展开运算符不能展开对象,是因为React的作用才能这样使用
ReactDOM.render(<MyComoonent {...p}/>,document.getElementById("test2"))
function speak(){
console.log("++++++++")
}
</script>
</body>
函数式组件使用props
<script type="text/babel">
function MyComoonent(props){
return (
<ul>
<li>姓名:{props.name} </li>
<li>年龄: {props.age} </li>
<li>性别: {props.sex} </li>
</ul>
)
}
ReactDOM.render(<MyComoonent name="tom" age={18} sex="女"/>,document.getElementById("test"))
</script>
组件三大核心属性-refs
字符串形式(不被推荐使用–)
<body>
<!--准备容器 -->
<div id="test"></div>
<div id="test1"></div>
<div id="test2"></div>
<!-- 引入Staticfile CDN 的 React CDN 库 -->
<!--React核心库 -->
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<!--支持React操作Dom -->
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<!-- 生产环境中不建议使用 -->
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
<!-- 对组件标签进行限制 -->
<script src=" https://cdn.staticfile.org/prop-types/15.6.1/prop-types.js"></script>
<script type="text/babel">
class MyComoonent extends React.Component{
//点击事件
showData=()=>{
console.log("+++++++++++++++")
// 弃用
// <input id="input1" type="text" placeholder="点击按钮提示数据" />
// const input=document.getElementById('input1')
// alert(input.value)
console.log(this.refs.input1)
const {input1} =this.refs
alert(input1.value)
}
showData2=()=>{
console.log(this.refs.input2)
const {input2} =this.refs
alert(input2.value)
}
render(){
return(
<div>
<input ref="input1" type="text" placeholder="点击按钮提示数据" />
<button ref="button" onClick={this.showData}>点我提示左侧数据</button>
<input ref="input2" onBlur= {this.showData2} type="text" placeholder="失去焦点提示数据" />
</div>
)
}
}
ReactDOM.render(<MyComoonent />,document.getElementById("test"))
</script>
</body>
回调形式
<body>
<!--准备容器 -->
<div id="test"></div>
<div id="test1"></div>
<div id="test2"></div>
<!-- 引入Staticfile CDN 的 React CDN 库 -->
<!--React核心库 -->
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<!--支持React操作Dom -->
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<!-- 生产环境中不建议使用 -->
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
<!-- 对组件标签进行限制 -->
<script src=" https://cdn.staticfile.org/prop-types/15.6.1/prop-types.js"></script>
<script type="text/babel">
class MyComoonent extends React.Component{
//点击事件
showData=()=>{
const {input1} =this
console.log(input1.value)
}
showData2=()=>{
const {input2} =this
console.log(input2.value)
}
render(){
return(
<div>
<input ref={(currentNode)=>{this.input1=currentNode}} type="text" placeholder="点击按钮提示数据" />
<button ref="button" onClick={this.showData}>点我提示左侧数据</button>
<input ref={(c)=>{this.input2=c}} onBlur= {this.showData2} type="text" placeholder="失去焦点提示数据" />
</div>
)
}
}
ReactDOM.render(<MyComoonent />,document.getElementById("test"))
</script>
</body>
解决回调函数执行两次的方法
<body>
<!--准备容器 -->
<div id="test"></div>
<div id="test1"></div>
<div id="test2"></div>
<!-- 引入Staticfile CDN 的 React CDN 库 -->
<!--React核心库 -->
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<!--支持React操作Dom -->
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<!-- 生产环境中不建议使用 -->
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
<!-- 对组件标签进行限制 -->
<script src=" https://cdn.staticfile.org/prop-types/15.6.1/prop-types.js"></script>
<script type="text/babel">
class MyComoonent extends React.Component{
//点击事件
showData=()=>{
const {input1} =this
console.log(input1.value)
}
showData2=()=>{
const {input2} =this
console.log(input2.value)
}
//将内联回调函数写成class绑定函数的形式,可以避免回调函数执行两次
classTest=(c)=>{
this.input2=c
}
render(){
return(
<div>
{/* 这里的回调函数每次渲染会执行两次*/}
<input ref={(currentNode)=>{this.input1=currentNode}} type="text" placeholder="点击按钮提示数据" />
<button ref="button" onClick={this.showData}>点我提示左侧数据</button>
<input ref={ this.classTest} onBlur= {this.showData2} type="text" placeholder="失去焦点提示数据" />
</div>
)
}
}
ReactDOM.render(<MyComoonent />,document.getElementById("test"))
</script>
</body>
createRef形式
<script type="text/babel">
class MyComoonent extends React.Component{
myRef=React.createRef()
//点击事件
showData=()=>{
console.log(this.myRef.current.value)
}
//当操作的数据源为当前节点的数据时可以使用event事件获取数据,无需使用refs
showData2=(event)=>{
console.log(event.target.value)
}
render(){
return(
<div>
{/* 这里的回调函数每次渲染会执行两次*/}
<input ref={this.myRef} type="text" placeholder="点击按钮提示数据" />
<button ref="button" onClick={this.showData}>点我提示左侧数据</button>
<input onBlur={this.showData2} type="text" placeholder="点击按钮提示数据" />
</div>
)
}
}
ReactDOM.render(<MyComoonent />,document.getElementById("test"))
</script>
受控组件与非受控组件
非受控组件:现用现取 使用ref获取数据
<script type="text/babel">
class MyComoonent extends React.Component{
submit=(event)=>{
event.preventDefault();//阻止表单提交默认事件
const {username,password} = this
console.log(username.value,password.value)
}
render(){
return(
<form action="http://www.atguigu.com" onSubmit={this.submit}>
用户名:<input ref={c=>this.username=c} type="text" name="username"/>
密码:<input ref={c=>this.password=c} type="password" name="password"/>
<button>登录</button>
</form>
)
}
}
ReactDOM.render(<MyComoonent />,document.getElementById("test"))
</script>
受控组件:将数据交由state维护
class MyComoonent extends React.Component{
state={
username: '',
password:''
}
submit=(event)=>{
event.preventDefault();//阻止表单提交默认事件
const {username,password} = this.state
console.log(username,password)
}
saveUsername=(event)=>{
console.log(event.target.value)
this.setState({username:event.target.value})
}
savePassword=(event)=>{
console.log(event.target.value)
this.setState({password:event.target.value})
}
render(){
return(
<form action="http://www.atguigu.com" onSubmit={this.submit}>
用户名:<input onChange={this.saveUsername} type="text" name="username"/>
密码:<input onChange={this.savePassword} type="password" name="password"/>
<button>登录</button>
</form>
)
}
}
ReactDOM.render(<MyComoonent />,document.getElementById("test"))
</script>
函数柯里化
<script type="text/babel">
class MyComoonent extends React.Component{
state={
username: '',
password:''
}
submit=(event)=>{
event.preventDefault();//阻止表单提交默认事件
const {username,password} = this.state
console.log(username,password)
}
//函数柯里化 、、函数复用
// saveFormData=(dataType)=>{
//
// return (event)=>{
// console.log(event.target.value)
// this.setState({[dataType]:event.target.value})
// }
// }
//不使用函数柯里化 、、函数复用
saveFormData=(dataType,value)=>{
return (event)=>{
console.log(event.target.value)
this.setState({[dataType]:event.target.value})
}
}
render(){
return(
<form action="http://www.atguigu.com" onSubmit={this.submit}>
用户名:<input onChange={(event)=>this.saveFormData("username",event.target.value)} type="text" name="username"/>
密码:<input onChange={this.saveFormData("password")} type="password" name="password"/>
<button>登录</button>
</form>
)
}
}
ReactDOM.render(<MyComoonent />,document.getElementById("test"))
</script>
React的生命周期