函数式组件
准备好容器
<div id='test'></div>
<script type = "tsext/babel">
//1. 创建函数式组件
function MyComponent() {
console.log(this)
//这个this是undefined,由于jsx代码经过babel翻译,
//开启了严格模式,严格模式下禁止自定义的函数指向window
//所以这个this指向了undefined
return <h2>我式用函数式定义的组件,适用于【简单组件】的定义</h2>
}
//2. 渲染组件到页面,记得jsx标签必须闭合
ReactDOM.render(<MyComponent/>,document.getElementById('test'))
</script>
执行了React DOM……之后发生了什么?
- React解析组件标签,找到了MyComponet组件
- 发现组件时使用函数定义的,随后调用该函数,将返回的虚拟DOM转为真实DOM,随后呈现在页面中
类的基本知识
//创建一个Person类
class Person {
//构造器方法
constructor(name,age){
this.name = name
this.age = age
}
//一般方法,除了构造器以外,自己写的都叫一般方法
speak(){
//speak方法放在了类的原型对象上,提供实例使用
//通过person实例调用speak时,speak中的this就是person实例
console.log("我叫${this.name}我的年龄是${this.age}")
//${}es6模板字符串
}
}
const p1 = new Person('tom',18);
const p2 = new Person('jerry',18);
console.log(p1);
console.log(p2);
p1.speak();
p2.speak();
类的继承
```javascript
//创建一个Student类,继承person类
class Student extends Person {
//构造器方法
constructor(name,age,grade){
//super必须放在最前面
super(name,age)
this.grade = grade
}
speak() {
//重写父类继承过来的speak方法
console.log("我叫${this.name}我的年龄是${this.age}我读${this.grade}年级")
}
study() {
//study放在类的原型对象,供实例使用
//通过Student对象调用时,this指向实例对象
console.log("我很努力学习")
}
}
const s1 = new Student("小明",17);
console.log(s1);
s1.speak();
总结
- 类的构造器不是必须写的,要对实例进行一些初始化的操作,如添加指定属性时才写
- 如果A类继承了B类,A类中写了构造器,那么A类构造器中的super方法是必须要调用的,且必须放在最前面
- 类中所定义的方法,都是放在了类的原型对象上,供实例使用
类式组件
<script type="text/babel">
//1. 创建类式组件,类必须继承React内置的类React.Component
class MyComponent extends React.Component{
//2. 必须写render,并且render必须有返回值
render() {
//render放在MyComponent的原型对象上,供实例使用
//render中的this指向MyComponent的实例对象(MyComponent组件实例对象)
console.log(this);
return <h2>我式用函数式定义的组件,适用于【复杂组件】的定义</h2>
}
}
//渲染组件到页面
ReactDOM.render(<MyComponent />,document.getElementById('test'));
</script>
执行了React DOM……之后发生了什么?
- React解析组件标签,找到了MyComponet组件
- 发现组件时使用类定义的,随后new出来该类的实例,并通过该实例调用到原型上的render方法
- 将render返回的虚拟DOM转为真实DOM,随后呈现在页面中
复杂组件 简单组件
如果组件有状态,就是复杂组件
没有状态则是,简单组件
- 组件状态驱动页面
组件实例的三大核心属性
旧版本中函数式组件没有这三个属性
state
<script type="text/babel">
//1. 创建组件
class Weather extends React.Component {
constructor(props) {
super(props);
this.state = { isHot: true };
}
render() {
const { isHot } = this.state;//解构赋值
return <h1>今天天气很{isHot ? "炎热" : "凉爽"}</h1>;
}
}
ReactDOM.render(<Weather />, document.getElementById("test"));
</script>
React事件的绑定
类中方法中的this
类中所有定义的方法,在局部都开启了严格模式
<script type="text/babel">
//1. 创建组件
class Weather extends React.Component {
constructor(props) {
super(props);
this.state = { isHot: true };
//解决changeWeather中this指向问题
this.changeWeather = this.changeWeather.bind(this);
}
render() {
const { isHot } = this.state;
return (
<h1 id="title" onClick={this.changeWeather}>
今天天气很{isHot ? "炎热" : "凉爽"}
</h1>
);
}
changeWeather() {
//changeWeather放在了weather的原型对象上,供实例使用
//【通过weather的实例】调用changeWeather时,this就是weather实例
//由于changeWeather是作为onclick的回调,所以不是通过实例调用的,是直接调用
//类中的方法默认开启了局部的严格模式,所以changeweather中的this是undefined
alert("Hello world!");
this.state.isHot = false;
console.log(this);
}
}
ReactDOM.render(<Weather />,document.getElementById("test"));
</script>
setState
React状态中的数据不能够直接更改,要借助一个内置的API修改——setState
- setState更新是一种合并,不是替换。
- 构造函数只调用1次,render调用1+n次
- changeWeather点几次调用几次
<script type="text/babel">
//1. 创建组件
class Weather extends React.Component {
constructor(props) {
//构造器调用一次
super(props);
this.state = { isHot: true };
//解决changeWeather中this指向问题
this.changeWeather = this.changeWeather.bind(this);
}
//render调用1+n次
render() {
const { isHot } = this.state;
return (
<h1 id="title" onClick={this.changeWeather}>
今天天气很{isHot ? "炎热" : "凉爽"}
</h1>
);
}
//change weather点几次调几次
changeWeather() {
//changeWeather放在了weather的原型对象上,供实例使用
//【通过weather的实例】调用changeWeather时,this就是weather实例
//由于changeWeather是作为onclick的回调,所以不是通过实例调用的,是直接调用
//类中的方法默认开启了局部的严格模式,所以changeweather中的this是undefined
//严重注意!!状态不可以直接更改,下面这行就是直接更改
// this.state.isHot = !isHot;
//严重注意!!要借助一个内置的API更改,setState,且更新是一种合并,不是替换
const isHot = this.state.isHot; //回去原来的isHot值
this.setState({ isHot: !isHot });
console.log(this);
}
}
ReactDOM.render(<Weather />, document.getElementById("test"));
</script>
state简写
- 自定义的方法要写成:赋值语句 + 箭头函数
- 解决this的问题
- state当作属性直接写出来
<script type="text/babel">
class Weather extends React.Component {
//初始化状态
state = { isHot: true };
render() {
const { isHot } = this.state;
return (
<h1 id="title" onClick={this.changeWeather}>
今天天气很{isHot ? "炎热" : "凉爽"}
</h1>
);
}
//自定义方法——要用赋值语句+箭头函数
changeWeather = () => {
const isHot = this.state.isHot;
this.setState({ isHot: !isHot });
}
}
ReactDOM.render(<Weather />, document.getElementById("test"));
</script>
总结
- state是组件对象最重要的属性,它的值是一个对象
- 组件被成为”状态机“,通过更新组件的state来更新对应页面显示(重新渲染组件)
- 强烈注意!!
3.1 组件中render方法中的this为组件实例对象
3.2 组件中自定义的方法中this为undefiend
3.2 a. 强制绑定this:通过函数对象的bind()
3.2 b. 赋值语句 + 箭头函数
3.3 状态数据不能直接修改或更新,必须通过setState更新