文章目录
常用的css属性
styled-components的使用(css样式组件)
github地址:
https://github.com/styled-components/styled-components
styled-components允许您编写实际的 CSS 代码来设置组件的样式。它还删除了组件和样式之间的映射。
InnerRef
在styled-components中使用innerRef代替ref
<Input placeholder='账号' innerRef={(input)=>{this.account=input}}/>
复选框
- checkbox.checked属性可以用来判断复选框是否被选中
<CheckBoxWrapper>
<CheckBox id="checkbox" type="checkbox"/>
<CheckBoxLabel htmlFor="checkbox"/>
</CheckBoxWrapper>
const CheckBoxWrapper = styled.div`
position: relative;
`
const CheckBoxLabel = styled.label`
position: absolute;
top: 0;
left: 0;
width: 42px;
height: 26px;
border-radius: 15px;
background: #BEBEBE;
cursor: pointer;
`;
const CheckBox = styled.input`
opacity: 0;
z-index:1;
border-radius: 15px;
width: 42px;
height: 26px;
`;
react-transition-group的使用(设置动画)
github地址:
https://github.com/reactjs/react-transition-group
下载:
npm install @types/react-transition-group
引入:
使用:
设置动画效果:
redux(统一管理状态)
安装:
yarn add redux
yarn add react-redux
原理:
创建store文件夹:
index.js中存储数据,创建store
import { createStore } from "redux";
import Reducer from './reducer'
// 引入需要用到的reducer
const store = createStore(Reducer);
export default store
Header组件:
//在Header组件中引入connect
import { connect } from 'react-redux'
//将state状态映射到props上
const mapStateToProps = (state) => {
return {
//在props中属性名为focused
focused: state.header.focused,
}
}
//将需要修改state的函数
const mapDispathToProps = (dispatch) => {
return {
//向props中映射一个函数名为onFocusHandle
//当这个函数被触发时,就会让reducer更改state,页面重新渲染。
onFocusHandle() {
//定义一个action
const action = {
type:'search_focus'
}
//将action传递给reducer,供reducer判断
dispatch(action)
},
onBlurHandle() {
const action = {
type:'search_blur'
}
dispatch(action)
}
}
}
//改变暴露Header组件的方式
export default connect(mapStateToProps,mapDispathToProps)(Header)
HeaderReducer中通过传递过来的action对state进行修改,
将每个组件需要的reducer单独定义,使代码易于维护。
//state中状态的初始化
const defaultState = {
focused:false
}
//暴露一个纯函数
export default (state = defaultState, action) => {
//对传入的action对state中的状态进行修改
if (action.type === 'search_focus') {
return {
focused:true
}
}
if (action.type === 'search_blur') {
return {
focused:false
}
}
return state
}
在总的reducer中整合所有的reducer
import { combineReducers } from "redux";
import HeaderReducer from "../common/Header/store/reducer";
export default combineReducers({
header:HeaderReducer
})
App组件中:
import React, { Fragment } from "react";
import Header from "./common/Header";
//引入store
import store from "./store";
//引入Provider组件
import { Provider } from 'react-redux'
class App extends React.Component {
render() {
return (
//该<Provider>组件使 Redux store可用于任何需要访问 Redux 存储的嵌套组件。
<Provider store={store}>
<Header />
</Provider>
)
}
}
优化
将action和constants提出来作为单独的文件。
actions文件:返回对象
constants文件
redux调试工具(redux-devtools)
github地址:
https://github.com/reduxjs/redux-devtools/tree/main/extension
import { createStore,applyMiddleware ,compose } from "redux";
import thunk from "redux-thunk";
import Reducer from './reducer'
// 引入需要用到的reducer
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(Reducer, composeEnhancers(
applyMiddleware(thunk)
));
export default store
immutable.js
github地址:
https://immutable-js.com/
不可变数据一旦创建就无法更改,从而使应用程序开发更加简单,无需防御性复制,并通过简单的逻辑实现高级记忆和更改检测技术。持久数据提供了一个可变 API,它不会就地更新数据,而是总是产生新的更新数据。
下载:
npm install immutable
预防state被改变,将state设置为immutable
immutable对象的获取和设置
设置:
获取:
redux-immutable
npm install redux-immutable
redux-thunk
Redux 的Thunk中间件。它允许编写内部带有逻辑的函数,这些函数可以与 Redux 存储dispatch和getState方法进行交互。允许在action中进行异步操作。
安装:
npm install redux-thunk
导入redux-thunk
//添加applyMiddleware
import { createStore,applyMiddleware,compose } from "redux";
//引入中间件
import thunk from "redux-thunk";
import Reducer from './reducer'
// 引入需要用到的reducer
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(Reducer, composeEnhancers(
applyMiddleware(thunk)
));
export default store
axios(异步请求获取数据)
axios中文文档:
http://axios-js.com/zh-cn/docs/index.html
axios是一个基于promise的HTTP库,
安装:
npm install axios
//get请求
axios.get('/user', {
params: {
ID: 12345
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
//post请求
axios.post('/user', {
firstName: 'Fred',
lastName: 'Flintstone'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
react-router-dom
BrowserRouter,Routers,Route:
npm i react-router-dom
在需要引入路由的js文件引入browserRouter和route
import { BrowserRouter , Route} from “react-router-dom”;
在route6中:
import React, { Fragment } from "react";
//引入路由相关的组件
import { BrowserRouter,Route,Routes} from "react-router-dom";
import Header from "./common/Header";
import store from "./store";
import { Provider } from 'react-redux'
import Home from "./pages/home";
import Detail from "./pages/detail";
class App extends React.Component {
render() {
return (
<Provider store={store}>
<Fragment>
<Header />
//使用BrowserRouter包裹所有与路由相关的内容
<BrowserRouter>
//Routes与Switch中的功能相同
//Routes让下面的所有路由中只有一个可以匹配到,当有一个匹配到的时候,不在进行匹配。
<Routes>
//route6中使用element代替component
<Route path="/" element={<Home/>}></Route>
<Route path="/detail" element={<Detail/>}></Route>
</Routes>
</BrowserRouter>
</Fragment>
</Provider>
)
}
}
export default App
Link
使用Link组件代替a标签的跳转
import { Link } from 'react-router-dom'
<Link to='/'>
<Logo />
</Link>
Link 新建一个浏览器窗口打开
_self :默认。在相同的框架中打开被链接文档。
_blank: 新开一个窗口打开文档
_parent : 在父框架集中打开被链接文档。
_top:在整个窗口中打开被链接文档。
<Link target='_blank' to='/download'>
<NavItem className='left'>
<i className='iconfont'></i>
下载App
</NavItem>
</Link>
Redirect/Navigate
重定向组件
relplace模式:是会将最顶上的浏览记录替换掉,
push模式:会在浏览器中的history存有记录。
<Redirect to='/'/>
<Navigate to={'/login'} replace='true'/>
//其中relplace是会将最顶上的浏览记录替换掉,
//push模式,会在浏览器中的history存有记录。
- 在V6中已经删除重定向redirect,替换成navigate
- 在V5中使用编程式导航,需要使用this.props.history对象上的API进行跳转、前进、后退。
this.props.history.push()
this.props.history.replace()
this.props.history.goBack()
this.props.history.goForward()
this.props.history.go()
性能优化
使用PureComponent
将class app extends component替换成class app extends PureComponent
PureComponent在底层实现了shouldComponentUpdate
由于我们的组件几乎都使用了connect进行连接,所以一旦store中的数据发生了改变,所有的组件都会重新渲染,而此时存在一些组件,发生改变的数据和该组件无关,但是该组件也进行了渲染。使用shouldComponentUpdate钩子,可以通过return false的方式阻止该组件的渲染。
shouldComponentUpdate这个生命周期钩子,用于判断只有和该组件相关的数据发生改变的时候,才渲染这个组件。
其他问题
防止字符串中的html内容被转义
//在组件中设置
<Content dangerouslySetInnerHTML={{__html:this.props.content}}/>
完成“记住我”功能
未设置过期时间
1. 使用local storage记住用户的信息
const user = {
account: account,
password:password
}
// 如果复选框被选中,保存账号密码
if (checkbox.checked) {
localStorage.setItem('user',JSON.stringify(user))
}
2. 在componentDidMount中获取用户的信息,如果存在,更改store中的login属性为true
componentDidMount() {
// 获取local storage中的user
const user =localStorage.getItem('user')
if (user) {
// 更改store中的login
this.props.changeLogin()
}
}
3. 点击退出按钮时,将存在store中的user属性删除。
// 清楚local storage中保存的user信息
localStorage.removeItem('user')
设置过期时间,在原型链上设置setExpire,getExpire
// 给local storage设置过期时间
Storage.prototype.setExpire = (key, value, expire) => {
let obj = {
data: value,
time: Date.now(),
expire:expire
}
localStorage.setItem(key,JSON.stringify(obj))
}
localStorage.setExpire('user',user,10000)
// 给storage中添加函数,判断是否过期
Storage.prototype.getExpire = key => {
let val = localStorage.getItem(key)
if (!val) {
return val;
}
val = JSON.parse(val)
if (Date.now() - val.time > val.expire) {
localStorage.removeItem(key)
return null
}
return val.data
}
const user= localStorage.getExpire('user')
完成PC端屏幕自适应(BootStrap)
在index.html中引入
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css"
integrity="sha384-9gVQ4dYFwwWSjIDZnLEWnxCjeSWFphJiwGPXr1jddIhOegiu1FwO5qRGvFXOdJZ4" crossorigin="anonymous">
<title>React App</title>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js"
integrity="sha384-cs/chFZiN24E4KMATLdqdvsezGxaGsi4hLGOzlXwp5UZB1LY//20VyM2taTB4QvJ"
crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js"
integrity="sha384-uefMccjFJAIv6A+rW+L4AHf99KvxDjWSu1z9VI8SKNVmz4sk7buKt/6v9KI65qnm"
crossorigin="anonymous"></script>