1.简介
- 声明式
- 组件化(基于组件)
- 学习一次,随处使用
2.安装配置
1、安装React
安装命令 npm i react react-dom
- react 包是核心,提供创建元素、组件等功能
- react-dom 包提供DOM相关功能等
2、安装脚手架
npm i create-react-app -g // 全局安装
3、初始化项目
create-react-app 项目名
4、启动项目
npm start
5、其他方式
2.JSX
1.jsx简介
JSX 是 JavaScript 的简写,表示在JavaScript 代码中 写 XML(HTML)格式的代码。
优势: 声明式语法更加直观,与HTML结构相同,降低了学习成本,提升了开发效率
let h1 = <h1 id='title' className='box' >hello,React</h1>
/* jsx语法,h1是react元素 */
ReactDOM.render(h1,document.getElementById('root'))
2.jsx插值语法
import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
// import App from './App'
// jsx语法,h1是react元素
// let h1 = <h1 id='title' className='box' >hello,React</h1>
// ReactDOM.render(h1,document.getElementById('root'))
// JSX⭐⭐ 语法:
// 单表签必须闭合;布尔值不渲染; {}单括号
// 标签属性有所变化
// 1. class改成className
// 2. 多个单词组成的属性,需要变成小驼峰
let num = 50
let state = false
let message = 'Start'
let pic = 'https://img0.baidu.com/it/u=3927459320,2138990686&fm=26&fmt=auto'
let person = {
name: 'zs',
age: 50
}
let arr = ['zs', 'li']
let arr2 = [<li key="1">你好</li>, <li key="2">我好</li>]
let htmlStr = '<div>我是一个文字的内容</div><b>我是文章的段落</b>'
let tpl = (
<div>
<h1 id={'data' + num}>{message}</h1>
<img src={pic} alt='' className='pic' />
<h1>{state}</h1>
{/* 不能直接渲染对象 */}
<h2>{JSON.stringify(person)}</h2>
{/* 数组 */}
<div>{arr}</div>
<div>{arr2}</div>
{/* html字符串;插值语法+对象 */}
<div dangerouslySetInnerHTML={{ __html: htmlStr }}></div>
</div>
)
ReactDOM.render(tpl, document.getElementById('root'))
3.样式操作
import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
// 样式操作:
// 1. 操作class
// 2. 操作style
let sty = { backgroundColor: 'red', color: '#fff' }
let tpl = (
<div>
<h1 className={200 > 2 ? 'success' : 'fail'}>hello!react</h1>
<h1 style={sty}>hello!react</h1>
</div>
)
ReactDOM.render(tpl, document.getElementById('root'))
4.条件渲染(三元表达式)
// 导入react
// 导入react-dom
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css'
// 条件渲染
let tpl = (<div>
{
20 > 10 ?
<ul>
<li>111</li>
<li>111</li>
<li>111</li>
<li>111</li>
</ul>
:
<p>
<span>暂无数据</span>
<img src="" alt="" />
</p>
}
</div>)
ReactDOM.render(tpl, document.getElementById('root'))
5.列表渲染
// 导入react
// 导入react-dom
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css'
// 列表渲染
let arr = ['铁娃', '二狗子', '翠花']
// 直接渲染数组的话,会把数组每个元素取出直接拿去渲染!
let arr2 = [<li key="1">铁娃</li>, <li key="2">二狗子</li>, <li key="3">翠花</li>]
// 处理arr变成像arr2一样
let arr3 = arr.map((item, index) => {
return <li key={index}>{item}</li>
})
let tpl = (<div>
{/* 1 */}
{arr}
<hr />
{/* 2 */}
<ol>
{arr2}
</ol>
{/* 3 */}
<ul>
{arr3}
</ul>
<hr />
{/* 最终写法 */}
<ul>
{arr.map((item, index) => (<li key={index}>{item}</li>))}
</ul>
</div>)
ReactDOM.render(tpl, document.getElementById('root'))
3.组件
1.函数式组件
快捷键 rfc
import React from 'react';
// 函数式组件
let Item = () => {
return (
<div className="item">
<div className="title">测试</div>
<div className="content">内容</div>
</div>
)
}
export default Item
2.类组件
快捷键 rcc
import React, { Component } from 'react';
/*
class 组件名 extends Component/React.Component {
render(){
return jsx片段
}
}
*/
class Box extends Component {
render () {
return (
<div className="box">
我是Box组件
</div>
);
}
}
export default Box;
3.补充
// 函数式组件没有状态,没有生命周期,必须依赖Hook钩子才可以获取到状态以及生命周期钩子
// 类组件有状态,有生命周期!
// 组件名首字母必须大写
4.事件绑定
1.函数式组件事件绑定
// 函数式组件
import React from 'react';
function click (str) {
console.log('aa' + str);
}
const App = () => {
return (
<div>
{/*事件函数是click, 不可以写()*/}
<button onClick={click}>触发事件</button>
{/* 事件函数是箭头函数 */}
<button onClick={() => click('点击了')}>触发事件,并且传参</button>
</div>
);
}
export default App;
2.类组件事件绑定
import React, { Component } from 'react'
class App extends Component {
fn (event) {
console.log(111)
console.log(this) //undefined
console.log(event);
}
constructor() {
super()
this.fn3 = this.fn3.bind(this)
}
fn3 (event) {
console.log(333)
console.log(this)
console.log(event);
}
fn4 (event) {
console.log(444)
console.log(this)
console.log(event);
}
fn5 = (event) => {
console.log(555)
console.log(this)
console.log(event);
}
render () {
return (
<div>
{/* ⭐⭐缺点:没有this指向,且不能传参 */}
<button onClick={this.fn}>事件绑定1</button>
{/* ⭐以下均是解决this指向丢失问题 */}
{/* 最常用⭐⭐⭐每一次模板更新都重新绑定 */}
<button onClick={this.fn.bind(this)}>事件绑定2</button>
{/* 只绑定一次 ,性能更优*/}
{/* <button onClick={this.fn3}>事件绑定3</button> */}
{/* 最常用⭐⭐⭐箭头函数可以留住this指向 */}
<button onClick={(event) => this.fn4(event)}>事件绑定4</button>
{/* <button onClick={this.fn5}>事件绑定5</button> */}
</div>
)
}
}
export default App
// 类组件传值
import React, { Component } from 'react'
class App extends Component {
fn (num, event) {
console.log(num);
console.log(event);
console.log(this) //undefined
}
fn4 (num, event) {
console.log(num);
console.log(event);
console.log(this)
}
render () {
return (
<div>
<button onClick={this.fn.bind(this, 60)}>事件绑定2</button>
<button onClick={(event) => this.fn4(60, event)}>事件绑定4</button>
</div>
)
}
}
export default App
5.组件状态(state和setState)
函数组件叫无状态组件,类组件叫做有状态组件
负责展示 负责更新ui
import React, { Component } from 'react'
class App extends Component {
constructor() {
super()
// 类似于vue中的data
this.state = {
num: 10,
age: 20,
}
}
changeNum = () => {
//⭐ 修改state必须使用setState,setState会调用render方法更新视图
// this.setState(修改对象,回调函数)
// this.setState(函数,回调函数),修改的值依赖之前的值
// ⭐⭐this.setState是异步的
this.setState({
num: this.state.num + 1,
})
console.log(this.state.num)
}
changeAge = () => {
this.setState((state, props) => ({
age: state.age + 1,
}), () => {
console.log(this.state.age)//⭐⭐获取到的还是新值
})
console.log(this.state.age) //⭐⭐获取到的还是老值
}
render () {
return (
<div>
<button onClick={this.changeNum}>{this.state.num}</button>
<button onClick={this.changeAge}>年龄加一</button>
</div>
)
}
}
export default App
6.表单处理
import React, { Component, Fragment } from 'react';
// 表单分为俩类
// 受控组件 :能改
// input有事件绑定
// 非受控组件:只读
<input type="text" readOnly />
class App extends Component {
state = {
formData: {
username: '123',
sex: '1',
hobby: ['lq', 'zq'],
hometown: 'hz',
notes: '451485'
}
}
// 综合修改数据的方法
changeInputValue (event, key) {
// 获取新值
let newVal = event.target.value
console.log(event.target.value);
// 键名
console.log(key);
// ⭐⭐⭐es6箭头函数语法,以及解构的不可重复性
this.setState(state => ({
formData: {
...state.formData,
[key]: newVal
}
}))
}
// 修改复选框方法
changeCheckboxValue (event, key) {
let newVal = event.target.value
console.log(event.target.value);
// ⭐findIndex只能传入函数
let idx = this.state.formData[key].findIndex(item => item === newVal)
if (idx === -1) {
this.state.formData[key].push(newVal)
} else {
this.state.formData[key].splice(idx, 1)
}
// ⭐更新视图
this.setState({})
}
render () {
let { username, sex, hobby, hometown, notes } = this.state.formData
return (
<>
<p>姓名:<input onChange={(event) => this.changeInputValue(event, 'username')} typsexe="text" value={username} /> </p>
<p>性别:
<label htmlFor=""><input onChange={(event) => this.changeInputValue(event, 'sex')} type="radio" checked={sex === '1'} value='1' />男</label>
<label htmlFor=""><input onChange={(event) => this.changeInputValue(event, 'sex')} type="radio" checked={sex === '0'} value='0' />女</label></p>
<p>爱好
<label htmlFor=""><input type="checkbox" onChange={(event) => this.changeCheckboxValue(event, 'hobby')} checked={hobby.includes('lq')} value='lq' />篮球</label>
<label htmlFor=""><input type="checkbox" onChange={(event) => this.changeCheckboxValue(event, 'hobby')} checked={hobby.includes('zq')} value='zq' />足球</label>
<label htmlFor=""><input type="checkbox" onChange={(event) => this.changeCheckboxValue(event, 'hobby')} checked={hobby.includes('qq')} value='qq' />铅球</label>
</p>
<p>家乡:
<select value={hometown} onChange={(event) => this.changeInputValue(event, 'hometown')}>
<option value="">请选择</option>
<option value="hf">合肥</option>
<option value="nj">南京</option>
<option value="hz">杭州</option>
</select>
</p>
<p>
<textarea onChange={(event) => this.changeInputValue(event, 'notes')} value={notes} name="" id="" cols="30" rows="10"></textarea>
</p>
</>
);
}
}
export default App;
7.ref
import React, { Component } from 'react';
import Text from './text';
class App extends Component {
constructor() {
super()
//创建ref引用
this.fileRef = React.createRef()
this.textRef = React.createRef()
}
showFile = () => {
// ⭐获取dom节点
console.log(this.fileRef.current);
}
changeNum = () => {
this.textRef.current.setState({
num: 50
})
}
render () {
return (
<div>
<Text ref={this.textRef} />
<input ref={this.fileRef} type="file" />
<hr />
<button onClick={this.showFile}>获取文件信息</button>
<button onClick={this.changeNum}>修改text中的num</button>
</div>
);
}
}
export default App;
8.子父组件通信
1.父===> 子
2.子===> 父
3.context跨组件传递数据(provider/consumer)
9.props校验
4.路由
1.安装配置
react的路由核心思想 一切皆为组件!
this指向app实例对象
安装: npm install react-router-dom
2.图片引入方式
3.路由实现
往下||||
1.声明式导航
往下|||||
2.编程式导航
history.goback()
3.权限路由(路由拦截)
5.调用请求
6.生命周期
componentDidMount:生命周期:挂载完成之后
//组件将要被卸载 componentWillUnmount
// 组件是否应该更新!一定要返回布尔值,true表示组件要更新,false不会让组件更新 shouldComponentUpdate(newProps,newState){ return newProps.newMusic.length ? true :false } // 组件更新之后 componentDidUpdate
7.页面传值
this.props.match.params
8.redux
三大原则
-
单一数据源
-
state是只读
-
使用纯函数进行修改
- 一个函数的返回结果只依赖于它的参数,并且在执行过程里面没有副作用,我们就把这个函数叫做纯函数。
1.store.dispatch 触发action执行reducer函数
2.store.getState() 获取state数据
3.store.subscribe() 监听数据的变化
9.react-redux
10.hooks 钩子函数
\