什么是React?
React是一个专注于构建用户界面的JavaScript库,是目前主流的框架之一。中文文档:https://zh-hans.reactjs.org/
React有哪些特点?
声明式UI(JSX):声明式UI书写方式和普通HTML没有什么区别,避开了命令式的繁琐实现方式。
组件化开发:每一个组件可以通过划分成多个不同的模块进行开发,每一个模块就相当于一个组件。通过这种方式将一个页面分模块开发可以增强代码的可复用性和提高开发效率。
跨平台性:react可以开发多种不同的应用。比如:web应用、原生应用开发(react-native)、安卓和IOS应用,甚至可以开发VR应用。
React环境初始化
搭建一个react环境:
(1)确保已经安装node.js(注意版本问题)
(2)全局安装react脚手架:npm i -g create-react-app
(3)项目搭建:npx create-react-app 项目名称
npx:npx命令会临时安装creat-react-app包,然后初始化项目后自动删除,所以不用全局安装。
creat-react-app:固定命令,react脚手架名称。
项目目录:
node-modules:项目依赖文件
public:静态资源
src:项目目录下只保留App.js根组件文件、index.js将App组件插入到public中index.html根节点上、index.css全局样式文件。
JSX的基本概念及使用方法
JSX是JavaScript XML缩写,表示在JS中书写HTML结构。
优点:与HTML语法类似,学习成本低。利用JS本身的可编程能力创建HTML结构。
JSX:JS的语法扩展,浏览器不能直接识别,需要通过脚手架内置@babel/plugin-transform-react-jsx包,用来解析该语法。
JSX语法规则:(1)js表达式(2)三目运算符(3)函数
JSX列表渲染:采用{数组名.map(o=>{})}的方式循环遍历列表
JSX条件渲染:采用三元运算符和&&进行条件判断
JSX样式处理:分为style和className
style行内样式:
function App () {
return (
<div className="App">
<div style={{ color: 'red' }}>这是style行内样式</div>
</div>
)
}
style样式优化:
const style = {
color: 'blue'
}
function App () {
return (
<div className="App">
<div style={style}>这是style行内样式</div>
</div>
)
}
类名样式:
index.css中定义.title{color:blue;}
动态类名控制:App.js中
import './index.css'
const flag = true
function App () {
return (
<div className="App">
<div className={flag ? 'title' : ''}>这是style行内样式</div>
</div>
)
}
JSX注意事项:
JSX有且必须有一个根节点,如果没有可以使用幽灵节点<></>代替
所有标签必须闭合,成对闭合或者自闭和都可以。
JSX中语法更贴近于JS原生语法,属性名采用驼峰命名法,class=>className for=>htmlFor
JSX支持多行(换行),如果需要换行,需要使用()包裹,防止bug出现。
组件基础
组件的理解:我们在进行页面开发的时候,可以将每一个功能模块封装成一个组件,这个组件可以是兄弟关系也可以是嵌套关系。通过这种方式将一个页面抽离为一个组件树,组件开发模式有利于提高代码的可复用性以及开发效率。
React组件分为函数组件和类组件,函数组件:是通过JS普通函数或者ES6箭头函数return返回。类组件:通过继承React内部实例return
import React from "react"
// 函数组件和类组件的注册和事件绑定
// 函数组件的声明方式
const Hello = () => {
// 事件绑定
function getName () {
console.log('事件被触发了')
}
return <div onClick={getName} style={{ fontSize: '19px', color: 'red' }}>hello</div>
}
// 类组件的声明方式
class HelloComponent extends React.Component {
getName = () => {
console.log('this is HelloComponent 被触发了!')
}
render () {
return <div onClick={this.getName}>this is HelloComponent!</div>
}
}
function App () {
return (
<div className="App">
<Hello></Hello>
<HelloComponent></HelloComponent>
</div>
)
}
export default App
函数组件注意事项:
1、组件名称必须是首字母大写,react内部会通过这个来判断是组件还是html标签
2、组件函数必须有返回值,表示该组件得UI结构,如果不需要任何渲染,直接返回null
3、组件就像HTML标签一样可以被渲染到页面中,组件表示的是一段结构内容。
4、函数名称作为组件标签,可以成对也可以闭合。
类组件注意事项:
1、类名称必须以大写字母开头。
2、类组件是通过继承React.Component父类
3、类组件必须提供reader方法,且有返回值,表示该组件的UI结构。
函数组件的事件绑定:
1、绑定事件:on+事件名称 =>onClick、onMouseEnter、onFocus
import React from "react"
// 函数组件传递额外参数
// const Hello = () => {
// // 事件绑定
// function getName (msg) {
// console.log(msg)
// }
// return <div onClick={() => getName('这是组件函数传递额外参数')} style={{ fontSize: '19px', color: 'red' }}>hello</div>
// }
// 如果想要传递额外参数的同时还想传递事件对象
const Hello = () => {
// 事件绑定
function getName (e, msg) {
console.log(e, msg)
}
return <div onClick={(e) => getName(e, '这是组件函数传递额外参数')} style={{ fontSize: '19px', color: 'red' }}>hello</div>
}
// 类组件传递额外参数
// class HelloComponent extends React.Component {
// getName = (e) => {
// console.log('this is HelloComponent 被触发了!', e)
// }
// render () {
// return <div onClick={this.getName}>this is HelloComponent!</div>
// }
// }
// 类组件传递额外参数和事件对象方法
class HelloComponent extends React.Component {
getName = (e, msg) => {
console.log(e, msg)
}
render () {
return <div onClick={(e) => this.getName(e, '类组件被触发了')}>this is HelloComponent!</div>
}
}
function App () {
return (
<div className="App">
<Hello></Hello>
<HelloComponent></HelloComponent>
</div>
)
}
export default App
组件状态:为组件添加状态和修改状态的值
import React from 'react'
class HelloComponent extends React.Component {
// 状态修改
changeName = () => {
this.setState({
name: '你好,李毅'
})
}
// 状态定义
state = {
name: '这是初始状态'
}
render () {
return (
// 状态使用
<div>
这是类组件
<button onClick={this.changeName}>点击修改状态</button>
<div>{this.state.name}</div>
</div>
)
}
}
function App () {
return (
<div className="App">
<HelloComponent></HelloComponent>
</div>
)
}
export default App
案例Demo(点击+1):
import React from "react"
class ClickDemo extends React.Component {
state = {
count: 0
}
changeCount = () => {
this.setState({
count: this.state.count + 1
})
}
render () {
return (
<div>
<span>{this.state.count}</span>
<br />
<button onClick={this.changeCount}>+1</button>
</div>
)
}
}
function App () {
return (
<div className="App">
<ClickDemo></ClickDemo>
</div>
)
}
export default App
this指向问题:
import React from "react"
class Demo extends React.Component {
// 因为clickHeader函数this指向问题,需要改变当前This指向,通过bind方法强制装换
// 为什么使用bind而不使用apply和call()
// 因为调用apply和call方法会立即执行并返回执行结果,而bind()不会立即执行。
// 如果call和apply的第一个参数写的是null,那么this指向的是window对象
// call() 和bind()期望所有参数都单独传递,参数之间用逗号分隔,而 apply() 的参数都必须放在一个数组里面传进去。
// bind方法可以让对应的函数想什么时候调就什么时候调用,并且可以将参数在执行的时候添加。
constructor() {
super()
this.clickHeader = this.clickHeader.bind(this)
}
clickHeader () {
console.log(this)
// 如果没有改变this指向,默认为undefined
// 这时我们需要bind()强制改变this指向
}
render () {
return (
<div>
this指向问题
<button onClick={this.clickHeader}>click</button>
</div>
)
}
}
function App () {
return (
<div className="App">
<Demo></Demo>
</div>
)
}
export default App