Skip to content

Commit

Permalink
页面刷新面包屑错误修复
Browse files Browse the repository at this point in the history
  • Loading branch information
dL-hx committed Mar 8, 2019
1 parent a044c59 commit 3ba237f
Showing 1 changed file with 147 additions and 90 deletions.
237 changes: 147 additions & 90 deletions src/components/Header/index.js
Original file line number Diff line number Diff line change
@@ -1,109 +1,166 @@
// src/components/Header/index.js
import React from 'react';
import React from "react";
/*
Header组件 分两部分建立两行Row
第一行是用户的个人信息(这里以后要通过变量传输进来)
* */
import {Row, Col} from "antd";
import './index.less'
import Util from '../../utils/utils'//导入公共机制
import axios from "../../axios";//引入axios组件
import {connect} from 'react-redux' //连接器
import {Row, Col, Modal} from "antd";
import "./index.less";
import Util from "../../utils/utils"; //导入公共机制
import axios from "../../axios"; //引入axios组件
import {connect} from "react-redux";
import {switchMenu} from "../../redux/action"; //连接器
import {Menu} from "antd/lib/menu";
import MenuConfig from "./../../config/menuConfig"; //导入menuConfig这个文件


class Header extends React.Component {
//声明 state变量 在setState之前要声明变量
state = {};
//声明 state变量 在setState之前要声明变量
state = {};

componentWillMount() {
this.setState({
userName: '太阳王子',
});
/*
componentWillMount() {
this.setState({
userName: "太阳王子",
});
/*
创建定时器,每隔一秒获取时间
* 获取时间的方法
*/
setInterval(() => {
// new Date();
let sysTime = Util.formateDate(new Date().getTime());
this.setState({
sysTime
})
}, 1000);
this.getWeatherAPIData();//在这里调用下天气
}
setInterval(() => {
// new Date();
let sysTime = Util.formateDate(new Date().getTime());
this.setState({
sysTime
});
}, 1000);
this.getWeatherAPIData(); //在这里调用下天气
}

