类
class Person{
//构造器方法,不一定必须要写
constructor(name,age){
//构造器中的this是谁? ————— 类的实例对象
this.name = name
this.age = age
}
}
class Student extends Person{
constructor(name, age, grade){
//如果A类继承了B类,且A类中写了构造器,那么A类构造器中的super是必须要调用的
super(name, age)
this.grade = grade
}
speak(){
consle.log("这是一个方法")
}
}
类式组件
class MyComponent extends React.Component{
render(){
super(props)
//初始化状态
this.state = {
isHot: false
}
return (
<div onClick={this.changeWeather}>{this.state.isHot}</div>
);
//自定义方法要用赋值语句+箭头函数的形式,这样相当于在MyComponent实例中追加了changeWeather方法
const changeWeather = ()=>{
//由于changeWeather是作为onClick的回调,所以不是通过实例调用的,是直接调用
//类中的方法默认开启了局部的严格模式,所以changeWeather(){}中的this为undefined
console.log(this)
}
}
}
//渲染到页面,会自动new MyComponent实例,并通过该实例调用原型上的render方法
ReactDOM.render(<MyComponent/>, document.getElementById('test'))
函数式组件
function Person (props){
const { name, age, sex } = props
return (
<ul>
<li>姓名: {name}</li>
<li>性别: {sex}</li>
<li>年龄: {age}</li>
</ul>
)
}
//渲染组件到页面
ReactDOM.render(<Person name="jerry" sex="女" age={18}/>, document.getElementById('test1')))
refs
组件内的标签可以定义ref属性来标识自己,回调里的参数指向当前所在的这个结点
class Demo extends React.Component{
/*
React.createRef调用后可以返回一个容器,该容器可以存储被ref所标识的结点
*/
myRef = React.createRef()
showData = () => {
const { input1 } = this
alert(input1.value)
}
showData2 = () => {
const { input2 } = this
alert(input2.value)
}
render(){
return(
<div>
<input ref={this.myRef} type="text" placeholder="点击按钮提示数据"/>
<button onClick={this.showData}>点我提示左侧数据</button>  
//把ref当前所处的结点挂在demo的实例对象上,并取名叫input2
<input ref={(currentNode) => {this.input2 = currentNode}} onBlur={this.showData2} type="text"/>
</div>
)
}
}
ReactDOM.render(<Demo a="1" b="2"/>, document.getElementById('test'))
高阶函数
class Demo extends React.Component{
// #region
/*
高阶函数:如果一个函数符合下面2个规范中的任何一个,那该函数就是高阶函数。
1.若A函数,接收的参数是一个函数,那么A就可以称之为高阶函数
2.若A函数,调用的返回值依然是一个函数,那么A就可以称之为高阶函数。
函数的柯里化:通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的函数编码形式
*/
state = {
username: '', //用户名
}
saveFormData = (dataType) => {
return (event) => {
this.setState({[dataType]: event.target.value})
}
}
showData2 = () => {
const { input2 } = this
alert(input2.value)
}
render(){
return(
<div>
<input onChange={this.saveFormData('username')} type="text" placeholder="点击按钮提示数据"/>
</div>
)
}
}
ReactDOM.render(<Demo a="1" b="2"/>, document.getElementById('test'))
路由组件与一般组件
1.写法不同:
一般组件: < Demo />
路由组件: < Route path=“/demo” component={Demo}/>
2.存放位置不同
一般组件:components
路由组件:pages
3.接收到的props不同
一般组件:写组件标签时传递了什么,就能收到什么
路由组件:接收到三个固定的属性:history、location、match
路由的严格匹配和模糊匹配
1.默认使用的是模糊匹配(【输入的路径】必须要包含【匹配的路径】,且顺序要一致)
2.开启严格匹配:<Route exact={true} path=“/about” component={About} / >
3.严格匹配不要随便开启,需要再开,有些时候开启会导致无法继续匹配二级路由
向路由组件传递参数
1.parmas参数
路由链接(携带参数):< link to=‘/demo/
m
.
i
d
/
{m.id}/
m.id/{m.title}/${m.content}’ >详情< /link>
注册路由(声明接收):< Route path=“/demo/:id/:title/:content” component={Test}/ >
接收参数: this.props.match.parmas
2.search参数
路由链接(携带参数):< link to=‘/demo/test?name=tom&age=18’ >详情< /link>
注册路由(无需声明,正常注册即可):< Route path=“/demo/test/” component={Test}/ >
接收参数: this.props.location.search
备注:获取到的search是urlencoded编码字符串,需要借助querystring解析
3.state参数
路由链接(携带参数):< link to{{‘/demo/test’, state:{name:‘tom’, age:18}}} >详情< /link>
注册路由(无需声明,正常注册即可):< Route path=“/demo/test/” component={Test}/ >
接收参数: this.props.location.state
备注:刷新也可以保留住参数
Context
一种组件间通信方式,常用于【祖组件】与【后代组件】间通信
使用
1)创建Context容器对象:
const XxxContext = React.createContext()
2)渲染子组件时,外面包裹xxxContext.Provider,通过value属性给后代组件传递数据:
<xxxContext.Provider value={数据}>
子组件
</xxxContext.Provider>
3)后代组件读取数据:
//第一种方式:仅适用于类式组件
static contextType = xxxContext //声明接收context
this.context //读取context中的value数据
第二种方式:函数组件与类组件都可以
<xxxContext.Consumer>
{
value =>( //value就是context中的value数据
要显示的内容
)
}
</xxxContext.Consumer>