目录
- 一.React
- 1. React 的主要特性是什么
- 2.React 的核心思想是
- 3. 什么是jsx
- 4. render()函数
- 5. 函数组件和类组件的区别
- 6. HTML和React中事件处理的区别
- 7. React 中的合成事件
- 8. 虚拟Dom?为什么使用?如何实现?
- 9. 在 constructor 中给 super 函数传递 props 的目的是什么?
- 10.state和props之间的区别
- 11. 什么是React生命周期
- 12. React中如何使用Hooks
- 13. React的单向数据绑定
- 14.什么是flux
- 15.React中如何控制组件的样式
- 16.React中如何进行服务器渲染
- 17.如何进行React性能优化
- 18.React解决了什么问题
- 19.React的协议
- 20.shouldComponentUpdate生命周期
- 22.怎么阻止组件的渲染
- 二、react-router相关
- 1.路由跳转
- 2.路由模式
- 3. Link、NavLink和Navigate
- 4.router中的路由钩子函数
- 5.路由懒加载
- 三.Redux相关
- 1.使用
- 2.state管理
- 3.单向数据流
一.React
1. React 的主要特性是什么
- 虚拟 DOM(VirtualDOM) 替代了真实 DOM(RealDOM)
- 支持服务端渲染
- 遵循单向数据流或数据绑定
- 使用可复用 / 可组合的 UI 组件来进行视图开发
2.React 的核心思想是
封装组件,各个组件维护自己的状态和UI,当状态变更,自动重新渲染整个组件
3. 什么是jsx
(JavaScript XML)实际上,它只是为 React.createElement() 函数提供语法糖,为我们提供了在 JavaScript 中使用类 HTML 模板语法的能力。
原理:jsx语法最终会被babel
编译成为React.createElement()
方法,createElement方法会生成虚拟的DOM节点对象,再由ReactDOM.render()
函数生成真实DOM,插入到对应节点中去
//jsx
<div className="wang.haoyu">hello</div>
经过bale
编译之后的:
React.createElement("div", {
className:'wang.haoyu'
}, "hello");
render()
生成真实Dom
ReactDOM.render(<App />, document.getElementById('root'));
4. render()函数
- 一个虚拟节点就是一个对象:
下面输出的对象就是createElement()方法的返回值
- 转化为真实Dom:
// 真正渲染方法 function render(vDom, el) { const newDom = createDom(vDom); el.appendChild(newDom); } // 先不考虑自定义组件 function createDom(vDom) { const { type, props } = vDom; let dom; // 文本节点 if (type === REACT_TEXT) { dom = document.createTextNode(props.content); } else { dom = document.createElement(type); } // 更新属性 if (props) { // 更新跟节点Dom属性 .... } // 记录挂载节点 vDom.__dom = dom; return dom; }
5. 函数组件和类组件的区别
- 语法上: 类组件需要去继承
React.Component
需要更多的代码; - 状态管理: 函数组件是一个纯函数,无状态组件;类组件可以直接使用
setSate()
- 生命周期钩子: 函数组件中不能使用生命周期钩子,所有的生命周期钩子都来自于继承的
React.Component
中; - 调用方式: 函数组件可以直接调用;如果是一个类组件,需要先用
new
操作符将其实例化,然后调用render
方法
// 函数组件
function SayHi() {
return <p>Hello, React</p>
}
// React 内部
const result = SayHi(props) // » <p>Hello, React</p>
// 类组件
class SayHi extends React.Component {
render() {
return <p>Hello, React</p>
}
}
// React 内部
const instance = new SayHi(props) // » SayHi {}
const result = instance.render()
6. HTML和React中事件处理的区别
HTML | REACT | |
---|---|---|
写法 | 全小写onclick | 小驼峰onClick |
阻止默认行为 | 可以直接 return false | 必须用 event.preventDefault(); |
方法调用 | οnclick=“activateLasers()” | onClick={activateLasers} |
传参 | activateLasers(abc) | onClick={(e)=>this.handleClick(e, ‘aa’)} / onClick={this.handleClick.bind(this, ‘aa’)} |
7. React 中的合成事件
SyntheticEvent
是基于浏览器本地事件的跨浏览器包装。它的 API 与浏览器的本地事件相同,包括 stopPropagation()
和 preventDefault()
,但事件在所有浏览器中的表现均一致
8. 虚拟Dom?为什么使用?如何实现?
虚拟dom: 数据发生更改时,会计算旧的 DOM 与新的 DOM 之间的差异,更新真正改变的那部分到真实的 DOM。
作用: 虚拟 dom 相当于在 js 和真实 dom 中间加了一个缓存,利用 dom diff 算法避免了没有必要的 dom 操作,从而提高性能。
实现步骤:
1. 用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文档当中;
2. 当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,记录两棵树差异;
3. 把新旧Dom树之间差异,应用到真正的 DOM 树上,视图就更新了。
9. 在 constructor 中给 super 函数传递 props 的目的是什么?
在constructor 方法中,您可以对组件进行初始化,为属性设置默认值,并绑定事件处理程序
调用 super()
时传递 props
主要是为了拿到 this 的引用
,在子类的构造器中访问 this.props
class MyComponent extends React.Component {
constructor(props) {
//1.
super(props);
console.log(this.props); // 打印 { name: 'John', age: 42 }
// 2.但是 props 参数依然可以访问
super();
console.log(this.props); // 打印 undefined
console.log(props); // 打印 { name: 'John', age: 42 }
}
//3.在 constructor 之外没有影响
render() {
console.log(this.props); // 打印 { name: 'John', age: 42 }
}
}
10.state和props之间的区别
state
是一种数据结构,用于组件挂载时所需数据的默认值。state
是可变的,可以被修改,多数时候作为用户时间行为的结果。props
是组件的配置,由父组件传递给子组件,props
是不可变的,不能被修改
11. 什么是React生命周期
钩子函数 | 触发时机 | 作用 |
---|---|---|
constructor () | 创建组件时 | 1,初始化state; 2.为事件处理程序绑定this |
render () | 每次组件渲染都会触发 | 渲染UI( 注意不能调用setState() ) |
componentDidMount () | 组件挂载(完成DOM渲染)后 | 1.发送网络请求; 2.DOM操作 |
render() | 每次组件渲染都会触发 | 渲染UI |
componetDidUpdate() | 组件更新(完成Dom渲染)后 | 1.发送网络请求;2.Dom操作 |
componentWillUnMount() | 组件卸载之前 | 完成组件的卸载和数据的销毁 |
其他钩子:
shouldCompontentUpdate(nextProps, nextState)
是否要更新组件时触发的函数。
父组件的重新渲染会导致组件重新渲染,可以通过此钩子函数限制子组件是否需要更新,return false
可以阻止组件更新
12. React中如何使用Hooks
useState
状态管理useEffect
生命周期管理(函数组件Didmount、DidUpdate、WillUnmount时会触发;也可以监听某个state)useContext
共享状态数据useMemo
缓存值useRef
获取Dom 操作seCallback
缓存函数useReducer
redux 相似useImperativeHandle
子组件暴露值/方法useLayoutEffect
完成副作用操作,会阻塞浏览器绘制
// 1.状态钩子 useState
const [data, setData] = useState('微信公众号: 前端自学社区')
// 2.生命周期钩子 useEffect
useEffect(() => {
//默认会执行
// 这块相当于 class 组件 生命周期的 compoentDidmount compoentDidUpdate
console.log(`num: ${num}`)
console.log(`count: ${count}`)
// 组件在卸载时,将会执行 return 中内容
return () => {
// 相当于 class 组件生命周期的 componentWillUnMount
console.log('测试')
}
}, [num])
// 3.传值钩子-数据共享 useContext
// Context.js
import React from 'react';
export const MyContext = React.createContext();
// index.js
const Son = () => {
const res = useContext(MyContext)
return (<h1>{res.code}</h1>)
}
export default () => {
return (
<MyContext.Provider value={{code:200,title:'添加数据成功'}}>
<Son/>
</MyContext.Provider>
)
}
// 4.useMemo
13. React的单向数据绑定
14.什么是flux
flux
最大的特点就是单向数据流
1. 用户访问view
2. view发出用户的action
3. dispatcher收到action,更新store
4. store更新后,触发change事件
5. view收到change事件后,更新页面
15.React中如何控制组件的样式
16.React中如何进行服务器渲染
17.如何进行React性能优化
- 重写
shouldComponentUpdate
来避免不必要的 dom 操作。 - 使用 production 版本的 React.js。
- 使用 key 来帮助 React 识别列表中所有子组件的最小变化
18.React解决了什么问题
组件复用问题、性能问题、兼容性问题
19.React的协议
React遵循的协议是“BSD许可证 + 专利开源协议”,是否可以自由的使用React,取决于你的产品与FaceBook是否有竞争关系
20.shouldComponentUpdate生命周期
在比较新旧虚拟Dom时,如果我们不希望某个组件刷新,或者刷后和之前的一样,可以用这个函数直接告诉React,省去Diff
操作,进一步提高效率 。
22.怎么阻止组件的渲染
在组件的render
方法中返回null
。(不会影响触发生命周期方法)
二、react-router相关
npm install react-router-dom
安装后,直接引入,并用路由组件包裹根组件
// index.js
import ReactDOM from 'react-dom/client'
// 1. 从 react-router-dom 中引入 HashRouter
import {HashRouter} from 'react-router-dom'
import App from './App'
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
// 2. 包裹根组件,给整个应用开启路由功能,就能监听路径的改变,并且将相应的路径传递给子组件
<HashRouter>
<App />
</HashRouter>
)
1.路由跳转
//js传参
this.props.history.push('/discover/playlist');
this.props.match.params.xxx(此处为id)
this.props.location.query
//umi
import { history } from 'umi';
history.push('/' + e.key);
//标签
<Routes><Route path='/about' element={<About/>} /></Routes>
<Link to='/about'>关于</Link>
<NavLink to='/about' className='about-link'>关于</NavLink>
<Navigate to='/home' /> //重定向
2.路由模式
history
模式:<BrowserRouter>
hash
模式:<HasRouter>
PS:两种模式的区别
hash
模式背后的原理是onhashchange
事件,可以在window
对象上监听这个事件。history
利用了 H5 中新增的pushState()
和replaceState()
方法。- 除了外观上;
hash
模式#
后面的变化并不会导致浏览器向服务器发出请求,不会刷新请求、重新加载页面;history
模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致 hash
兼容性会比history
模式好,因为history
模式是依赖HTML5
的Web History API
,特定浏览器才会支持;hash
模式不利SEO
,爬虫不会读取到#
后的内容,因为会把#
当作是锚点,这也导致会与网站里的锚点功能产生冲突hash
模式,页面刷新后会导致路由state参数
丢失
3. Link、NavLink和Navigate
<NavLink>
和<Link>
的用法相似,都用于设置路径的跳转,最终会被渲染成<a>
元素.<NavLink>
是在<Link>
的基础上增加了一些样式属性,被选中时会自动添加上class='active'
<Navigate>
用于路由的重定向。只要这个组件一显示,就会自动跳转到 to 属性指定的路径中。
4.router中的路由钩子函数
useNavigate()
:用于在函数组件中进行手动跳转。
useParams()
:用于在函数组件中获取动态路由的参数。
useSearchParams()
:用于在函数组件中获取路径中的search(?号后面的)参数。
useLocation()
:用于在函数组件中获取 location。
useRoutes()
:用于在函数组件中通过配置的方式使用路由 {useRoutes(routers)}
5.路由懒加载
路由懒加载不是 React Router
提供的功能,而是借助 React 提供的 React.lazy()
来实现。 React.lazy()
需要传入一个函数作为参数,在函数内部可以使用 import()
来异步加载文件。
const About = React.lazy(() => import('./components/About'))
function App() {
return (
<div>
<div>
<Link to='/home'>首页</Link>
<Link to='/about?userId=123'>关于</Link>
</div>
<Routes>
<Route path='/home' element={<Home />} />
<Route path='/about' element={<About />} />
</Routes>
</div>
)
}
export default App
React Router 基础、组件、钩子函数
三.Redux相关
1.使用
访问:useSelector
钩子函数
调用:在Redux Toolkit
的 reducers
中写计算逻辑,在组件中用useDispatch()
钩子函数调用
// 访问
const count = useSelector(state => state.counter.value)
// 调用
// 1.在Redux Toolkit中配置
export const counterSlice = createSlice({
name: 'counter',
initialState: {value: 0},
reducers: {
increment: (state, action) => {
state.value += 1
},
}
})
//2.全局注册 store
import {configureStore} from '@reduxjs/toolkit'
import counterReducer from '../features/counter/counterSlice'
export default configureStore({
reducer: {
counter: counterReducer
}
})
// 3.引入 调用dispatch方法,并传入一个action对象
import {increment} from './counterSlice'
onClick={
() => dispatch(increment({ name: '参数' }))
}
2.state管理
view
:基于当前状态的视图声明性描述state
:驱动应用的真实数据源头actions
:根据用户输入在应用程序中发生的事件,并触发状态更新reducer
: reducer 是一个函数,可以将 reducer 视为一个事件监听器,它根据接收到的 action(事件)类型处理事件。
3.单向数据流
- State 描述了应用程序在特定时间点的状况
- 基于 state 来渲染视图
- 当发生某些事情时(例如用户单击按钮),state 会根据发生的事情进行更新
- 基于新的 state 重新渲染视图
Redux 中文官网