// 处理页面刷新的修改面包屑的代码
handleMenUpdate = (data) => {
let currentKey = window.location.hash.replace(/#|\?.*$/g, "");
const {dispatch} = this.props;

let obj = []; //创建数组,将需要的数据放入其中,代码无形中使用了工厂模式👍,将需要值进行了处理
data.map(item => {
if (item.children) {// 如果有children属性,将其展开放入数组中
obj.push(...item.children);
} else{
obj.push(item);
}
});
const menuName = obj;
menuName.forEach((item)=>{
if(currentKey==item.key){
dispatch(switchMenu(item.title))
}
})
};

/*定义得到API天气的方法*/
getWeatherAPIData() {
//通过jsonp的方式 调用百度Api接口
//1.安装jsonp插件 yarn add jsonp --save
//2.对jsonp插件进行的封装 新建文件夹axios-----index.js
//3.通过axios插件来发送jsonp()方法
//通过字符串的方式发送url
//地区动态储存,定义变量 city // url:'http://api.map.baidu.com/telematics/v3/weather?location='+this.city+'&output=json&ak=3p49MVra6urFRGOT9s8UBWr2'
//对中文进行编码,转为页面字符
// 编码后通过 .then 进行接收
/* 判断页面是否刷新,定义生命周期方法 ,如果页面刷新,重新给menuName值*/
componentDidMount() {
this.handleMenUpdate(MenuConfig);
}

let city = '咸阳';
/*定义得到API天气的方法*/
getWeatherAPIData() {
//通过jsonp的方式 调用百度Api接口
//1.安装jsonp插件 yarn add jsonp --save
//2.对jsonp插件进行的封装 新建文件夹axios-----index.js
//3.通过axios插件来发送jsonp()方法
//通过字符串的方式发送url
//地区动态储存,定义变量 city // url:'http://api.map.baidu.com/telematics/v3/weather?location='+this.city+'&output=json&ak=3p49MVra6urFRGOT9s8UBWr2'
//对中文进行编码,转为页面字符
// 编码后通过 .then 进行接收

axios.jsonp({
// url:'http://api.map.baidu.com/telematics/v3/weather?location='+this.city+'&output=json&ak=3p49MVra6urFRGOT9s8UBWr2'
url: 'http://api.map.baidu.com/telematics/v3/weather?location=' + encodeURIComponent(city) + '&output=json&ak=3p49MVra6urFRGOT9s8UBWr2'
}).then((res) => {//通过这里拿到返回值,可以先看下返回值是什么
let city = "咸阳";

if (res.status == 'success') {//状态成功取得数据进行使用
let data = res.results[0].weather_data[0];
this.setState({//将状态设置进去
date:data.date,
dayPictureUrl: data.dayPictureUrl,
weather: data.weather
})
}
})
}
axios
.jsonp({
// url:'http://api.map.baidu.com/telematics/v3/weather?location='+this.city+'&output=json&ak=3p49MVra6urFRGOT9s8UBWr2'
url:
"http://api.map.baidu.com/telematics/v3/weather?location=" +
encodeURIComponent(city) +
"&output=json&ak=3p49MVra6urFRGOT9s8UBWr2"
})
.then(res => {
//通过这里拿到返回值,可以先看下返回值是什么

render() {
// 取出menuType 用作二级导航(父组件Common.js传来)
const menuType = this.props.menuType;
return (
<div className="header">
<Row className="header-top">
{
menuType?
<Col span="6" className="logo">
<img src="/assets/logo-ant.svg" alt=""/>
<span>IMooc 通用管理系统</span>
</Col>:''
}
<Col span={menuType?18:24}>
<span>欢迎,{this.state.userName}</span>
<a href="#">退出</a>
</Col>
</Row>
{
menuType?'':<Row className="breadcrumb">
<Col span="4" className="breadcrumb-title">
{/* 首页 */}
{this.props.menuName}
</Col>
<Col span="20" className="weather">
<span className="date">{this.state.sysTime}</span>
<span className="weather-img">
<img src={this.state.dayPictureUrl} alt=""/>
</span>
<span className="weather-detail">
{this.state.weather}
{/*{this.state.date}*/}
</span>
</Col>
</Row>
}
</div>
);
}
if (res.status == "success") {
//状态成功取得数据进行使用
let data = res.results[0].weather_data[0];
this.setState({
//将状态设置进去
date: data.date,
dayPictureUrl: data.dayPictureUrl,
weather: data.weather
});
}
});
}

showExitConfirm = () => {
Modal.confirm({
title: "是否确定退出系统?",
onOk() {
window.location.href = "/#/login";
},
onCancel() {
console.log("Cancel");
}
});
};

render() {
// 取出menuType 用作二级导航(父组件Common.js传来)
const menuType = this.props.menuType;
return (
<div className="header">
<Row className="header-top">
{menuType ? (
<Col span="6" className="logo">
<img src="/assets/logo-ant.svg" alt=""/>
<span>IMooc 通用管理系统</span>
</Col>
) : (
""
)}
<Col span={menuType ? 18 : 24}>
<span>欢迎, {this.props.userName || this.state.userName} </span>
<a onClick={this.showExitConfirm}>退出</a>
</Col>
</Row>
{menuType ? (
""
) : (
<Row className="breadcrumb">
<Col span="4" className="breadcrumb-title">
{/* 首页 */}
{this.props.menuName}
</Col>
<Col span="20" className="weather">
<span className="date">{this.state.sysTime}</span>
<span className="weather-img">
<img src={this.state.dayPictureUrl} alt=""/>
</span>
<span className="weather-detail">
{this.state.weather}
{/*{this.state.date}*/}
</span>
</Col>
</Row>
)}
</div>
);
}
}

//将state.menuName 绑定到 props 的menuName
const mapStateToProps = state => {
return {
menuName: state.menuName
}
console.log(state);
return {
menuName: state.menuName,
userName: state.userName
};
};
export default connect(mapStateToProps)(Header) 
export default connect(mapStateToProps)(Header);

1 comment on commit 3ba237f

@dL-hx
Copy link
Owner Author

@dL-hx dL-hx commented on 3ba237f Mar 8, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

15.3 页面刷新面包屑

这里主要讲解课程完成后,我对项目错误的一些修正

[TOC]

Github地址

在之前的代码中, 我们刷新页面后,面包屑会恢复为"首页",如下图:

