一、react基本了解
1.组件定义
React 组件是一段可以使用标签进行扩展 的 JavaScript 函数。每个 React 组件都是一个 JavaScript 函数,它会返回一些标签,React 会将这些标签渲染到浏览器上。React 组件使用一种被称为 JSX 的语法扩展来描述这些标签。JSX 看起来和 HTML 很像,但它的语法更加严格并且可以动态展示信息。了解这些区别最好的方式就是将一些 HTML 标签转化为 JSX 标签。
-
函数组件
export default function Demo(){ return ( <div>hello,react</div> ) }
-
类组件
import React from 'react' export default class Demo extends React.Component{ render(){ return ( <div>hello,react</div> ) } }
使用html的cdn练习,后面使用脚手架
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>reactDemo</title>
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/babel-standalone/7.24.8/babel.js"></script>
</head>
<body>
<div id="test"></div>
<script type="text/babel">
class Demo extends React.Component{
render(){
return (
<div>hello,react</div>
)
}
}
// 2.渲染虚拟DOM到页面
ReactDOM.render(<Demo/>, document.getElementById('test'))
</script>
</body>
</html>
2.组件创建
-
组件命名规范(jsx规范)
-
组件必须以大写字母开头,而 HTML 标签则必须是小写字母。
-
虚拟DOM元素只能有一个根元素 比如
<div>...</div>
或使用空的<>...</>
包裹 -
虚拟DOM元素必须有结束标签
function MyDemo(){ return ( <div> 里面写html内容 </div> ) }
-
3.组件样式
-
使用class样式 使用className代替class名称
import React, { Component } from 'react' import './index.css' export default class extends Component { render() { return ( <div className='title'>hello react</div> ) } }
<!-- index.css --> .title{ width:300px; height:30px; background-color:'red' }
-
使用style样式
style={{}}
,第一个{}表示接受的是一个对象,第二个{}表示读取引入的变量内容
import React, { Component } from 'react' export default class extends Component { render() { return ( <div style={{width:'200px',height:'30px',backgroundColor:'red'}}>hello react</div> ) } }
4.数据渲染
-
变量渲染 通过
{}
引用变量或者函数return ( <h1> {user.name} </h1> );
-
条件渲染
import React, { Component } from 'react' export default class extends Component { isLogin=false render() { if(this.isLogin){ return ( <div>已经登录了</div> ) }else{ return ( <div>未登录,将返回登录页面</div> ) } } }
-
列表渲染 使用数组的map方法
- key 帮助 React 识别哪些元素改变了,比如被添加或删除。因此你应当给数组中的每一个元素赋予一个确定的标识。
- key必须唯一
import React, { Component } from 'react' export default class extends Component { fruitArr=['西瓜','苹果','草莓'] render() { return ( <ul> {this.fruitArr.map((n,index)=>{ return <li key={index}>{n}</li> })} </ul> ) } }
5.事件绑定
import React, { Component } from 'react'
export default class extends Component {
handleClick=(e)=>{
e.preventDefault(); //阻止事件默认效果
alert('hello,world')
}
render() {
return (
<div>
<button onClick={this.handleClick}>点我弹框</button>
</div>
)
}
}
6.数据存储
state 状态记录器
组件内部重要的属性,取值是一个对象,存储组件的信息,案例如下:
- state:组件内部的属性,用于记录组件状态,取值是一个object
- setState:用于修改state的值,页面才会对应变化
//当前天气默认炎热 点击改变按钮 变成凉爽
import React, { Component } from 'react'
export default class Weather extends Component {
//创建默认天气
state={isHot:true}
//改变天气
changeTq=()=>{
//只能通过setState来改变值,页面才会渲染变化的值
this.setState({isHot:false})
}
render() {
return (
<div>
<p>当前天气:{this.state.isHot?'炎热':'凉爽'}</p>
<button onClick={this.changeTq}>改变天气</button>
</div>
)
}
}
props 属性收集器
记录每个组件标签属性对象,通常用于父组件给子组件传递数据。如下:App给Student传递数据
import Student from "./components/Student";
function App() {
return (
<div>
<Student name="夫子" age="96"/>
</div>
);
}
export default App;
import React, { Component } from 'react'
export default class Student extends Component {
render() {
return (
<div>
<ul>
<li>姓名:{this.props.name}</li>
<li>年龄:{this.props.age}</li>
</ul>
</div>
)
}
}
对props
中的属性值进行类型限制和必要性限制:
安装prop-types
import PropTypes from 'prop-types';
使用PropTypes:
import React, { Component } from 'react'
import PropTypes from 'prop-types';
export default class Student extends Component {
static propTypes={
name:PropTypes.string.isRequired, //必须传入
age:PropTypes.string
}
render() {
return (
<div>
<ul>
<li>姓名:{this.props.name}</li>
<li>年龄:{this.props.age}</li>
</ul>
</div>
)
}
}
refs 身份定义器
组件通过refs值来定义自己,相当于原生documen.getElementByxxx
-
字符串定义
//定义 <input ref="myInput"></input> //使用 this.refs.myInput.value
-
回调函数定义
//定义 <input ref={c=>this.myInput=c}></input> //使用 this.myInput.value
-
createRef方法定义
//定义 myInput=React.createRef() <input ref={this.myInput}></input> //使用 this.myInput.current.value
案例:点击按钮,显示输入框内容
import React, { Component } from 'react'
export default class extends Component {
myInput=React.createRef()
render() {
return (
<div>
<input ref={this.myInput}></input>
<button onClick={()=>alert(this.myInput.current.value)}>点我弹框</button>
</div>
)
}
}
7.生命周期
7.1 旧版本生命周期
- 初始化阶段
- constructor
- componentWillMount (将废弃)
- componentDidMount 比较常用: 一般在这个钩子中做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息
- 更新阶段
- shouldComponentUpdate 组件是否应该被更新(默认返回
true
) - componentWillUpdate (将废弃)
- render
- componentDidUpdate
- shouldComponentUpdate 组件是否应该被更新(默认返回
- 卸载阶段
- componentWillUnmount 关闭定时器
class LifeDemo extends React.Componet(){
//构造器 默认实例后就执行 【出生】
constructor(){
}
//组件将要挂载前执行
componentWillMount(){
}
//组件完成挂载执行(只执行一次)
componentDidMount(){
}
//每次组件内容变了则会执行 1+n次
render(){
}
//通常是父组件给子组件传递属性值,引发此函数顺序一系列执行
//第一次传递的无效,后面的有效
componentWillReceiveProps(){
}
//组件是否更新 默认为返回true 【组件的更新阀门(state状态变了,则执行)】
// 如果写了,则必须返回true ,如果返回false,则state变了不会引入组件内容变化
shouldComponentUpdate(){
return true;
}
//组件将要更新前执行 forceUPdate也能导致此函数顺序一系列执行
componentWillUpdate(){
}
//组件完成更新后执行
componentDidUpdate(){
}
//组件将要销毁执行 【死亡】
componentWillUnmount(){
}
}
- 更新说明:
7.2 新版本生命周期
- 初始化
- constructor
- getDerivedStateFromProps
- render :初始渲染dom数据
- componentDidMount :组件挂载dom执行一次 通常开启监听、发生请求
- 更新阶段 由组件this.setState或者组件重新render出发
- getSnapshotBeforeUpdate
- render
- componentDidUpdate
- 卸载阶段
- componentWillUnmount
- componentWillUnmount
class Life extends React.Component(){
// 此方法适用于罕见的用例,即 state 的值在任何时候都取决于 props。
//从Props获取一个派生的state 返回的值会更改已有的state
static getDerivedStateFromProps(props,state){
return props
}
render(){}
compoentDidMount(){}
// 组件能在发生更改之前从 DOM 中捕获一些信息(例如,滚动位置)。此生命周期方法的任何返回值将作为参数传递给 componentDidUpdate()。
getSnapshotBeforeUPdate(preProps,preState){
return snapshotValue
}
componentDidUpdate(preProps,preState,snapshotValue){
}
}
getSnapshotBeforeUPdate
的使用案例:
每次添加新闻,保持滑动的那条新闻不随滚动条移动。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>reactDemo</title>
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/babel-standalone/7.24.8/babel.js"></script>
<style>
.list{
width: 200px;
height: 150px;
background-color: aqua;
overflow:auto;
}
.news{
height: 30px;
}
</style>
</head>
<body>
<div id="test"></div>
<script type="text/babel">
class MyLife extends React.Component{
//初始化数据
state={newArr:[]}
componentDidMount(){
console.log('dfdfd');
this.timer=setInterval(()=>{
let {newArr}=this.state
//每次创建一条新闻
let news="新闻"+(newArr.length+1)
this.setState({newArr:[news,...newArr]})
},1000)
}
stop=()=>{
console.log("停了吗");
clearInterval(this.timer)
}
getSnapshotBeforeUpdate(){
console.log("getSnapshotBeforeUpdate....");
return this.dd.scrollHeight
}
render(){
return (
<>
<div className="list" ref={c=>this.dd=c}>
{
this.state.newArr.map((n,index)=>{
return <div key={index} className="news">{n}</div>
})
}
</div>
<button onClick={this.stop}>stop</button>
</>
);
}
componentDidUpdate(preProps,preState,height){
console.log("componentDidUpdate...");
console.log(this.dd,height);
this.dd.scrollTop+=this.dd.scrollHeight-height
}
}
// 2.渲染虚拟DOM到页面
ReactDOM.render(<MyLife/>, document.getElementById('test'))
</script>
</body>
</html>
8.快速demo(脚手架)
-
模块化,组件化:react+webpack+eslint+es6
-
快速构建一个简单的react项目
npx create-react-app react_demo
-
启动react项目
cd react_demo npm start Starting the development server...
9. 快速创建Hello组件
创建Hello组件
使用Hello组件
10 样式模块化
创建Welcome组件,设置class,但是Welcome组件没有css文件
import { render } from '@testing-library/react'
import react,{Component} from 'react'
export default class WelCome extends Component{
render(){
return (
<div className='title'>hello welcome</div>
)
}
}
Hello组件的内容
import { render } from '@testing-library/react'
import react,{Component} from 'react'
//【引入目录下的css样式】
import './index.css'
export default class Hello extends Component{
render(){
return (
<div className='title'>hello react</div>
)
}
}
App引入Welcome组件,这个时候Welcome被渲染的时候使用了Hello组件下的样式了。
import logo from './logo.svg';
//直接引入
import Hello from './components/Hello'
import Welcome from './components/Welcome'
function App() {
return (
<div>
<Hello/>
<Welcome/>
</div>
);
}
export default App;
效果:
解决办法:
- 将
xxx.css
------>xxx.module.css
- 通过
import xxx from './xxx.module.css'
className={xxx.title}
<!--正常引入的css -->
.title{
width: 300px;
height: 30px;
color: rgb(78, 78, 53);
background-color: rgb(157, 110, 49);
border: 2px solid #ccc;
}
<!-- 样式模块化后的css-->
.Hello_title__OTB7- {
width: 300px;
height: 30px;
color: rgb(78, 78, 53);
background-color: rgb(157, 110, 49);
border: 2px solid #ccc;
}
11.插件安装
通过命令快速生成组件模式,如class模式组件,function模式组件
// 输入【rcc】(react class create)
import React, { Component } from 'react'
export default class index extends Component {
render() {
return (
<div>index</div>
)
}
}
// 输入【rfc】(react function create)
import React from 'react'
export default function index() {
return (
<div>index</div>
)
}