学习React基础的第一天
Day two
1.组件实例的三大核心属性 1:State
- state(做状态管理的)
class Weather extends React.Component {
constructor(props) {
super(props) //不一定要写
this.state = { isHot: true } //当state里面的数据更新时,会重新调用render方法
}
render() {
const { isHot } = this.state
return <h2>今天天气真{isHot ? '炎热' : '凉快'}呀</h2>
}
}
ReactDOM.render(<Weather />, document.querySelector('#test'))
2.React中的事件绑定
class Weather extends React.Component {
constructor(props) {
super(props)
this.state = { isHot: true }
}
//react解析到组件的时候发现是class组件,就会去new这个class,让这个实例去调用render方法 所以render this指向这个类
render() {
const { isHot } = this.state
//推荐行内的事件绑定,但是注意写法格式 含义为将demo这个函数作为onClick事件的回调,当你点击的时候,React会帮你执行 onClick={demo()}这种形式的话,React解析到这里的时候会直接会调用这个函数拿到这个函数的返回值给onClick
return <h2 id="title" onClick={demo}>今天天气真{isHot ? '炎热' : '凉快'}呀</h2>
}
}
ReactDOM.render(<Weather />, document.querySelector('#test'))
function demo() {
console.log(111111);
},
3.类里面的注意点
- 类里面的方法会默认在局部开启严格模式!!!
- 类里面是可以直接写类似 a = 1, fn = () => {} 这样的赋值语句的,他们会作为实例自身的方法或属性存在,不在构造函数的原型对象上
4.类中方法的this
class Weather extends React.Component {
constructor(props) {
super(props)
this.state = { isHot: true }
}
render() { //
const { isHot } = this.state
return <h2 id="title" onClick={this.demo}>今天天气真{isHot ? '炎热' : '凉快'}呀</h2>
}
demo() {
//dmeo是放在Demo类的原型上的
//由于demo是作为onClick的回调,所以不是通过实例调用的,是直接调用
//类中·方法默认开启了局部的严格的模式,所以demo中的this为undefined
console.log(this); //undefined
}
}
ReactDOM.render(<Weather />, document.querySelector('#test'))
5.使用bind方法实现state状态更新步骤
//定义一个展示天气情况的组件
class Weather extends React.Component {
//constructor只调用一次
constructor(props) {
super(props)
this.state = { isHot: true }
//解决demo中的this指向问题
this.demo = this.demo.bind(this)
}
// 调用 1+n次
render() { //
const { isHot } = this.state
//调用的时候是普通调用 但是这个时候调用的函数是绑定在实例身上的方法,不是原型上的方法,而且已经用bind改变了this的指向了,
//换句话说就是这个实力上的方法始终指向的是这个实例
return <h2 id="title" onClick={this.demo}>今天天气真{isHot ? '炎热' : '凉快'}呀</h2>
}
//点几次就调用几次
//这个方法在构造函数的原型对象上
demo() {
//开启了严格模式
const ishot = this.state.isHot
//严重注意状态(state)不可以直接更改,必须要通过settate方法修改
//这个setState方法是来自React.Component这个类上的 是一种合并,不是替换!!!!
this.setState({ isHot: !ishot })
}
}
ReactDOM.render(<Weather />, document.querySelector('#test'))
6.精简版实现state状态更新
class Weather extends React.Component {
state = { isHot: true } //直接以赋值的形式写在class中是作为实例的一个属性的
render() {
//this指向的也是实例化对象
const { isHot } = this.state
return <h2 id="title" onClick={this.demo}>今天天气真{isHot ? '炎热' : '凉快'}呀</h2>
}
//以赋值的方式去写,是作为实例的一个方法,不是在对象原型上,而且因为是箭头函数,中的this指向的是自己的上下文(父级),也就是实例化对象,所以就不需要bind在demo方法中可以直接使用this就是实例化对象
demo = () => {
const ishot = this.state.isHot
this.setState({ isHot: !ishot })
}
}
ReactDOM.render(<Weather />, document.querySelector('#test'))
7.组件实例三大核心组件 2:props
class List extends React.Component {
render() {
const { name, sex, age } = this.props
return (
<ul>
<li>姓名: {name}</li>
<li>性别: {sex}</li>
<li>年龄: {age}</li>
</ul>
)
}
}
// ReactDOM.render(<List name="Tom" sex="女" age="18" />, document.querySelector('#test1'))
const obj = { name: "jerry", sex: "男", age: "20" }
//注意这里的{...obj} 外层的{}表示里面是一个js表达式,里面的...不是拓展运算符!!!
//是react加上babel才可可以使用的语法糖
//批量传递标签属性
ReactDOM.render(<List {...obj} />, document.querySelector('#test2'))
8. … 的注意点
- 在react的props传参位置使用代表的是这里的语法糖,将这个对象转换为注释那里的样子
- js原生中的…分为两种,一种为拓展运算符,一种为剩余参数
- 注意对象{}是不可以使用…展开的,因为他没有部署iterator接口
- 特殊情况为{…obj},这个表达式的意思为,对象的复制(首层深拷贝),而不是展开!!
9.对props属性做限制
//要多导入一个类型限制的包
<script src="./prop-types.js"></script>
List.propTypes = { //大小写区分好
name: PropTypes.string.isRequired, //字符且必须
age: PropTypes.number, //数字类型
speak: PropTypes.func //限定为函数类型
}
//默认值设置
List.defaultProps = {
sex: '不男不女',
age: 18
}
ReactDOM.render(<List name='nihao' sex="女" age={18} speak={speak} />, document.querySelector('#test1'))
function speak() {
console.log('hahaha');
}
10.constructor的使用注意点
- 在 React 组件挂载之前,会调用它的构造函数。在为 React.Component 子类实现构造函数时,应在其他语句之前调用
super(props)
。否则在constructor中不用直接使用this.props
会出现undefined 的情况 - 通常,在 React 中,构造函数仅用于以下两种情况:
11.props的简写和注意事项
- 因为加限制的propTypes 和 defaultProps 必须加在这个构造函数上
- 可以使用static关键字把这两个属性直接写在class中,作为这个类的静态属性,即可实现简写
- 组件标签的所有属性都保存在props中
- 不要直接修改props的值,会报错,它是一个只读属性
12.函数组件使用props(利用参数)
//函数组件使用不了状态(state) 和refs 但是用hooks的话就可以使用
function Demo(props) {
//利用了函数可以接收参数的特性接收props
const { name, age, sex } = props
return (
<ul>
<li>姓名: {name}</li>
<li>性别: {sex}</li>
<li>年龄: {age + 1}</li>
</ul>
)
}
//和类中做限制的普通方法一致
Demo.propTypes = {
name: PropTypes.string.isRequired, //字符且必须
age: PropTypes.number, //数字类型
}
//默认值设置
Demo.defaultProps = {
sex: '不男不女',
age: 18
}
ReactDOM.render(<Demo name='nihao' age='18' sex="男" />, document.querySelector('#test1'))
13.ref的使用方式
- 字符型 : 不推荐使用,效率很低(后续可能会丢弃)
- 回调函数型: (推荐使用,官网说了,没啥影响)
- 如果
ref
回调函数是以内联函数(ref ={(currentNode) => {this.xxxx = currentNode}})的方式定义的,在更新过程中(state状态改变,render重新渲染后)它会被执行两次,第一次传入参数null
,然后第二次会传入参数 DOM 元素。这是因为在每次渲染时会创建一个新的函数实例,所以 React 清空旧的 ref 并且设置新的。 - 通过将 ref 的回调函数定义成 class的绑定函数的方式可以避免上述问题,但是大多数情况下它是无关紧要的。
- React.createRef() 专人专用 React.createRef这个函数被调用之后会返回一个容器,可以存储被ref标识的节点
14.到现在为止用到的几个API
- React.createElement(tag, props, children) // 可以用来创建虚拟DOM
- ReactDOM.render(VDOM, ‘dom容器’) // 将虚拟DOM渲染到页面上
- React.createRef() //返回一个可以用来存储被ref标识的节点的容器
- 构造函数.propTypes / PropTypes(用来做props类型的限制的js文件) / 构造函数.defaultProps(用来设置默认值的)
- RactDOM.unmountComponentAtNode(node) //用来销毁一个dom容器中的组件
- this.setState() //修改状态(状态不能直接修改)
- this.farceUpdate() //强制更新
15.React中的事件处理
- 通过onXxxx属性指定的事件处理函数(注意大小写)
- React使用的是自定义(合成)事件(不是原生的DOM事件) —— 为了更好的兼容性
- React中的事件是通过事件委托的方式来处理的(委托给组件最外层的元素)—— 为了更高效
- 在事件处理函数中可以接收到事件event,通过event.target可以获取到触发事件的那个DOM元素—— 不要过度的使用ref打标识
16.受控组件于非受控组件
在HTML中,标签、