import React,{Component} from 'react'
import './header.less'
export default class Header extends Component{
render(){
return(
<div className='header'>
<div className='header-top'>
<span>欢迎,admin</span>
<a href='javascript:'>退出</a>
</div>
<div className='header-bottom'>
<div className='header-bottom-left'>
<span>首页</span>
</div>
<div className='header-bottom-right'>
<span>2020-2-6 10:10:10</span>
<img src='http://www.weather.com.cn/m2/i/icon_weather/21x15/d14.gif' alt='天气'/>
<span>雪</span>
</div>
</div>
</div>
)
}
}
.header{
height: 80px;
.header-top{
height: 40px;
line-height: 40px;
// 以上两行控制行内文字居中
text-align:right;
border-bottom: 2px solid lightseagreen;
padding-right: 30px;
span{
margin-right:10px;
}
}
.header-bottom{
height: 40px;
background-color: white;
display:flex;
align-items: center;
padding:0 30px;
.header-bottom-left{
width: 25%;
text-align:center;
font-size: 18px;
position: relative;
//以下用伪元素::after及transform来实现下指三角形
&::after {
content: '';
position: absolute;
right: 50%;
top: 100%;
transform: translateX(50%);
border-top: 20px solid white;
border-right: 20px solid transparent;
border-bottom: 20px solid transparent;
border-left: 20px solid transparent;
}
}
.header-bottom-right{
width:75%;
text-align:right;
img{
margin: 0 10px;
height:4px;
width:3px;
}
}
}
}
1). jsonp只能解决GET类型的ajax请求跨域问题
2). jsonp请求不是ajax请求, 而是一般的get请求
3). 基本原理
浏览器端:
动态生成<script>来请求后台接口(src就是接口的url)
定义好用于接收响应数据的函数(fn), 并将函数名通过请求参数提交给后台(如: callback=fn)
服务器端:
接收到请求处理产生结果数据后, 返回一个函数调用的js代码, 并将结果数据作为实参传入函数调用
浏览器端:
收到响应自动执行函数调用的js代码, 也就执行了提前定义好的回调函数, 并得到了需要的结果数据
Request URL: http://api.map.baidu.com/telematics/v3/weather?location=%E5%BE%90%E5%B7%9E&output=json&ak=3p49MVra6urFRGOT9s8UBWr2&callback=__jp0
注意最后多了一个callback=__jp0
,它指定了返回时用来处理数据的函数名__jp0&&__jp0({"error":0,"status":"success",...})
在network里查看请求,注意看它的名字和请求时的指定一样jsonp(url, opts, fn)
url (String) url to fetch
opts (Object), optional
param (String) name of the query string parameter to specify the callback (defaults to callback)
timeout (Number) how long after a timeout error is emitted. 0 to disable (defaults to 60000)
prefix (String) prefix for the global callback functions that handle jsonp responses (defaults to __jp)
name (String) name of the global callback functions that handle jsonp responses (defaults to prefix + incremented counter)
fn callback
The callback is called with err, data parameters.
If it times out, the err will be an Error object whose message is Timeout.
Returns a function that, when called, will cancel the in-progress jsonp
request (fn won't be called).
【1】天气接口函数
【2】返回一个promise函数
【3】发送一个jsonp请求,{}内为空意思是使用默认配置选项
【4】异步返回成功数据给调用者
【5】异步返回失败信息给调用者
// 【1】天气接口函数
export const reqWeather=(city) => {
//百度天气api接口
const url = `http://api.map.baidu.com/telematics/v3/weather?location=${city}&output=json&ak=3p49MVra6urFRGOT9s8UBWr2`
//【2】返回一个promise函数
return new Promise((resolve,reject) => {
//【3】发送一个jsonp请求,{}内为空意思是使用默认配置选项
jsonp(url,{},(err,data) => {
//【3.1】如果请求成功
if(!err && data.status==='success'){
//请求成功处理语句编写处
resolve({obj}) //【4】异步返回成功数据给调用者
}else{//【3.2】如果请求失败
//请求失败处理语句编写处
reject() //【5】异步返回失败信息给调用者
}
})
})
}
http://api.map.baidu.com/telematics/v3/weather
GET
|参数 |是否必选 |类型 |说明
|location |Y |string |城市名称
|output |Y |string |返回数据格式: json
|ak |Y |string |唯一的应用key(3p49MVra6urFRGOT9s8UBWr2)
{
"error": 0,
"status": "success",
"date": "2019-06-02",
"results": [
{
"currentCity": "北京",
"pm25": "119",
"index": [
{
"des": "建议着长袖T恤、衬衫加单裤等服装。年老体弱者宜着针织长袖衬衫、马甲和长裤。",
"tipt": "穿衣指数",
"title": "穿衣",
"zs": "舒适"
},
{
"des": "不宜洗车,未来24小时内有雨,如果在此期间洗车,雨水和路上的泥水可能会再次弄脏您的爱车。",
"tipt": "洗车指数",
"title": "洗车",
"zs": "不宜"
},
{
"des": "各项气象条件适宜,无明显降温过程,发生感冒机率较低。",
"tipt": "感冒指数",
"title": "感冒",
"zs": "少发"
},
{
"des": "天气较好,赶快投身大自然参与户外运动,尽情感受运动的快乐吧。",
"tipt": "运动指数",
"title": "运动",
"zs": "适宜"
},
{
"des": "紫外线强度较弱,建议出门前涂擦SPF在12-15之间、PA+的防晒护肤品。",
"tipt": "紫外线强度指数",
"title": "紫外线强度",
"zs": "弱"
}
],
"weather_data": [
{
"date": "周日 06月02日 (实时:30℃)",
"dayPictureUrl": "http://api.map.baidu.com/images/weather/day/duoyun.png",
"nightPictureUrl": "http://api.map.baidu.com/images/weather/night/leizhenyu.png",
"weather": "多云转雷阵雨",
"wind": "西南风3-4级",
"temperature": "31 ~ 20℃"
},
{
"date": "周一",
"dayPictureUrl": "http://api.map.baidu.com/images/weather/day/duoyun.png",
"nightPictureUrl": "http://api.map.baidu.com/images/weather/night/duoyun.png",
"weather": "多云",
"wind": "南风微风",
"temperature": "34 ~ 20℃"
},
{
"date": "周二",
"dayPictureUrl": "http://api.map.baidu.com/images/weather/day/leizhenyu.png",
"nightPictureUrl": "http://api.map.baidu.com/images/weather/night/leizhenyu.png",
"weather": "雷阵雨",
"wind": "东风微风",
"temperature": "28 ~ 21℃"
},
{
"date": "周三",
"dayPictureUrl": "http://api.map.baidu.com/images/weather/day/duoyun.png",
"nightPictureUrl": "http://api.map.baidu.com/images/weather/night/duoyun.png",
"weather": "多云",
"wind": "北风3-4级",
"temperature": "33 ~ 19℃"
}
]
}
]
}
【0】借用antd返回信息组件
【1】天气请求接口函数编写
【2】从数据中解构取出图片、天气
【3】异步返回图片、天气给调用函数者
【4】返回错误信息给调用者
import ajax from './ajax'
import jsonp from 'jsonp'
import {message} from 'antd' //【0】借用antd返回信息组件 默认暴露不要大括号,否则需要大括号
// const BASE = 'http://localhost:5000'
const BASE = ''
//导出一个函数,第1种写法
//登录接口函数
// export function reqLogin(username,password){
// return ajax('login',{username,password},'POST')
// }
//导出一个函数,第2种写法
// 登录接口函数
export const reqLogin=(username,password)=>ajax(BASE+'login',{username,password},'POST')
//添加用户接口
export const AddUser=(user)=>ajax(BASE+'/manage/user/add',user,'POST')
// 【1】天气请求接口函数编写
export const reqWeather=(city) => {
const url = `http://api.map.baidu.com/telematics/v3/weather?location=${city}&output=json&ak=3p49MVra6urFRGOT9s8UBWr2`
//返回一个promise函数
return new Promise((resolve,reject) => {
//发送一个jsonp请求
jsonp(url,{},(err,data) => {
//输出请求的数据到控制台
console.log('jsonp()', err, data)
//如果请求成功
if(!err && data.status==='success'){
//【2】从数据中解构取出图片、天气
const {dayPictureUrl,weather}=data.results[0].weather_data[0]
//【3】异步返回图片、天气给调用函数者
resolve({dayPictureUrl,weather})
}else{//如果请求失败
//【4】返回错误信息给调用者
message.error('天气信息获取失败')
}
})
})
}
reqWeather('上海')
刷新页面即会在控制台输入【1.3 的 返回示例】类似的信息,之所以会直接运行,原因是login页面请求了api,从而触发reqWeather(‘上海‘)直接运行
Date.now() //返回样式:1581070286188
功能:把【时间获取Date.now()】的时间处理成如下格式 2020-2-6 10:10:10
/*
包含n个日期时间处理的工具函数模块
*/
/*
格式化日期
*/
export function formateDate(time) {
if (!time) return ''
let date = new Date(time)
return date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate()
+ ' ' + date.getHours() + ':' + date.getMinutes() + ':' + date.getSeconds()
}
【1】时间格式化工具
【2】内存中存取用户信息工具
【3】当前时间格式化后的字符串
【4】每过一秒获取一次系统时间
定时器函数setInterval(()=>{},1000)
【5】在第一次render()之后执行一次
一般在此执行异步操作: 发ajax请求/启动定时器
【6】解构state内的数据
【7】获取memoryUtils中的用户名
【8】把变量填入标签内:用户名、当前时间、天气图标、天气
import React,{Component} from 'react'
import './header.less'
import {formateDate} from '../../../utils/dateUtils.js' //【1】时间格式化工具
import memoryUtils from '../../../utils/memoryUtils' //【2】内存中存取用户信息工具
export default class Header extends Component{
state={
curentTime:formateDate(Date.now()), //【3】当前时间格式化后的字符串
dayPictureUrl:'', //天气小图标地址
weather:'', //天气文字
}
// 【4】每过一秒获取一次系统时间
getTime=()=>{
//定时器函数setInterval()
this.intervalId = setInterval(()=>{
let curentTime=formateDate(Date.now()) //获取当前时间并格式化为字符串
this.setState({curentTime}) //更新到state里,实现每秒更新一次时间
},1000)
}
/* 【5】在第一次render()之后执行一次
一般在此执行异步操作: 发ajax请求/启动定时器*/
componentDidMount(){
this.getTime()
}
render(){
//【6】解构state内的数据
const {curentTime,dayPictureUrl,weather} = this.state
//【7】获取memoryUtils中的用户名
const username = memoryUtils.user.username
return(
<div className='header'>
//【8】把变量填入标签内:用户名、当前时间、天气图标、天气
<div className='header-top'>
<span>欢迎,{username}</span>
<a href='javascript:'>退出</a>
</div>
<div className='header-bottom'>
<div className='header-bottom-left'>
<span>首页</span>
</div>
<div className='header-bottom-right'>
<span>{curentTime}</span>
<img src={dayPictureUrl} alt='天气'/>
<span>{weather}</span>
</div>
</div>
</div>
)
}
}
【1】引入接口函数,非默认导
【2】天气小图标地址
【3】天气文字
【4】异步获取天气
【5】渲染之后调用一次天气
【6】解构state内的数据
【7】写入页面
import React,{Component} from 'react'
import './header.less'
import {formateDate} from '../../../utils/dateUtils.js' //时间格式化工具
import memoryUtils from '../../../utils/memoryUtils' //内存中存取用户信息工具 默认导出,不用加花括号
import {reqWeather} from '../../../api/index' //【1】引入接口函数,非默认导出,加花括号
export default class Header extends Component{
state={
curentTime:formateDate(Date.now()), //当前时间格式化后的字符串
dayPictureUrl:'', //【2】天气小图标地址
weather:'', //【3】天气文字
}
//【4】异步获取天气
getWeather = async () => {
//解构天气小图标,天气
const {dayPictureUrl, weather} = await reqWeather('上海')
//更新状态
this.setState({dayPictureUrl, weather})
}
// 每过一秒获取一次系统时间
getTime=()=>{
//定时器函数setInterval()
this.intervalId = setInterval(()=>{
let curentTime=formateDate(Date.now()) //获取当前时间并格式化为字符串
this.setState({curentTime})
},1000)
}
/* 在第一次render()之后执行一次
一般在此执行异步操作: 发ajax请求/启动定时器*/
componentDidMount(){
this.getTime() //调用时间,因为getTime内部写了定时,所以每隔1秒会更新一次时间state,页面就会重新渲染一次
this.getWeather() //【5】渲染之后调用一次天气
}
render(){
//【6】解构state内的数据
const {curentTime,dayPictureUrl,weather} = this.state
//获取用户名
const username = memoryUtils.user.username
return(
<div className='header'>
<div className='header-top'>
<span>欢迎,{username}</span>
<a href='javascript:'>退出</a>
</div>
<div className='header-bottom'>
<div className='header-bottom-left'>
<span>首页</span>
</div>
{/*【7】写入页面*/}
<div className='header-bottom-right'>
<span>{curentTime}</span>
<img src={dayPictureUrl} alt='天气'/>
<span>{weather}</span>
</div>
</div>
</div>
)
}
}
效果:
【1】用于包装当前组件,使其具有路由的3属性history
【1.1】包装起来,使有路由组件的属性
【2】导入导航配置菜单
【3】根据当前网址,在menuListConfig内找到对应的title
【4】得到当前需要显示的title
【5】显示title
import React,{Component} from 'react'
import './header.less'
import {formateDate} from '../../../utils/dateUtils.js' //时间格式化工具
import memoryUtils from '../../../utils/memoryUtils' //内存中存取用户信息工具 默认导出,不用加花括号
import {reqWeather} from '../../../api/index' //引入接口函数,非默认导出,加花括号
//import {message} from 'antd'
import {withRouter} from 'react-router-dom' //【1】用于包装当前组件,使其具有路由的3属性history
import menuList from '../../../config/menuConfig.js' //【2】导入导航配置菜单
class Header extends Component{
state={
curentTime:formateDate(Date.now()), //当前时间格式化后的字符串
dayPictureUrl:'', //天气小图标地址
weather:'', //天气文字
}
// 获取路径
// getPath=()=>{
// }
//【3】根据当前网址,在menuListConfig内找到对应的title
getTitle = () => {
// 得到当前请求路径
const path = this.props.location.pathname
let title
menuList.forEach(item => {
if (item.key===path) { // 如果当前item对象的key与path一样,item的title就是需要显示的title
title = item.title
} else if (item.children) {
// 在所有子item中查找匹配的
const cItem = item.children.find(cItem => path.indexOf(cItem.key)===0)
// 如果有值才说明有匹配的
if(cItem) {
// 取出它的title
title = cItem.title
}
}
})
return title //返回title
}
//异步获取天气
getWeather = async () => {
//解构天气小图标,天气
const {dayPictureUrl, weather} = await reqWeather('上海')
//更新状态
this.setState({dayPictureUrl, weather})
}
// 每过一秒获取一次系统时间
getTime=()=>{
//定时器函数setInterval()
this.intervalId = setInterval(()=>{
let curentTime=formateDate(Date.now()) //获取当前时间并格式化为字符串
this.setState({curentTime})
},1000)
}
/* 在第一次render()之后执行一次
一般在此执行异步操作: 发ajax请求/启动定时器*/
componentDidMount(){
this.getTime()
this.getWeather()
}
render(){
//解构state内的数据
const {curentTime,dayPictureUrl,weather} = this.state
//获取用户名
const username = memoryUtils.user.username
// 【4】得到当前需要显示的title
const title = this.getTitle()
return(
<div className='header'>
<div className='header-top'>
<span>欢迎,{username}</span>
<a href='javascript:'>退出</a>
</div>
<div className='header-bottom'>
<div className='header-bottom-left'>
{/*【5】显示title*/}
<span>{title}</span>
</div>
<div className='header-bottom-right'>
<span>{curentTime}</span>
<img src={dayPictureUrl} alt='天气'/>
<span>{weather}</span>
</div>
</div>
</div>
)
}
}
export default withRouter(Header)//【1.1】包装起来,使当前组件具有路由组件的属性
import {Modal} from 'antd'
//退出登录
loginOut=()=>{
Modal.confirm({
title: '确定要退出登录吗?',
content: '是请点确定,否则点取消',
onOk() {
console.log('OK');
},
onCancel() {
console.log('Cancel');
},
})
}
【1】内存中存取用户信息工具 默认导出,不用加花括号
【2】删除localstorage中的用户登录数据
【3】引入对话框模块
【4】退出登录函数
【5】改成前头函数,因为下面要用到
【6】删除localstorage中登录信息。及内存中登录信息
【7】删除内存中user信息
【8】跳转到登录页面,用替换因为无需退回
【9】调用退出
import React,{Component} from 'react'
import './header.less'
import {formateDate} from '../../../utils/dateUtils.js' //时间格式化工具
import memoryUtils from '../../../utils/memoryUtils' //【1】内存中存取用户信息工具 默认导出,不用加花括号
import storageUtils from '../../../utils/storageUtils' //【2】删除localstorage中的用户登录数据
import {reqWeather} from '../../../api/index' //引入接口函数,非默认导出,加花括号
import {withRouter} from 'react-router-dom' //用于包装当前组件,使其具体路由的3属性history
import menuList from '../../../config/menuConfig.js' //导入导航配置菜单
import {Modal} from 'antd' //【3】引入对话框模块
class Header extends Component{
state={
curentTime:formateDate(Date.now()), //当前时间格式化后的字符串
dayPictureUrl:'', //天气小图标地址
weather:'', //天气文字
}
// 获取路径
// getPath=()=>{
// }
getTitle = () => {
// 得到当前请求路径
const path = this.props.location.pathname
let title
menuList.forEach(item => {
if (item.key===path) { // 如果当前item对象的key与path一样,item的title就是需要显示的title
title = item.title
} else if (item.children) {
// 在所有子item中查找匹配的
const cItem = item.children.find(cItem => path.indexOf(cItem.key)===0)
// 如果有值才说明有匹配的
if(cItem) {
// 取出它的title
title = cItem.title
}
}
})
return title
}
//异步获取天气
getWeather = async () => {
//解构天气小图标,天气
const {dayPictureUrl, weather} = await reqWeather('上海')
//更新状态
this.setState({dayPictureUrl, weather})
}
// 每过一秒获取一次系统时间
getTime=()=>{
//定时器函数setInterval()
this.intervalId = setInterval(()=>{
let curentTime=formateDate(Date.now()) //获取当前时间并格式化为字符串
this.setState({curentTime})
},1000)
}
//【4】退出登录函数
loginOut=()=>{
Modal.confirm({
title: '确定要退出登录吗?',
content: '是请点确定,否则点取消',
onOk:()=> {//【5】改成前头函数,因为下面要用到this.props.history.replace()
console.log('OK');
//【6】删除localstorage中登录信息。及内存中登录信息
storageUtils.removeUser()
memoryUtils.user={}//【7】删除内存中user信息
//【8】跳转到登录页面,用替换因为无需退回
this.props.history.replace('/login')
}//,取消时什么也不做,所以可省略不写
// onCancel() {
// console.log('Cancel');
// },
})
}
//在第一次render()之后执行一次
//一般在此执行异步操作: 发ajax请求启动定时器
componentDidMount(){
this.getTime();
this.getWeather();
}
render(){
//解构state内的数据
const {curentTime,dayPictureUrl,weather} = this.state
//获取用户名
const username = memoryUtils.user.username
// 得到当前需要显示的title
const title = this.getTitle()
return(
<div className='header'>
<div className='header-top'>
<span>欢迎,{username}</span>
{/*【9】*/}
<a href='javascript:' onClick={this.loginOut}>退出</a>
</div>
<div className='header-bottom'>
<div className='header-bottom-left'>
<span>{title}</span>
</div>
<div className='header-bottom-right'>
<span>{curentTime}</span>
<img src={dayPictureUrl} alt='天气'/>
<span>{weather}</span>
</div>
</div>
</div>
)
}
}
export default withRouter(Header)
效果:
此为定时器函数未清除造成的问题
Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.
in Header (created by Context.Consumer)
in withRouter(Header) (at admin.jsx:42)
in section (created by BasicLayout)
in BasicLayout (created by Context.Consumer)
in Adapter (at admin.jsx:41)
in section (created by BasicLayout)
in BasicLayout (created by Context.Consumer)
in Adapter (at admin.jsx:37)
in Admin (created by Context.Consumer)
/*
当前组件卸载之前调用
*/
componentWillUnmount () {
// 清除定时器
clearInterval(this.intervalId)
}
【1】当前组件卸载之前调用清除定时器,避免其造成警告信息
import React,{Component} from 'react'
import './header.less'
import {formateDate} from '../../../utils/dateUtils.js' //时间格式化工具
import memoryUtils from '../../../utils/memoryUtils' //内存中存取用户信息工具 默认导出,不用加花括号
import storageUtils from '../../../utils/storageUtils' //删除localstorage中的用户登录数据
import {reqWeather} from '../../../api/index' //引入接口函数,非默认导出,加花括号
import {withRouter} from 'react-router-dom' //用于包装当前组件,使其具体路由的3属性history
import menuList from '../../../config/menuConfig.js' //导入导航配置菜单
import {Modal} from 'antd'
class Header extends Component{
state={
curentTime:formateDate(Date.now()), //当前时间格式化后的字符串
dayPictureUrl:'', //天气小图标地址
weather:'', //天气文字
}
// 获取路径
// getPath=()=>{
// }
getTitle = () => {
// 得到当前请求路径
const path = this.props.location.pathname
let title
menuList.forEach(item => {
if (item.key===path) { // 如果当前item对象的key与path一样,item的title就是需要显示的title
title = item.title
} else if (item.children) {
// 在所有子item中查找匹配的
const cItem = item.children.find(cItem => path.indexOf(cItem.key)===0)
// 如果有值才说明有匹配的
if(cItem) {
// 取出它的title
title = cItem.title
}
}
})
return title
}
//异步获取天气
getWeather = async () => {
//解构天气小图标,天气
const {dayPictureUrl, weather} = await reqWeather('上海')
//更新状态
this.setState({dayPictureUrl, weather})
}
// 每过一秒获取一次系统时间
getTime=()=>{
//定时器函数setInterval()
this.intervalId = setInterval(()=>{
let curentTime=formateDate(Date.now()) //获取当前时间并格式化为字符串
this.setState({curentTime})
},1000)
}
//退出登录
loginOut=()=>{
Modal.confirm({
title: '确定要退出登录吗?',
content: '是请点确定,否则点取消',
onOk:()=> {//改成前头函数,因为下面要用到this.props.history.replace()
console.log('OK');
//删除localstorage中登录信息。及内存中登录信息
storageUtils.removeUser()
memoryUtils.user={}
//跳转到登录页面,用替换因为无需退回
this.props.history.replace('/login')
}//,取消时什么也不做,所以可省略不写
// onCancel() {
// console.log('Cancel');
// },
})
}
//在第一次render()之后执行一次
//一般在此执行异步操作: 发ajax请求启动定时器
componentDidMount(){
this.getTime();
this.getWeather();
}
/*
【1】当前组件卸载之前调用清除定时器,避免其造成警告信息
*/
componentWillUnmount () {
// 清除定时器
clearInterval(this.intervalId)
}
render(){
//解构state内的数据
const {curentTime,dayPictureUrl,weather} = this.state
//获取用户名
const username = memoryUtils.user.username
// 得到当前需要显示的title
const title = this.getTitle()
return(
<div className='header'>
<div className='header-top'>
<span>欢迎,{username}</span>
<a href='javascript:' onClick={this.loginOut}>退出</a>
</div>
<div className='header-bottom'>
<div className='header-bottom-left'>
<span>{title}</span>
</div>
<div className='header-bottom-right'>
<span>{curentTime}</span>
<img src={dayPictureUrl} alt='天气'/>
<span>{weather}</span>
</div>
</div>
</div>
)
}
}
export default withRouter(Header)
/src/component/link-button/index.jsx
import React,{component} from 'react'
import './index.less'
export default function LinkButton(props){
return <button {...props} className='link-button'></button>
}
index.less
.link-button{
background-color: transparent;
border: none;
outline: none;
color: #1da57a;
cursor: pointer;
}
【1】引入自定按键
【2】使用自定义组件
import React,{Component} from 'react'
import './header.less'
import {formateDate} from '../../../utils/dateUtils.js' //时间格式化工具
import memoryUtils from '../../../utils/memoryUtils' //内存中存取用户信息工具 默认导出,不用加花括号
import storageUtils from '../../../utils/storageUtils' //删除localstorage中的用户登录数据
import {reqWeather} from '../../../api/index' //引入接口函数,非默认导出,加花括号
import {withRouter} from 'react-router-dom' //用于包装当前组件,使其具体路由的3属性history
import menuList from '../../../config/menuConfig.js' //导入导航配置菜单
import {Modal} from 'antd'
import LinkButton from '../../../components/link-button/index'//【1】引入自定按键
class Header extends Component{
state={
curentTime:formateDate(Date.now()), //当前时间格式化后的字符串
dayPictureUrl:'', //天气小图标地址
weather:'', //天气文字
}
// 获取路径
// getPath=()=>{
// }
getTitle = () => {
// 得到当前请求路径
const path = this.props.location.pathname
let title
menuList.forEach(item => {
if (item.key===path) { // 如果当前item对象的key与path一样,item的title就是需要显示的title
title = item.title
} else if (item.children) {
// 在所有子item中查找匹配的
const cItem = item.children.find(cItem => path.indexOf(cItem.key)===0)
// 如果有值才说明有匹配的
if(cItem) {
// 取出它的title
title = cItem.title
}
}
})
return title
}
//异步获取天气
getWeather = async () => {
//解构天气小图标,天气
const {dayPictureUrl, weather} = await reqWeather('上海')
//更新状态
this.setState({dayPictureUrl, weather})
}
// 每过一秒获取一次系统时间
getTime=()=>{
//定时器函数setInterval()
this.intervalId = setInterval(()=>{
let curentTime=formateDate(Date.now()) //获取当前时间并格式化为字符串
this.setState({curentTime})
},1000)
}
//退出登录
loginOut=()=>{
Modal.confirm({
title: '确定要退出登录吗?',
content: '是请点确定,否则点取消',
onOk:()=> {//改成前头函数,因为下面要用到this.props.history.replace()
console.log('OK');
//删除localstorage中登录信息。及内存中登录信息
storageUtils.removeUser()
memoryUtils.user={}
//跳转到登录页面,用替换因为无需退回
this.props.history.replace('/login')
}//,取消时什么也不做,所以可省略不写
// onCancel() {
// console.log('Cancel');
// },
})
}
//在第一次render()之后执行一次
//一般在此执行异步操作: 发ajax请求启动定时器
componentDidMount(){
this.getTime();
this.getWeather();
}
/*
当前组件卸载之前调用清除定时器,避免其造成警告信息
*/
componentWillUnmount () {
// 清除定时器
clearInterval(this.intervalId)
}
render(){
//解构state内的数据
const {curentTime,dayPictureUrl,weather} = this.state
//获取用户名
const username = memoryUtils.user.username
// 得到当前需要显示的title
const title = this.getTitle()
return(
<div className='header'>
<div className='header-top'>
<span>欢迎,{username}</span>
{/*【2】使用自定义组件*/}
<LinkButton href='javascript:' onClick={this.loginOut}>退出</LinkButton>
</div>
<div className='header-bottom'>
<div className='header-bottom-left'>
<span>{title}</span>
</div>
<div className='header-bottom-right'>
<span>{curentTime}</span>
<img src={dayPictureUrl} alt='天气'/>
<span>{weather}</span>
</div>
</div>
</div>
)
}
}
export default withRouter(Header)
效果:
《React后台管理系统实战 :三》header组件:页面排版、天气请求接口及页面调用、时间格式化及使用定时器、退出函数
原文:https://www.cnblogs.com/chenxi188/p/12312203.html