npm i react react-dom
创建元素
// 名称,属性,之后子节点
const title = React.createElement('h1', null, 'hello react')
渲染
// 挂载元素,挂载位置
ReactDOM.render(title, document.getElementById('root'))
React脚手架
npx create-react-app my-app
npm start
直接使用声明式的HTML的标签
该语法为ECMA扩展语法,使用babel/preset-react编译后使用
驼峰命名
class -> classNamefor -> htmlFortabindex -> tabIndex无子节点标签可以 />结尾
推荐小括号包裹()
js嵌入js// 使用 {}
const name = 'dog';
const = (hello,{name})
{} 注意点
{} 中可以输入js表达式{} 中可以调用函数jsx自身也可以放入{}不能直接使用object,一般只出现在style中不能出现语句
条件渲染、列表渲染
使用map进行列表渲染时需要加上key,渲染谁,key就加谁身上(避免使用索引作为key)
jsx样式处理 行内:style= { { color:‘red’} }类名:className 附React完全使用js语言自身的能力来编写ui,而不是造轮子增强html功能
组件 组件创建 函数(无状态组件)约定
首字母大写返回值&&表示组件结构function Hello(){
return 第一个函数组件
}
ReactDOM.render( , document.getElementById('root'))
类(有状态组件)
约定
首字母大写继承React.Component必须有render()方法且返回值为组件结构 抽离组件 创建组件.jsimport React from 'react'
创建类export default ‘className’在使用的文件中import改组件
事件处理
on+event={事件处理程序}
function类型组件不需要this
state组件类型 | 名称 | 功能 |
---|---|---|
function | 无状态 | 只负责展示 |
class | 有状态 | 更新UI |
// 1
constructor(){
super()
this.state={
count:0
}
}
// 2
state={
count:0
}
修改state
不能直接修改
this.setState()
将事件处理抽离出render此时this为undefined
this应该指向组件实例
事件绑定this指向 箭头函数//函数要加()
Function.prototype.bind()
//在constructor内部将this绑定到方法上
this.myFunction = this.myFunction.bind(this);
class实例方法(推荐)
handleClick=()=>{
this.setState(
{count:this.state.count+1}
)
}
表单处理
受控组件
将表单元素的value交给state去控制
handleChange=(e)=>{
this.setState(
{txt:e.target.value}
)
}
//处理多表单
//为表单元素添加name属性,name的值与state绑定的value一样
handleChange=(e)=>{
const value = e.target.type === 'checkbox' ? e.target.checked : e.target.value;
const name = e.target.name
this.setState(
//属性名表达式??
{[name]:value}
)
}
非受控组件
React.createRef()方法创建ref对象
this.txtRef = React.createRef();
添加ref属性
ref获取文本框的值
getText =()=> this.txtRef.current.value
表单联系出错事项
凡是使用this.state的地方必须使用{}包裹凡是使用html标签的地方要使用()包裹渲染数据需要加key属性到要遍历的节点上直接调用function要加(),事件处理程序不需要添加state数组方法
[{新数据},...原数据]
组件通讯
props
props
接收传递给组件的数据可以传递任何类型的值,包括function和jsx只读class组件中,构造函数中拿props需要super(props)传递数据:组件标签添加属性
接收数据:
状态提升,将state给最近的父组件
在父组件提供共享数据在父组件提供 *** 作方法 Context跨组件传递数据
React.createContext();// ??
// 创建context得到两个组件
const { Provider, Consumer } = React.createContext()
在两个传值组件中使用
// 传递
我是1级
// 接收
{
data=>{data}
}
props.children
jsx,function,components都可以作为子节点
创建组件时,指定props的类型
package: prop-typesnpm i prop-types
import PropTypes from 'prop-types'
//注意大小写
ComponentName.propTypes={
color: PropTypes.array
}
props约束规则
类型elementisRequired特定结构对象:shape({})
props默认值
ComponentName.defaultProps={
pageSize: 10
}
组件生命周期
创建(挂载阶段)
Constructor()
this指向state初始化 render()
组件渲染render中不能调用setState componentDidMount()
DOM渲染后网络请求此时可以获取、 *** 作DOM
更新(更新阶段)
rener()
New propssetStateforceUpdate() componentDidUpdate(preProps)
DOM重新渲染后在if语句中调用setState
卸载(卸载阶段)
componentWillUnmount()
清理(定时器)
组件复用
render props
render模式
使用组件时,添加一个值为函数的prop,通过参数来获取state
state={
x:0,
y:0
}
render(){
return this.props.render(this.state)
}
componentDidMount(){
window.addEventListener('mousemove',this.handleMousePos)
}
handleMousePos=(e)=>{
this.setState({
x:e.clientX,
y:e.clientY
})
}
使用函数的返回值作为渲染的UI内容
root.render((
当前位置:{data.x}:{data.y}
)}/>)
children模式
Context的用法和children一致
1.
{mouse=>{return (当前位置:{mouse.x}:{mouse.y})}}
this.props.children(this.state)
添加render-props优化
校验
ComponentName.propTypes={
children:PropTypes.func.isRequired
}
组件卸载时事件绑定
componentWillUnmount(){
window.removeEventListener('mousemove')
}
HOC(高阶组件-函数)
//??
包装模式
import React from 'react'
function withMouse(WrappedComponent){
class MouseMove extends React.Component{
state={
x:0,
y:0
}
componentDidMount(){
window.addEventListener('mousemove',this.handleMouseMove)
}
handleMouseMove=(e)=>{
this.setState({
x:e.clientX,
y:e.clientY
})
}
componentWillUnmount(){
window.removeEventListener('mousemove')
}
render(){
return
}
}
return MouseMove
}
const Position = (props) =>(鼠标当前位置:{props.x}:{props.y}
)
const Don = withMouse(Position);
class MyCom extends React.Component{
render(){
return (
123456
)
}
}
export default MyCom
displayName
区分不同高阶组件名字
MouseMove.displayName = `WithMouse${getDisplayName(WrappedComponent)}`
function getDisplayName(componentName){
return componentName.displayName|| componentName.name || 'Component'
}
props丢失
return
附
子组件多次使用需要在外边包裹div
解构,将对象中的某些元素给暴露出来,直接使用获取0-2的随机数,Math.floor(Math.random()*3) 原理 setState 异步更新数据避免多次调用setState只触发一次render() 推荐语法// state为最新state
// props为最新props
// 回调会在DOM重新更新后触发
this.setState((state,props)=>{
return {
num:state.num +1
}
},()=>{})
JSX语法转化过程
JSX->preset-react->React.createElement()->React元素 Obj
组件更新机制setState
修改state更新UI只会更新当前组件以及子组件
组件性能优化 减轻state 之储存跟组件渲染有关的数据多个方法之间共享但和组件渲染无关的数据放入this中 避免不必要的重新渲染更新阶段
shouldComponentUpdate->render
//false为不渲染该组件
// nextProps 最新props this.props当前props
// nextState 最新状态 this.state当前状态
shouldComponentUpdate(nextProps,nextState){
return false
}
纯组件
React.PureComponent与React.Component类似,只是自动调用shouldComponentUpdate
分别比较前后两次的props和state来觉得是否需要重新渲染组件
通过shallow compare来进行判断
obj仅仅比较地址有没有变,因此不能直接copy该object
//创建新对象
const newObj = {...state.obj,number:2}
//数组
//不要使用push,unpush
//使用concat,slice
[...this.state.list,{newList}]
虚拟DOM和Diff算法
同组件相同,组件内不变的DOM是否需要更新
state(Model)->Virtual DOM->DOMsetState->new Virtual DOM->DOMdiff:compare Virtual(Virtual DOM,new Virtual DOM)render the changed part to the DOMrender之后
V-DOM -> JSX + State
性能,跨平台
yarn add react-router-dom
import { BrowserRouter as Router,Route,Link,Routes} from ‘react-router-dom’// 6版本以上
路由配置规则
页面去把
}>
// 以下
//不需要Routes
注意
包裹整个应用
BrowserRouter/HashRouter
HashRouter:使用URL的哈希实现
BrowserRouter(推荐):使用H5的history API实现
路由入口
页面去把
等同于
+ (location.pathname)
路由入口
path 路由规则component 指定的组件Route 指定渲染位置 执行过程 点击Link标签,修改浏览器地址栏中的URLReact监听地址栏URL变化React路由内部遍历所有的Route组件,使用路由规则(path)和pathname匹配匹配成功展示该组件 编程式导航JS代码实现页面跳转
// 跳转到指定路径
this.props.history.push('/path')
// 前进后退到第几个
this.props.history.go(n)
默认路由
path匹配
path:/
可以匹配所有路由path:/first
可以匹配 pathname/to:/first/
或/first/a
或/first/a/b/..
精确匹配
path和pathname完全匹配才可以
给Route加上exact属性
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)