1.可以用&&运算符。前面为true才能运行后面的 {true && <div>嘿嘿</div> }
2.再就是用三元表达式
3.复杂的逻辑的话收敛为一个函数,通过专门的函数来写分支逻辑
样式的话是引入。通过import './asstent.index.css'
动态控制类名 className = { active ? 'active' : ''}
必须有一个根结点,可以通过幽灵节点<></>代替
组件的开发
阻止默认行为e.preventDefault()
onClick((e)=>{ handle(e,'msg') })
<input ref = { msgRef }/>
Const msgRef = createRef()
mgsRef.current
组件通讯
1.父传子props,函数组件通过props接受,只能读取不能修改(和vue一样vue3是通过v-model,vue2是通过sync修饰符) 可以传递函数,也可以执行,可以传递html标签和组件都是可以的jsx,想传递什么传递什么
const Info = (props)=>{ }
解构:const Info = ({msg,fn,...args})=>{ },剩余参数
props的校验,通过yarn add prop-types
import PropTypes from 'prop-types'
Info.propTypes = { //定义规则
list: PropTypes.arry
}
2.子给父:子组件调用父组件传递过来的函数
fn(msgInfo)给父组件传递msgInfo,父组件接受就可以了。就能访问到了
3.Context祖先给后代传值
import React,{ createContext,useState } from 'react'
const Context = createContext()
<Context.Provider value={count}>祖先组件
</Context.Provider>
后代组件
import React,{ createContext,useState } from 'react'
const Context = createContext()
const count = useContext(Context)
4.PubSubJs库发布订阅
特殊的children属性,跟插槽差不多,只要写在内部children属性
<List>
{msg}
<div></div>
</List>
Const List = ({children})=>{}
生命周期
constructr render componentDidMount。 挂在时
render componentDidupdate 更新时
componentDidUnmount 卸载时
新版生命周期函数和旧版的差别:新版即将废弃老的3个钩子(componentWillMount、componentWillReceiveProps、componentWillUpdate),新增了2个钩子(getDerivedStateFromProps、getSnapshotBeforeUpdate)
Hooks,函数组件更强大,更灵活的钩子
1.useState const [ info,setInfo ] = useState({})
useState返回值时数组(解构),赋值顺序不可以调换,不能直接修改原值,是生成一个新值
组件的更新,调用useState会更新dom
参数可以定义成一个函数userState(()=>{ return props.count })
2.useEffect()生命周期:是在dom渲染之后执行
1.组件初始化的时候执行一次,每次数据更新的时候执行
重点 2.加一个空数组,只有初始化执行一次
useEffect(()=>{
return ()=>{卸载的时候调用}
},[])
3.添加特定的依赖项,首次渲染的时候执行,依赖想发生变化时重新执行
4.只要在useEffect回调函数中用到的数据状态就应该出现在依赖项数组中声明 否则可能会有bug
理解函数副作用:
1.数据请求ajax发送
2.手动修改dom
3.localstorage操作
4. 用userEffect发送请求
useEffect(()=>{
async function info(){
const res = await fetch('')
}
},[])
5.userRef()。 获取组件实例或者是dom对象
Const refInfo = userRef(null)
内部有一个current属性
refInfo.current
用于组件用ref,父组件可以访问子组件的值
forwardRef(props, ref){
useImperativeHandle(ref, () => ({
play: play,
pause: pause,
currentTime: currentTime,
playbackRate: playbackRate,
volume: volume,
setBrightness: setBrightness
}))
}
6.useMemo,跟计算属性很相似,有缓存
Const [fnum.setFnum] = useState(10)
Const [snum,setSnum] = useState(20)
const sum = useMeou(()=>{
return fnum + snum
},fnum,snum)
重点:路由
1.非hash模式的路由 <BrowserRouter></BrowserRouter>
2.hash路由<HashRouter></HashRouter>
BrowserRouter和HashRouter区别,一个是hash模式,一个是history模式
useRoutes(路由)站位
(BrowserRouter会真正的发请求要页面。后端没有对应的路径处理路径,就会404,解决,一旦接受不合法路径或没有路径,
让后端从新渲染让事我给你提供的index页面就可以了)
编程式导航
import { useNavigate } from "react-router-dom";
Const navigate = useNavigate()
navigate('./about',{replace:true}),替换的形式去跳转而不是叠加有历史记录
跳转传递参数:
1.params传递参数, 但是需要占位。 /about:id
navigate('./about/001',{replace:true})
接收参数: let params = useParams()
let id = params.id
2.searchParams传参。 navigate('./about?id=001',{replace:true})
接收参数:let [params] = useSearchParams()
let id = params.get('id')
<Outlet />是二级路由的占位,二级路由的出口
样式的全局引入
import './comp1.scss' 这个是全局的引入
样式的模块化引入,重点重点重点
import styles from './comp1.module.scss'
<div className = { style.box }>
</div>
//获取当前的路径
import { useLocation } from 'react-route-dom'
Const location = useLocation()
受控组件是 React 控制中的组件,并且是表单数据真实的唯一来源。
非受控组件是由 DOM 处理表单数据的地方,而不是在 React 组件中
useCallback来缓存组件
useCallback:当父组件向子组件传递函数的时候,父组件的改变会导致函数的重新调用产生新的作用域,所以还是会导致子组件的更新渲染,这个时候我们可以使用
useMemo:用来计算数据,返回一个结果,监听数据的变化,第二个参数就是监听的数据,具有缓存性
如果更新数据的话,函数组件会从函数头开始执行
Hooks函数就是把东西提出来。然后返回回去,就是自定义hooks
路由守卫
const getHtag = (type) => {
if(type == 1){
return <div>显示这个1</div>
}
if(type == 2){
return <div>显示这个2</div>
}
}
export default function App (){
return (
<>
{getHtag(1)}
</>
)
}
受控组件:input框自己的状态被React组件状态控制,就是双向数据绑定
非受控组件:通过手动操作dom的方式获取文本框的值