[toc]
React
- React.Component React.PureComponent 区别
PureComponent 通过 props 和 state 的 浅对比实现 shouldComponentUpdate;前者需要自己实现
当input设置了value,但是没有设置onChange时会报错,可设置defaultValue或把onChange事件加上
ReactDOM.render(< div>当要添加多个标签时要用div包含在内</ div>,容器元素对象)
jsx中写js的代码用{}括起来;之外可以正常用;
react推荐使用内联样式
img 引入图片
- css 设置背景图
- src="require('xx/xx/x.jpg')" // 该方式在最新的 create-react-app 脚手架搭建的项目中已经不能使用 ,使用方式以脚手架或自己搭建的项目方式为准
- import logo from './public/logo.png'; // create-react-app 可用
React.createElement(标签名|函数组件|class组件, { ...props }, children)
React.cloneElement(createElement创建的元素)
react 严格模式 StrictMode, 用了antd 后,会报错,删除严格模式即可
<React.StrictMode>
<App />
</React.StrictMode>
- HOC: 参见 react-admin ;(与公共组件区别,主要是公共组件应该是多地方引用相同的组件,而不需要修改公共组件内容)
- 在 create-react-app 中使用 装饰器:
- npm run eject
- 配置babel
"plugins": [
[
"@babel/plugin-proposal-decorators", 这里的插件,create-react-app 已经安装
{
"legacy": true
}
]
]
- 勾选 vscode 中的 typescript 配置 "javascript.implicitProjectConfig.experimentalDecorators": true
组件
组件中 this 两种方式调用当前组件
// 方式一:
constructor(props) {
this.handleClick = this.handleClick.bind(this);
}
// 方式二:利用箭头函数
onChange = () => {
console.log(this);
}
- function component
function Welcome(props) {
return < h1>Hello, { props.name}< /h1>;
}
- es6语法
class Welcome extends React.Component {
render() {
return < h1>Hello, {this.props.name}< /h1>;
}}
组件类名必须大写,且只能包含一个顶层标签
通过this.props.属性名,来获取参数
属性名class要用 className,for要用htmlFor
复合组件要用div标签包含起来
this.props的属性与组件的属性一一对应,但是this.props.children例外,它表示组件的所有子节点,它会返回undefind,object,array类型的值,所以react提供了React.Children来处理它可以用React.Children.map(),来遍历就不用担心返回的是什么类型的值。
ref和findDOMNode
- 在节点上设置ref属性,然后用this.refs.属性名即可获取到真实的节点
- ref添加到Compoennt上获取的是Compoennt实例,添加到原生HTML上获取的是DOM
- ReactDOM.findDOMNode,当参数是DOM,返回值就是该DOM(这个没啥卵用);当参数是Component获取的是该Component render方法中的DOM,返回的都是DOM
对于表单value 不能用this.props来获取,只能用event.target.value获取
组件的生命周期 mounting:已插入真实的DOM
updating:正在被重新渲染
unmounting:已移除真实的DOM
will:函数在进入状态之前,did:函数在进入状态之后
componentWillMount()
componentDidMount()
componentWillUpdate(object nextProps, object nextState)
componentDidUpdate(object prevProps, object prevState)
componentWillUnmount()
Mounted:组件被render解析,生成对应DOM节点并被插入浏览器DOM结构的过程。
Update:mounted的组件被重新render的过程。
Unmounted:组件对应的DOM节点被从DOM结构中移除的过程。
每一个状态都封装了相应的hook(钩子)函数
状态state
初始状态用getInitialState对象赋值
getInitialState:function(return {状态名:值})
该对象可以用this.state获取
用this.setState修改该对象,每次修改都会重新调用this.render方法重新渲染
在渲染是修改了state或props会陷入死循环。
props和state
props是不可以改变的
赋初值一般用于 props 未赋值,但又不能为 null 的情况
组件名.defaultProps = {
key: value
};
组件的属性类型判断,验证props 使用 prop-types 库
Hook
实践代码: react-admin/src/pages/practice/hooks
- 使函数组件拥有状态 useState
- 只能放到函数组件中,如(useParams)
- 复杂状态用
useReducer()
// 必须放在函数内顶部
const [ val, setVal ] = useState('initValue') // 返回数组,第一个值是设置的值,第二个值是更新这个值的函数
// 这里用数组 就是为了可以自己定义 state 和修改state函数的名字,如果用对象解构 名字就需要固定
setVal(old => old+1) // 采用回调方式更新,更好,修改后 react 会自动渲染对应UI,不会将新的 state和旧的state 合并
原理:全局维护了一个 workInProgressHook 变量,多个数据间是采用链式的通过 next 进行的串联结构,所以不能在判断,循环,嵌套中使用,否则破坏链式结构
拥有了生命周期的概念(对应关系):
constructor -> useState
getDerivedStateFromProps -> useState 中的 update 函数
shouldComponentUpdate -> useMemo
render -> 函数本身
componentDidMount -> useEffect
componentDidUpdate -> useEffect
componentWillUnmount -> useEffect 里返回的函数
Redux
Action 发出以后,Reducer 立即算出 State,这叫做同步;Action 发出以后,过一段时间再执行 Reducer,这就是异步。
参考示例: https://www.redux.org.cn/docs/basics/ExampleTodoList.html
基本概念
store
保存数据的地方,可看成一个容器,整个应用只能有一个store
redux提供了createStore函数接收一个函数参数,返回新的store对象
state
store对象包含了所有数据,如果想得到某个时点的数据就要对store生成快照,这种时点的数据结合就叫state
当前时刻的state可以用store.getState()获得一个state对应一个view
action
state的变化会导致view的变化,但是用户只能看到view,所以state的变化是view导致的, action就是view发出的通知,告知state要变了
action是一个对象,type属性是必须的,其它的随意
store.dispatch()是view发出action的唯一方法,可接受一个action对象作为参数。
reducer
store接收到action后,必须给出一个新的state,view才会变化,这就是reducer过程。
reducer函数接收state和action参数,返回一个新的state。 简单的通过 switch 判断不同的 action 返回不同的state 通过 connect 连接多个reducer store.dispatch()方法会触发reducer的自执行
subscribe
可以用subscribe函数监听store,一旦state发生变化就自动执行这个函数,该方法返回一个函数,调用这个函数就可以接触监听。
redux-toolkit
教程 https://penueling.com/%E6%8A%80%E8%A1%93%E7%AD%86%E8%A8%98/react-react-redux-redix-toolkit-%E6%96%B0%E6%89%8B%E6%95%99%E5%AD%B8/
- createSlice() 根据传递的参数自动生成相应的actionCreator和reducer函数 https://blog.csdn.net/ilovethesunshine/article/details/109627560
react-router
react-router 和react-router-dom 只要引用一个就行了,不同之处就是后者比前者多出了 < Link> < BrowserRouter> 这样的 DOM 类组件。
因此我们只需引用 react-router-dom 这个包就行了。当然,如果搭配 redux ,你还需要使用 react-router-redux。
exact
精准定位路由 匹配 '/' 跟路由时作用明显
create-react-app
- 修改端口: 创建
.env
文件
PORT=3006
使用 eject 暴露出配置后 可以在 config/webpack.config.js 中配置 alias '@': path.resolve(__dirname, '../src'),
- 修改端口号和关闭自动打开浏览器:
- 修改package.json的"start" 值为:
set BROWSER=none&&set PORT=3800 reatc-scripts start
- 修改node_modules/af-webpack/lib/dev.js中的如下代码
- 修改package.json的"start" 值为:
const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 5656; // 修改默认值
(0, _openBrowser.default)(urls.localUrlForBrowser); // 注释该行