目录
什么是组件?
创建组件的两种方式
2.类组件
提取组件
组件的状态
实例属性方法
事件绑定this指向的问题,有以下几种方法
?表单的受控和非受控
什么是组件?
组件就是页面中的一部分,使用 React 就是在用组件,而所谓的组件化开发就是采用分而治之的思想来管理繁杂的页面逻辑。
特点:独立,可复用,可组合
创建组件的两种方式
1.函数式组件
通过函数创建出来的组件,又称简单组件或无状态组件
本质上来说就是一个js函数
使用的步骤有两步:
1.先定义?
a,函数名称必须以大写字母开头。
b,必须有返回值,返回值表示该组件的结构,如果不想渲染任何内容,可以
?2.再使用
a,<函数名/> ,单标签闭合。
b,<函数名></函数名> ,双标签。
***注意点:函数式 组件里面this指向的是undefined,因为Babel 编译后的代码开启了严格模式
import ReactDOM from 'react-dom'
function Hello() {
return <div>这是第一个函数组件</div>
}
// const Hello = () => <h1>这是一个函数组件!</h1>;
// 把函数的名字作为标签名进行渲染,可以使用单闭合,或双标签的形式
ReactDOM.render(<Hello />, document.getElementById('root'))
react解析 <Hello />标签发现是大写开头的话会被当成组来进行解析,解析的时候又发现其是一个函数式组件,随后会调用此函数,将返回的虚拟 DOM 转为真实 DOM,并渲染到页面中。
2.类组件
它也有两个步骤
1.先定义
a,使用 ES6 语法的 class 创建的组件,又称复杂组件或有状态组件。
b,类名称也必须要大写字母开头。
c,类组件应该继承?React.Component ?父类,从而可以使用父类中提供的方法或者属性。
d,类组件必须提供?render() ?方法,此方法中的 this 指向此组件的实例对象,此方法中必须要有 return 返回值。
2.再使用
class Hello extends React.Component {
render() {
return <div>这是第一个类组件</div>
}
}
ReactDOM.render(<Hello />, document.getElementById('root'))
ReactDOM.render()解析类式组件的过程:
react解析 <Hello />标签发现是大写开头的话会被当成组来进行解析,解析的时候又发现其是一个类组件,会自动的new出来该实例,并在该实例调用原型上的render()方法,将render方法返回的虚拟DOM转为真实DOM,并渲染到页面上
提取组件
1.默认导出---------------在 App.js 中通过 export default 默认导出该组件。
2.默认导入---------------在 index.js 中通过 import 默认导入 App 组件。
组件的状态
状态就是用来描述事物在某一时刻数据
特点:
可以被修改,修改之后状态会更新
作用
-
保存数据。 -
数据变化响应到视图(React 包内部的操作)
使用的步骤是:
1.先定义
第一种方式:在 constructor 中通过?this.state = {} 。
第二种方式:通过 state 来定义状态,state 对应的值必须是一个对象。
2.再使用
一般在render函数内部使用? ?--- this.state.xxx
还可以修改
语法:
this.setState({ 属性:修改成什么 })
注意点:
不要直接修改原数据
实例属性方法
class App {
constructor() {
// 实例属性
this.age = 18
// this.sex = '男' // #1
}
// 实例属性,等价于 #1
sex = '男'
// 实例方法
handleClick = () => {}
}
?原型属性方法
class App {
// 原型方法
handleClick(){}
}
?静态属性方法
class App {
// 静态属性
static age = 18
}
// 静态属性
App.sex = '男'
console.log(App.age) // 18
事件绑定this指向的问题,有以下几种方法
1.使用高阶函数/函数科里化
class App extends React.Component {
state = {
count: 0,
}
handleClick() {
// 这里的 this 指向是什么?那就看是谁调用的!
return () => {
console.log(this.state.count)
}
}
render() {
return (
<div>
<h2>计数器:{this.state.count}</h2>
<button onClick={this.handleClick()}>+1</button>
</div>
)
}
}
2. 包裹一层箭头函数
class App extends Component {
state = {
count: 0,
}
handleClick() {
console.log(this.state.count)
}
render() {
return (
<div>
<h2>计数器:{this.state.count}</h2>
<button onClick={() => this.handleClick()}>+1</button>
</div>
)
}
}
3.使用bind---改变this指向
class App extends Component {
state = {
count: 0,
}
handleClick() {
console.log(this.state.count)
}
render() {
return (
<div>
<h2>计数器:{this.state.count}</h2>
<button onClick={this.handleClick.bind(this)}>+1</button>
</div>
)
}
}
?4.通过赋值语句往实例上面添加箭头函数---一般使用这个比较多
class App extends Component {
state = {
count: 0,
}
handleClick = () => {
console.log(this.state.count)
}
render() {
return (
<div>
<h2>计数器:{this.state.count}</h2>
<button onClick={this.handleClick}>+1</button>
</div>
)
}
}
?5.在构造函数中再创建一个实例方法,和原型方法公用一个函数体
class App extends React.Component {
constructor() {
super()
this.state = {
count: 0,
}
// 1. 往实例自身上又挂载了一个 handleClick 函数
// 2. 此函数的函数体是通过原型上 handleClick 函数生成的新函数
// 3. 并把原型上 handleClick 函数中的 this 通过 bind 绑定为了 this,而这里构造函数中的 this 正是实例对象
// 4. 其实点击的时候调用的是这个构造函数 handleClick(就近原则),而这个构造函数中的 handleClick 执行的是原型上的 handleClick 的函数体
this.handleClick = this.handleClick.bind(this)
}
handleClick() {
console.log(this.state.count)
}
render() {
return (
<div>
<h2>计数器:{this.state.count}</h2>
<button onClick={this.handleClick}>+1</button>
</div>
)
}
}
?表单的受控和非受控
一.受控表单组件
1.第一类:
包含input,textarea,select
1. 在 state 当中定义变量
2. 把这个变量和 表单元素的 value 进行绑定
3. 给表单元素绑定 onChange 事件
4. 事件回调里面?this.setState({ 变量:e.target.value })
?2. 第二类
radio? , checkbox
和第一类的差异,绑定的是 checked 属性
?再者就是优化---通过掌握自定义属性优化代码
二.非受控表单组件
import React, { Component } from 'react'
export default class App extends Component {
// Step1
input = React.createRef()
handleChange = () => {
// Step3
console.log(this.input.current.value)
}
render() {
return (
<div>
{/* Step2 */}
<input ref={this.input} type='text' placeholder='输入内容' onChange={this.handleChange} />
</div>
)
}
}
|