在演示项目中: http://imoocms.51purse.com/是没有这个问题的,

那么如何解决这样的问题呢?

一 问题分析

  1. react 页面刷新后,所保存的state值就会情况

  2. 从解决页面刷新,MenuSelectedKey 不变的经验来看, 在后续刷新时,在componentWillMonut中,使用路由去解决, 如下图

分析得出:

工具一: currentKey

工具二:this. dispatch(switchMenu("将数据传入这里即可改变面包屑"));

二 思路分享

  1. 判断页面是否刷新,定义生命周期方法 ,如果页面刷新,重新给menuName值

    利用:componentDidMount()判断

  2. 创建一个函数A,用来处理这件事情

  3. 导入menuConfig这个文件,从这里找出需要的title,与key ,使其与currentKey匹配

    具体是通过if /switch 来判断条件即可

  4. 在componentDidMount()生命周期方法中,调用该函数A

三 尝试代码

修改menuConfig.js源文件(减号表示去掉),后来证明不去掉也可以(这里我是去除了,为了避免一些未知的错误)

// src/config/menuConfig.js
const menuList = [
    {
        title: '首页',
        key: '/home'
    },
    {
        title: 'UI',
        key: '/ui',
        children: [
            {
                title: '按钮',
                key: '/ui/buttons',
            },
            {
                title: '弹框',
                key: '/ui/modals',
            },
            {
                title: 'Loading',
                key: '/ui/loadings',
            },
            {
                title: '通知提醒',
                key: '/ui/notification',
            },
            {
                title: '全局Message',
                key: '/ui/messages',
            },
            {
                title: 'Tab页签',
                key: '/ui/tabs',
            },
            {
                title: '图片画廊',
                key: '/ui/gallery',
            },
            {
                title: '轮播图',
                key: '/ui/carousel',
            }
        ]
    },
    {
        title: '表单',
        key: '/form',
        children: [
            {
                title: '登录',
                key: '/form/login',
            },
            {
                title: '注册',
                key: '/form/reg',
            }
        ]
    },
    {
        title: '表格',
        key: '/table',
        children: [
            {
                title: '基础表格',
                key: '/table/basic',
            },
            {
                title: '高级表格',
                key: '/table/high',
            }
        ]
    },
    {
        title: '富文本',
        key: '/rich'
    },
    {
        title: '城市管理',
        key: '/city'
    },
    {
        title: '订单管理',
        key: '/order',
-        btnList: [
-            {
-               title: '订单详情',
-                key: 'detail'
-            },
-            {
-                title: '结束订单',
-                key: 'finish'
-            }
-        ]
    },
    {
        title: '员工管理',
        key: '/user'
    },
    {
        title: '车辆地图',
        key: '/bikeMap'
    },
    {
        title: '图标',
        key: '/charts',
        children: [
            {
                title: '柱形图',
                key: '/charts/bar'
            },
            {
                title: '饼图',
                key: '/charts/pie'
            },
            {
                title: '折线图',
                key: '/charts/line'
            },
        ]
    },
    {
        title: '权限设置',
        key: '/permission'
    },
];
export default menuList;

拷贝menuConfig文件,打开另一个编辑器

因为我们遍历的是数组

数组: map方法,类似递归(ES6常用方法)

判断: if语句

👍下面的代码无形中使用了工厂模式,将需要值进行了处理

修改后menuConfig.js如下

