jsx基本使用
- 变量,表达式
在render函数里使用 {this.state.xxx}表达式获取变量 - class style
style写法是
<p style={{fontSize:'18px',}}></p>
//如果要插入一段原生html,可以使用
const ralHtml = `<span>asdasdasd</span>`
<p dangerslySetInnerHTML={ralHtml }></p>
- 子元素和组件
- 条件判断
1.if else
2.三元表达式
3.逻辑运算符&& || - 渲染列表
1.map
2.key
2.事件
1.bind this
性能优化小知识点,可以在constructor里面修改函数this的指向
constructor(props) {
super(props)
this.getFirstRequest = this.getFirstRequest.bind(this)
}
或者使用静态方法(箭头函数,this指向当前实例)
getFirstRequest=()=>{
this.setstate({count:1})
}
//调用使用
{this.getFirstRequest}
2.关于event参数
3.传递自定义参数
3.react事件和dom事件
react中的event是syntheticEvent(合成事件),模拟出来DOM事件所有能力
event.nativeEvent是原生事件对象
所有的事件,都被挂载到doucument上(react16),
react17开始事件绑定到root上
和dom事件不一样和vue事件也不一样
//传递参数
clickHandle(id,title,event){
//最后追加一个参数,即可接收event
}
4.react表单知识点串讲
1.受控组件
render(){
return <div>
<p>{this.state.name}</p>
<input value={this.state.name} onchange=(this.changeValue)/>
</div>
}
//textArea 这些的值,要用vue,而不是
<textArea>{this.state.value}</textArea>
5.react父子组件通讯
1.props传递数据
2.props传递函数
3.props类型检查
状态提升,意思是把数据放在在高一层的组件,高层组件来做数据跟改和数据分发,子组件只用来渲染
6.setState为何使用不可变值
- setState
1.不可变值
不要直接操作不可变值,要用this.setState()
不能对this.state.arr直接使用push pop splice等,这样违反不可变值
不仅数组,object也是一样,最好的做法就是生成一份副本,再对副本做修改,然后使用this.setState()进行设置
在生命周期shouldComponentUpdate会有影响
//不要这样使用
this.setState({list:this.state.list.splice(0,3)})
2.可能是异步更新
this.setState({
count:this.state.count+1
},()=>{
//这里获取的是改变的最新的值
console.log(this.state.count)
})
//这里是之前未改变的值
console.log(this.state.count)
setState直接使用是异步的,在setTimeout和自定义dom事件中使用是同步的
3.可能会被合并
传入对象,会被合并,执行结果只一次 +1,类似于(Object.assgin)
this.setState({
count:this.state.count+1
})
this.setState({
count:this.state.count+1
})
this.setState({
count:this.state.count+1
})
//相当于只执行了一次
this.setState({
count:0+1
})
传入函数,不会被合并,执行结果+3
this,.setState((prevState,props)=>{
return{
count:prevState.count+1
}
})
this,.setState((prevState,props)=>{
return{
count:prevState.count+1
}
})
this,.setState((prevState,props)=>{
return{
count:prevState.count+1
}
})
//结果会是3,6,9依次往上叠加,
7.组件生命周期
8.react函数组件和class组件的区别
1.纯函数,输入props,输入jsx
2.没有实例,没有生命周期,没有state
3.不能扩展其他方法
9.非受控组件
1.ref
2.defaultValue defaultChecked
3手动操作DOM元素
- 非受控组件
必须手动操作DOM元素,setState实现不了
文件上传<input type=file>
某些富文本编辑器,需要传入DOM元素
10.portals
组件默认会按照既定层次嵌套渲染
如何让组件渲染到父组件以外
- 使用场景
overflow:hidden(父级设置了BFC)
父组件z-index值太小
fixed需要放在body第一层级
render(){
//正常使用
return <div class="modal">
{this.props.children}
</div>
}
//使用Portals渲染到body上
return ReactDom.createPortal(
<div class="modal">
{this.props.children}
</div>,document.body //后面这个document.body值的意思是渲染到body里面
)
11.react Context
主要用于设置公共信息(语言,主题)
//创建Context默认值
const ThemeContext = React.createContext('light')
//在最外层的父组件 渲染时用<ThemeContext.Provider value={this.state.theme}>包裹
render(){
return
<ThemeContext.Provider value={this.state.theme}>
//里面是一些子组件
<ThemedBUtton />
<ThemeContext.Provider>
}
//子组件获取context值(class组件)
class ThemedBUtton extends React.Component{
render(){
const theme = this.context//react会往上找最近的provider
return <div>
<p>{theme} </p>
</div>
}
}
themedButton.contextType = ThemeContext //指定conterxtType
//也可以写成
static contextType = themeContext
//函数组件获取
function theLinkl(props){
return <ThemeContext.Consumer>
{value => <p>link's theme is {value}</p>}
</ThemeContext.Consumer>
}
12.异步组件
import()
react.lazy
react.suspense
//异步加载当前组件
从三台ContextDemo= React.lazy(()=>import('./ContextDemo'))
class App extends React.Component{
constructor(props){
super(props)
}
render(){
return <div>
<React.Suspense fallBack={<div>Loading...</div}
<ContextDemo/>
</React.Suspense>
</div>
}
}
13.性能优化
- shouldComponentUpdate(简称SCU),必须配合不可变值使用
scu基本用法
shouldComponentUpdate(nextProps,nextState){
if(nextState.count !== this.state.count){
return true //刻意渲染
}
return false
}
- PureComponent(纯组件)和React.memo
纯组件其实也是scu中进行了浅比较,只比对了第一层是否一样
函数组件中的pureComponent memo
-不可变值immutable.js
1.彻底拥抱不可变值
2.基于共享数据(不是深拷贝),速度好
3.有一定的学习成本和迁移成本,按需使用
14.react高阶组件
- HOC
//高阶组件不是一种功能,而是一种模式
const HOCFactory = (COmponent)=>{
class HOC extends React.Component{
//在此定义多个组件的公共逻辑
render(){
return <Component {...this.props} />//返回拼装结果
}
}
return HOC
}
const EnhancedComponent1 = HOCFactory(WrappedComponent1)
const EnhancedComponent2 = HOCFactory(WrappedComponent2)
- HOC vs Render Props
1.HOC:模式简单,但会增加组件层级
2.render props:代码简洁,学习成本较高
3.按需使用
在react中实现公共逻辑的抽离,使用HOC或者render props
15.Redux使用
1.和vuex作用相同,但比Vuex学习成本高
2.不可变值,纯函数
3.面试常考
基本概念
1.store state
2.action
3.reducer单向数据流
dispatch(action)
reducer -> newState(不可变值)
subscribe 触发通知react-redux
Provider
connect
mapStateToProps mapDispatchToProps
在需要使用的index.js文件里面引入Provider
import {Privder} from 'react-redux'
import todoApp from './reducers'
import App from './component/App'
let store = createStore(todoApp)
export store = function(){
return <Provider store={store}>
<App />
</Provider>
}
//需要消费store的子组件里面需要调用一下connect方法
AddTodo = connect()(AddTodo)
export default AddTodo
//调用connect()后dispatch已经被注入到该组件中
//dispatch一个action到 effects =>reducer(不可变值)=>返回新的值=>store修改=>触发订阅跟新数据=>页面刷新
- 异步action
首先在创建store的时候要引入
import {createStore,applyMiddleWare} from 'redux'
import thunk from 'redux-thunk'
import rootReducer from './reducers/index'
const store = createStrore(rootReducer,applyMiddleWare(thunk ))
//在使用action 的地方 以前是返回一个对象,现在返回一个函数
- 中间件
中间件原理,大致就是把当前的dispatch做了下改造,先把当前的disptch用一个 let next = dispatch
console.log(1)
next()
console.log(2)
16.react-router路由模式
1.hash模式(默认)
2.h5history模式
3.后者需要后端支持,因此无特殊需求选择前者
import{hashRouter as Router,Switch,Route} from 'react-router-dom'
//BromserRouter as Router
function RouterComponent(){
return(
<router>
<Switch>
<route path="*">
//这里面包裹组件
</route>
</Switch>
</router>
)
}
jsx本质
通过createelement函数 第一个参数是tag,第二个参数是属性也就是一个对象,没有的话传入null,第三个参数可以是数组,数组里面继续是createelement函数对应的子元素,依次。也可以打散挨个传入。最终返回一个vnode 在通过patch渲染