一、React 创建组价组件的两种方式
1.函数组件
- 使用JS 的函数或者箭头函数创建的组件
- 为了区分普通标签,函数组件的名称必须 大写字母开头
- 函数组件
必须有返回值,表示该组件的结构 - 如果返回值为
null,表示不渲染任何内容 - 函数组件没有状态
2.类组件
- 使用
ES6的class语法创建组件-
组件的名称必须是 大写字母开头
-
类组件应该继承
React.Component父类,从而可以使用父类中提供的方法或者属性 -
类组件必须提供
render方法 -
render方法必须有返回值,表示该组件的结构 -
类组件有状态
-
二、组件的基本使用
1、找一处风水宝地,创建启动项目
- npx create-react-app react-com
- cd react-com
- yarn start 或 npm start 或 npm run start
2、保留入口文件 src/index.js 和 出口文件 src/App.js
3、index.js是入口文件,我们不动它
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
)
4、App.js 里面创建组件并导出
import React from 'react'
// ◆函数组件 1:使用函数创建组件
function FunCom1() {
return <div>我是 函数组件 FunCom1</div>
}
// ◆函数组件 2:使用箭头函数创建组件
const FunCom2 = () => {
return <div>我是 函数组件 FunCom2</div>
}
// ◆类组件
class ClassCom extends React.Component {
render() {
return <div>我是一个 类组件 ClassCom </div>
}
}
function App() {
return (
<div className="App">
app
<FunCom1></FunCom1>
<FunCom2></FunCom2>
<ClassCom></ClassCom>
</div>
)
}
export default App
5、项目跑起来,看页面效果
三、组件的进阶使用
思考分析:
如果所有的组件都写在 App.js 里面,组件多了,会非常混乱。所以,我们的最优解是把每个组件放到单独的 JS 文件中,下面来试一试。
1.新建文件夹及文件
- src/components/FunCom1.js
- src/components/FunCom2.js
- src/components/ClassCom.js
2.子组件抽离到成单独的 js 文件
FunCom1.js 普通函数组件
// ◆函数组件 1:使用普通函数创建组件
function FunCom1() {
return <div>我是 函数组件 FunCom1</div>
}
export default FunCom1
FunCom2.js 箭头函数组件
// ◆函数组件 2:使用箭头函数创建组件
const FunCom2 = () => {
return <div>我是 函数组件 FunCom2</div>
}
export default FunCom2
ClassCom.js 类组件
import React from 'react'
// ◆类组件
class ClassCom extends React.Component {
render() {
return <div>我是一个 类组件 ClassCom </div>
}
}
export default ClassCom
3.App.js 导入子组件
import React from 'react'
// 导入函数组件和类组件
import FunCom1 from './components/FunCom1'
import FunCom2 from './components/FunCom2'
import ClassCom from './components/ClassCom'
// ◆法1
// function App() {
// return (
// <div className="App">
// app
// <FunCom1></FunCom1>
// <FunCom2></FunCom2>
// <ClassCom></ClassCom>
// </div>
// )
// }
// ◆法2
// const App = () => {
// return (
// <div className="App">
// app
// <FunCom1></FunCom1>
// <FunCom2></FunCom2>
// <ClassCom></ClassCom>
// </div>
// )
// }
// ◆法3(一般用类组件比较多)
class App extends React.Component {
render() {
return <div className="App">
app
<FunCom1></FunCom1>
<FunCom2></FunCom2>
<ClassCom></ClassCom>
</div>
}
}
export default App
4.页面依然呈现
四、研究类组件 (ClassCom.js)
类组件通过
state提供数据,只有类组件才有状态,函数组件没有状态
1.state 的使用
第一种方法:state 就是 状态
- 定义状态:
state={} - 渲染状态:
this.state.变量名
import React from 'react'
// ◆类组件
class ClassCom extends React.Component {
// ◆ state 的 写法1:
state = {
message: '快乐呀!'
}
render() {
return <div>我是一个 类组件 ClassCom {this.state.message} </div>
}
}
export default ClassCom
第二种方法:在构造函数中用 this.state= {} 来做初始化
- 定义状态:
constructor(){ super(); this.state = {} } - 渲染状态:
this.state.变量名
import React from 'react'
// ◆类组件
class ClassCom extends React.Component {
// ◆ state 的 写法2:
constructor() {
super()
this.state = {
message: '你好呀!'
}
}
render() {
return <div>我是一个 类组件 ClassCom {this.state.message} </div>
}
}
export default ClassCom
2.函数调用执行顺序问题
- 调用不带小括号:点击才会触发
{this.clickHandler1} - 调用带小括号,写成箭头函数形式:点击才会触发
{()=>{this.clickHandler2()}} - 调用带小括号:一进入页面就触发,可用于发请求等(点击不触发)
{this.clickHandler3}
import React from 'react'
// ◆类组件
class ClassCom extends React.Component {
// ◆ 点击事件函数
clickHandler1() {
console.log('点我呀1!')
}
clickHandler2() {
console.log('点我呀2!')
}
clickHandler3() {
console.log('点我呀3!')
}
render() {
return <div>我是一个 类组件 ClassCom
<br />
<button onClick={this.clickHandler1}>按钮1</button>
<button onClick={() => { this.clickHandler2() }}>按钮2</button>
<button onClick={this.clickHandler3()}>按钮3</button>
</div>
}
}
export default ClassCom
3.关于 this 指向问题
1.绑定点击事件,打印 this
import React from 'react'
// ◆类组件
class ClassCom extends React.Component {
// ◆ 点击事件函数
clickHandler1() {
console.log(this,'点我呀1!')
}
clickHandler2() {
console.log(this,'点我呀2!')
}
clickHandler3() {
console.log(this,'点我呀3!')
}
render() {
return <div>我是一个 类组件 ClassCom
<br />
<button onClick={this.clickHandler1}>按钮1</button>
<button onClick={() => { this.clickHandler2() }}>按钮2</button>
<button onClick={this.clickHandler3()}>按钮3</button>
</div>
}
}
export default ClassCom
2.思考分析 this:
通过测试打印 this 发现,以 this.clickHandler1 的形式调用, this 指向 undefined,而其他的可以打印 this,这是为什么?
- 事件处理程序的函数式函数调用模式,在严格模式下,
this指向undefined render函数是被组件实例调用的,因此render函数中的this指向当前组件
4.解决类组件中 this 指向 undefined 的问题
法1:函数改成箭头函数(推荐)
import React from 'react'
// ◆类组件
class ClassCom extends React.Component {
// ◆法1:解决 this 指向 undefined 问题
clickHandler = () => {
console.log(this, 'clickHandler');// ◆改成箭头函数就可以打印 this
}
render() {
console.log(this, 'render');// ◆这里一进入页面就可以打印一次 this
return <div>我是一个 类组件 ClassCom
<br />
<button onClick={this.clickHandler}>按钮</button>
</div>
}
}
export default ClassCom
法2:在 constructor 里面通过 bind 修改 this 指向
import React from 'react'
// ◆类组件
class ClassCom extends React.Component {
// ◆法2:解决 this 指向 undefined 问题
constructor() {
super()
this.clickHandler = this.clickHandler.bind(this)// ◆ 修改 this指向
}
clickHandler() {
console.log(this, 'clickHandler')// ◆在 constructor 中改了 this 这里就可以打印
}
render() {
console.log(this, 'render')// ◆这里一进入页面就可以打印一次 this
return <button onClick={this.clickHandler}>按钮</button>
}
}
export default ClassCom
法3:调用的时候,通过 bind 修改 this 指向
import React from 'react'
// ◆类组件
class ClassCom extends React.Component {
// ◆法3:解决 this 指向 undefined 问题
clickHandler(){
console.log(this,'clickHandler');// ◆调用的时候改了 this 这里就可以打印
}
render() {
console.log(this,'render');// ◆这里一进入页面就可以打印一次 this
return <button onClick={this.clickHandler.bind(this)}>按钮</button>
}
}
export default ClassCom
法4:调用时以箭头函数的形式调用
import React from 'react'
// ◆类组件
class ClassCom extends React.Component {
// ◆法5:解决 this 指向 undefined 问题
clickHandler(){
console.log(this,'clickHandler');// ◆调用时以箭头函数的形式调用,就可以打印 this
}
render() {
console.log(this,'render');// ◆这里一进入页面就可以打印一次 this
return <button onClick={()=>{this.clickHandler()}}>按钮</button>
}
}
export default ClassCom
5.组件的状态-修改状态
法1:this.setState({})
import React from 'react'
// ◆类组件
class ClassCom extends React.Component {
state={
num:1
}
// ◆ 点击事件函数
clickHandler=()=> {
// 法1:this.stState({ })
this.setState({
num:this.state.num+1
})
}
render() {
console.log(this.state.num,'render');
return <div>我是一个 类组件 ClassCom
<br />
<p>数量变化:{this.state.num}</p>
<button onClick={this.clickHandler}>按钮</button>
</div>
}
}
export default ClassCom
法2:this.setState(()=>{return {}})
import React from 'react'
// ◆类组件
class ClassCom extends React.Component {
state={
num:10
}
// ◆ 点击事件函数
clickHandler=()=> {
// 法2:this.setState(()=>{return {}})
// 写成箭头函数的形式,参数 params 可以获取 state 中的数据变化
this.setState((params)=>{
console.log(params.num,'啦啦啦')
return {
num:this.state.num+10
}
})
}
render() {
console.log(this.state.num,'render');
return <div>我是一个 类组件 ClassCom
<br />
<p>数量变化:{this.state.num}</p>
<button onClick={this.clickHandler}>按钮</button>
</div>
}
}
export default ClassCom