const menuList = [
  {
    title: "首页",
    key: "/home"
  },
  {
    title: "UI",
    key: "/ui",
    children: [
      {
        title: "按钮",
        key: "/ui/buttons"
      },
      {
        title: "弹框",
        key: "/ui/modals"
      },
      {
        title: "Loading",
        key: "/ui/loadings"
      },
      {
        title: "通知提醒",
        key: "/ui/notification"
      },
      {
        title: "全局Message",
        key: "/ui/messages"
      },
      {
        title: "Tab页签",
        key: "/ui/tabs"
      },
      {
        title: "图片画廊",
        key: "/ui/gallery"
      },
      {
        title: "轮播图",
        key: "/ui/carousel"
      }
    ]
  },
  {
    title: "表单",
    key: "/form",
    children: [
      {
        title: "登录",
        key: "/form/login"
      },
      {
        title: "注册",
        key: "/form/reg"
      }
    ]
  },
  {
    title: "表格",
    key: "/table",
    children: [
      {
        title: "基础表格",
        key: "/table/basic"
      },
      {
        title: "高级表格",
        key: "/table/high"
      }
    ]
  },
  {
    title: "富文本",
    key: "/rich"
  },
  {
    title: "城市管理",
    key: "/city"
  },
  {
    title: "订单管理",
    key: "/order",
  },
  {
    title: "员工管理",
    key: "/user"
  },
  {
    title: "车辆地图",
    key: "/bikeMap"
  },
  {
    title: "图标",
    key: "/charts",
    children: [
      {
        title: "柱形图",
        key: "/charts/bar"
      },
      {
        title: "饼图",
        key: "/charts/pie"
      },
      {
        title: "折线图",
        key: "/charts/line"
      }
    ]
  },
  {
    title: "权限设置",
    key: "/permission"
  }
];
var copy = function(a, b) {
  return Object.assign(a, b);
};
function f1(data) {
  var obj = [];// 创建数组,将需要的数据放入其中,代码无形中使用了工厂模式👍,将需要值进行了处理
  data.map(item => {
    if (item.children) {// 如果有children属性,将其展开放入数组中
      obj.push(...item.children);
    } else{
      obj.push(item);// 没有children属性,直接放入数组中
    }
  });
  return obj
}
console.log(f1(menuList))

得到结果如下:

四 实例代码

得到处理好的数据后,我们就开始我们的实例代码

在 [src/components/Header/index.js]中:

  1. import MenuConfig from "./../../config/menuConfig"; //导入menuConfig这个文件
  2. 用来处理页面刷新后,面包屑刷新错误的的代码(类似于if else/switch case) 这里使用了forEach对其简化(也可使用for)

    // 处理页面刷新的修改面包屑的代码
    handleMenUpdate = (data) => {
      let currentKey = window.location.hash.replace(/#|\?.*$/g, "");
      const {dispatch} = this.props;
    
      let obj = [];
      data.map(item => {
        if (item.children) {// 如果有children属性,将其展开放入数组中
          obj.push(...item.children);
        } else{
          obj.push(item);
        }
      });
      const menuName = obj
      menuName.forEach((item)=>{
        if(currentKey==item.key){
          dispatch(switchMenu(item.title))
        }
      })
    };
  3. 生命周期中调用该方法

  /* 判断页面是否刷新,定义生命周期方法 ,如果页面刷新,重新给menuName值*/
  componentDidMount() {
    this.handleMenUpdate(MenuConfig);
  }
  1. 完整实例

    // src/components/Header/index.js
    ...
    import MenuConfig from "./../../config/menuConfig"; //导入menuConfig这个文件
    
    
    class Header extends React.Component {
      //声明 state变量 在setState之前要声明变量
      state = {};
    
      componentWillMount() {
    	...
      }
    
      // 处理页面刷新的修改面包屑的代码
      handleMenUpdate = (data) => {
        let currentKey = window.location.hash.replace(/#|\?.*$/g, "");
        const {dispatch} = this.props;
    
        let obj = [];
        data.map(item => {
          if (item.children) {
            obj.push(...item.children);
          } else{
            obj.push(item);
          }
        });
        const menuName = obj
        menuName.forEach((item)=>{
          if(currentKey==item.key){
            dispatch(switchMenu(item.title))
          }
        })
      };
    
      /* 判断页面是否刷新,定义生命周期方法 ,如果页面刷新,重新给menuName值*/
      componentDidMount() {
        this.handleMenUpdate(MenuConfig);
      }
    
      /*定义得到API天气的方法*/
      getWeatherAPIData() {
        ...
      }
    
      showExitConfirm = () => {
       ...
      };
    
      render() {
       ...
      }
    }
    
    //将state.menuName 绑定到 props 的menuName
    const mapStateToProps = state => {
      console.log(state);
      return {
        menuName: state.menuName,
        userName: state.userName
      };
    };
    export default connect(mapStateToProps)(Header);

    完成后,可见,刷新页面,面包屑不在改变

Please sign in to comment.