本文目录
- 1、react中使用antd组件库
- 2、Immutable
- 2.1 深拷贝和浅拷贝的关系
- 2.2 immutable优化性能方式
- 2.3 immutable的Map使用
- 2.4 immutable的List使用
- 2.5 实际场景formJS
- 3、redux中使用immutable
- 4、react路由中使用ts
- 5、redux中使用ts
- 6 、styled-components
- 6.1 安装使用
- 6.2 基于props做样式判断
- 6.3 样式化任意组件
- 6.4 动画
1、react中使用antd组件库
运行命令create-react-app antd-react
创建新项目:
运行命令npm i antd
安装:
使用:
import React from 'react'
import ReactDOM from 'react-dom'
import 'antd/dist/antd.css';
import { Button } from 'antd';
ReactDOM.render(
<div>
<Button type="primary">Primary Button</Button>
</div>,
document.getElementById("root"));
2、Immutable
每次修改一个immutable对象时都会创建一个新的不可变的对象,在新对象上操作并不会影响到原对象的数据。
2.1 深拷贝和浅拷贝的关系
1、
Object.assign
或者...
只是一级属性赋值,比浅拷贝多拷贝了一层而已。
2、const obj1 = JSON.parse(JSON.stringify(obj))
数组,对象都好用(缺点:不能有字段为undefined
)。
2.2 immutable优化性能方式
immutable实现的原料是Persistent Data Structure(持久化数据结构),也就是使用旧数据创建新数据时,要保准旧数据同时可用且不变。同时为了避免deepCopy把所有节点都复制一遍带来的性能损耗,immutable使用了structural sharing(结构共享),即如果对象树中一个节点发生变化,只修改这个节点和受它影响的父节点,其它节点则进行共享。
安装输入命令npm i immutable
:
2.3 immutable的Map使用
map
使用(map只能套一层,如果属性还是对象或者数组的话就再套一层):
import React from 'react'
import { createRoot } from 'react-dom/client';
import 'antd/dist/antd.css'
import { Button } from 'antd'
import {Map} from 'immutable'
var obj = {
name: 'immutable'
}
var oldObj = Map(obj)
console.log(oldObj)
// 更改值
var newObj = oldObj.set('name', 'react')
// 1.获取值:get获取
console.log(oldObj.get('name'), newObj.get('name'))
// 2.获取值:普通对象
console.log(oldObj.toJS(), newObj.toJS())
const container = document.getElementById('root')
const root = createRoot(container)
root.render(
<div>
<Button type="primary">Primary Button</Button>
</div>
)
效果:
state
中使用:
import React, { Component } from 'react'
import { Map } from 'immutable'
export default class imMap extends Component {
state = {
info: Map({
name: 'immutable',
key: 100
})
}
render() {
return (
<div>
<button onClick={() => {
this.setState({
info: this.state.info.set('name', 'react').set('key', 101)
})
}}>onclick</button>
{this.state.info.get('name')} --
{this.state.info.get('key')}
</div>
)
}
}
可以看到多个值时,immutable可以链式操作。
2.4 immutable的List使用
import React, { Component } from 'react'
import {List} from 'immutable'
var arr = List([1,2,3])
var arr1 = arr.push(4)
var arr2 = arr1.concat([5])
console.log(arr.toJS(), arr1.toJS(), arr2.toJS())
export default class ImList extends Component {
render() {
return (
<div>ImList</div>
)
}
}
效果:
2.5 实际场景formJS
在实际开发中我们的state中数据结构一般来自后端返回的,那么我们将使用formJS
:
import React, { Component } from 'react'
import { fromJS } from 'immutable'
export default class ImFromJs extends Component {
state = {
info: fromJS({
list: ['1', '2', '3'],
obj: {
name: 'immutable',
key: 100,
}
})
}
render() {
return (
<div>ImFromJs
<div><button onClick={() => {
this.setState({
info: this.state.info.setIn(['obj', 'name'], 'react')
})
}}>改变标题</button></div>
<div><button onClick={() => {
this.setState({
info: this.state.info.updateIn(['list'], (oldList) => {
return oldList.push(oldList._tail.array.length + 1)
})
})
}}>改变数组</button></div>
<div>{this.state.info.getIn(['obj', 'name'])}</div>
<div>
<ul>
{
this.state.info.get('list').map((item, index) => {
return <li key={index}>{item}
<button onClick={() => {
this.setState({
info: this.state.info.updateIn(['list'], (oldList) => {
return oldList.splice(index, 1)
})
})
}}>del</button>
</li>
})
}
</ul>
</div>
</div>
)
}
}
效果:
3、redux中使用immutable
4、react路由中使用ts
输入命令npm i react-router-dom@5
安装路由:
再输入命令:npm i --save-dev @types/react-router-dom
安装路由类型推断。新建如下文件:
Film.tsx
写入如下代码:
import axios from 'axios'
import { Component } from 'react'
import { RouteComponentProps } from 'react-router-dom'
interface JItem {
cinemaId: number,
name: string
}
export default class Film extends Component<RouteComponentProps> {
state = {
cinemaList: []
}
componentDidMount() {
axios({
url: 'https://m.maizuo.com/gateway?cityId=110100&ticketFlag=1&k=3085018',
method: 'get',
headers: {
'X-Client-Info':' {"a":"3000","ch":"1002","v":"5.2.0","e":"1646314068530784943341569"}',
'X-Host': 'mall.film-ticket.cinema.list'
}
}).then((res) => {
this.setState({
cinemaList: res.data.data.cinemas
})
}).catch((err) => {
console.log(err)
})
}
render() {
return (
<div>
<ul>
{
this.state.cinemaList.map((item: JItem) =>
<li key={item.cinemaId} onClick={() => {
this.props.history.push(`/cinema/${item.cinemaId}`)
}}>{item.name}</li>
)
}
</ul>
</div>
)
}
}
Cinema.tsx
写入如下代码:
import { Component } from 'react'
import { RouteChildrenProps } from 'react-router-dom'
interface IParams {
cinemaId: string
}
export default class Cinema extends Component<RouteChildrenProps<IParams>> {
componentDidMount() {
console.log((this.props.match?.params as any).cinemaId)
console.log(this.props.match?.params.cinemaId)
}
render() {
return (
<div>Cinema</div>
)
}
}
新建router\router.tsx
,写入代码:
import { Component } from 'react'
import {HashRouter, Route} from 'react-router-dom'
import Center from '../component/Center'
import Cinema from '../component/Cinema'
import Film from '../component/Film'
export default class Router extends Component {
render() {
return (
<HashRouter>
<Route path="/film" component={Film}></Route>
<Route path="/cinema/:cinemaId" component={Cinema}></Route>
<Route path="/center" component={Center}></Route>
</HashRouter>
)
}
}
新建router\index.tsx
,写入代码:
import React, { Component } from 'react'
import store from '../redux/store'
import Router from './router'
export default class Index extends Component {
render() {
return (
<div>
<Router></Router>
</div>
)
}
}
可以看到ts
的写法与普通js
写法多了RouteComponentProps
类型推断,并且自己写的interface JItem
接口去对接cinemaId
,name
类型。
在Cinema.tsx
子组件中,也多了RouteComponentProps
类型推断,并且取路由传参过来的值,第一种方法使用了类型推断。第二种方法是自己写了一个接口去对接类型。这两种方法都可以取到值。
效果:
5、redux中使用ts
新建redux\store.ts
,写入如下代码:
import { createStore } from "redux"
interface IAction {
type: string,
payload?: any
}
interface IState {
isShow: boolean
}
const reducer = (prevState:IState={
isShow: true
},
action: IAction) => {
const {type} = action
const newState = {...prevState}
switch(type) {
case "show":
newState.isShow = true
return newState
case "hide":
newState.isShow = false
return newState
default:
return prevState
}
}
const store = createStore(reducer)
export default store
router\index.tsx
修改为如下代码:
import React, { Component } from 'react'
import store from '../redux/store'
import Router from './router'
export default class Index extends Component {
state = {
isShow: store.getState().isShow
}
componentDidMount() {
store.subscribe(() => {
console.log(store.getState())
this.setState({
isShow: store.getState().isShow
})
})
}
render() {
return (
<div>
<Router></Router>
{
this.state.isShow && <div>显示/隐藏</div>
}
</div>
)
}
}
可以看到在redux
中我们定义了两个接口去限制了state
和action
的类型推断,让我们在写代码的阶段就能够将写错字母的问题给提前发现。效果:
6 、styled-components
6.1 安装使用
styled-components
它是通过javascript
改变css
编写方式的解决方案之一,从根本上解决常规css
编写的一些弊端。
通过javascript
来为css
赋能,能达到常规css
所不好处理的逻辑复杂、函数方法、复用、避免干扰。样式书写将直接依附在jsx
上面,html
、css
、js
三者再次内聚。all is js
思想。
运行安装命令npm i styled-components
在项目中创建文件夹styled-components
及其子文件StyleComponent.js
,并在index.js
引入:
在StyleComponent.js
写入代码:
import React, { Component } from 'react'
import styled from 'styled-components'
export default class StyleComponent extends Component {
render() {
const StyledFooter = styled.footer`
background:yellow;
position: fixed;
left: 0;
bottom: 0;
width: 100%;
height: 50px;
line-height: 50px;
text-align: center;
ul {
display: flex;
list-style-type: none;
li {
flex: 1;
}
}
`
return (
<StyledFooter>
<ul>
<li>首页</li>
<li>列表</li>
<li>我的</li>
</ul>
</StyledFooter>
)
}
}
效果:
可以看到我们引入的styled
就是一个组件.footer
将会生成footer
标签并用模版字符串进行样式写法,支持像sass
的嵌套写法
6.2 基于props做样式判断
import React, { Component } from 'react'
import styled from 'styled-components'
export default class StyleComponent extends Component {
render() {
const StyledButton = styled.button`
background: ${props=>props.bg || 'blue'}
`
return (
<div>
<StyledButton>btn</StyledButton>
<StyledButton bg="yellow">btn</StyledButton>
</div>
)
}
}
效果:
6.3 样式化任意组件
import React, { Component } from 'react'
import styled from 'styled-components'
export default class StyleComponent extends Component {
render() {
const Child = (props) => <div className={props.className}>child</div>
const StyledChild = styled(Child)`
background: ${props=>props.bg || 'blue'};
color: #fff;
`
return (
<div>
<StyledChild>btn</StyledChild>
</div>
)
}
}
6.4 动画
import React, { Component } from 'react'
import styled, {keyframes} from 'styled-components'
export default class StyleComponent extends Component {
render() {
const rotate360 = keyframes`
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
`
const Rotate = styled.div`
position: absolute;
left: 50px;
top: 100px;
background: blue;
width: 100px;
height: 100px;
animation: ${rotate360} 1s linear infinite;
`
return (
<div>
<Rotate></Rotate>
</div>
)
}
}
效果:
可以看到我们引入了keyframes
,进行了动画编写。