React路由-m

Swiper

  1. 首先安装并引入swiper,同时引入css文档
    • yarn add swiper
  2. 按照文档引入
  3. 动态数据请求
  4. 注:当页面中有多个轮播图时,要起一个id名来避免错误

项目流程简单记录

1. 创建项目,在项目中创建基本的目录如:

  • components
  • layout
  • utils
  • pages/views

2. 安装sass/less(具体查看sass安装)

  • cnpm i node-sass sass-loader -D

3.基本布局

  • 头部、中间、底部
    • 头部和底部为公共性组件–components
    • 中间–pages
    • 以上都在LayOut中引入形成布局
    • layout在App.js中引入

4.移动端自适应问题:参照具体文档(流行rem+弹性盒)

  • 淘宝:常用

    • https://github.com/amfe/lib-flexible
    /* 
      通过js来动态添加rem 
    */
    
    ;(function(designWidth, maxWidth) {
    	var doc = document,
    	win = window,
    	docEl = doc.documentElement,
    	remStyle = document.createElement("style"),
    	tid;
    
    	function refreshRem() {
    		var width = docEl.getBoundingClientRect().width;
    		maxWidth = maxWidth || 540;
    		width>maxWidth && (width=maxWidth);
    		var rem = width * 100 / designWidth;
    		remStyle.innerHTML = 'html{font-size:' + rem + 'px;}';
    	}
    
    	if (docEl.firstElementChild) {
    		docEl.firstElementChild.appendChild(remStyle);
    	} else {
    		var wrap = doc.createElement("div");
    		wrap.appendChild(remStyle);
    		doc.write(wrap.innerHTML);
    		wrap = null;
    	}
    	//要等 wiewport 设置好后才能执行 refreshRem,不然 refreshRem 会执行2次;
    	refreshRem();
    
    	win.addEventListener("resize", function() {
    		clearTimeout(tid); //防止执行两次
    		tid = setTimeout(refreshRem, 300);
    	}, false);
    
    	win.addEventListener("pageshow", function(e) {
    		if (e.persisted) { // 浏览器后退的时候重新计算
    			clearTimeout(tid);
    			tid = setTimeout(refreshRem, 300);
    		}
    	}, false);
    
    	if (doc.readyState === "complete") {
    		doc.body.style.fontSize = "16px";
    	} else {
    		doc.addEventListener("DOMContentLoaded", function(e) {
    			doc.body.style.fontSize = "16px";
    		}, false);
    	}
    })(375, 750); 
    
    // 备注: 这里的375本身就应该写成750 ,但是写成750之后,我们设计稿的尺寸要/50,不好算,我就想,除以100更好算,所以我改成了375
    
  • 网易:面试

    
    function font () {
      document.documentElement.style.fontSize = document.documentElement.clientWidth / 3.75 + 'px'
    }
    
    
    font()
    
    
    window.onresize = font
    
  • 阿里的一个项目

    (function(doc, win) {
      const docEl = doc.documentElement,
        resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
        recalc = function() {
          const clientWidth = docEl.clientWidth;
          if (!clientWidth) return;
          let max = 24;
          let min = 9.3125;
          let size = 20 * (clientWidth / 320);
    
          size = Math.min(size, max);
          size = Math.max(size, min);
          docEl.style.fontSize = size + 'px';
          console.log(docEl.style.fontSize, 'em= =====')
        };
      if (!doc.addEventListener) return;
      win.addEventListener(resizeEvt, recalc, false);
      doc.addEventListener('DOMContentLoaded', recalc, false);
    })(document, window);
    
    

5. sass(复习)

  • 注意: sass文件之间引用使用@import , 在路径上还得加一个~
    @import ‘~/…/…/…/assets/global_style/theme.scss’;

6. 以头部为例,配置自适应,写主题颜色

  • 自适应文档(utils- rem.js)在全局引入,如index.js、App.js等
  • 主题的scss在assets文件夹下的global_style中供整个项目使用

7.头部、底部、中间、高度要设为百分之百,并且引入全局reset.css

示例:
html,body,.App,#root{
  height: 100%;
}
//home页面将布局撑开:sass
.home-box{
    flex: 1;
    overflow: hidden;
}

8.打造底部组件( 局部 )

  • 写好结构

  • 渲染数据

  • 修改样式:

    • 弹性盒

    • 注意a标签应该有激活颜色:写法->&.active{}

    • 移动端布局是尽量不要使用继承,上线是会出错

//index.js
import React,{useState} from 'react'
import './index.scss'

const TabBar = props => {

    const [ tanBars ] = useState([
        {
            id: 1,
            iconName: 'fa-home',//icon类名
            text: '首页',
            path: ''//路由路径
        },
        {
            id: 2,
            iconName: 'fa-reorder',//icon类名
            text: '分类',
            path: ''//路由路径
        },
        {
            id: 3,
            iconName: 'fa-square',//icon类名
            text: '9.9包邮',
            path: ''//路由路径
        },
        {
            id: 4,
            iconName: 'fa-shopping-cart',//icon类名
            text: '购物车',
            path: ''//路由路径
        },
        {
            id: 5,
            iconName: 'fa-user-circle',//icon类名
            text: '我的',
            path: ''//路由路径
        }

    ])

   function renderItem (){
        return tanBars.map( item =>(
                <li key = { item.id }>
                    <a>
                        <i className = {'fa ' + item.iconName}></i>
                        <span> { item.text } </span>
                    </a>
                </li>
        ) )
    }

    return(
        <footer>
            <ul>
                {renderItem()}
            </ul>
        </footer>
    )
}

export default TabBar
index.scss
@import '~../../../../assets/global_style/theme.scss';

footer{
    width: 100%; 
    height: .48rem;
    ul{
        width: 100%;
        height: 100%;
        display: flex;
        justify-content: space-around;
        li{
            a{
                height: 100%;
                display: flex;
                flex-direction: column;
                justify-content: center;
                align-items: center;
                i{
                    font-size: 0.14rem;
                    margin-bottom: 0.04rem;
                }
                span{
                    font-size: 0.14rem
                }

                &.active{
                    i{
                        color: $themeColor;
                    }
                    span{
                        color: $themeColor;
                    }
                }

            }
        }
    }
}

9.图标

  • svg–iconfont中

    • 优点:减少ajax请求
    • 缺点:增大代码的体积
  • Font Awesome

    • 引入cdn

    10.移动端1px是有兼容的

    1px rem是无法转换的
    解决方案:https://www.cnblogs.com/katydids/p/9948546.html

  • sass解决方案

    @mixin border_bottom($color) {
        & {
          position: relative;
          &:before {
            content: "";
            position: absolute;
            top: 0;
            left: 0;
            border-top: 1px solid $color!important;
            transform-origin: 0 0;
            // padding: 1px;
            box-sizing: border-box;
            pointer-events: none;
          }
          &:last-child:before {
            border-top:none;
          }
        }
        @media (-webkit-min-device-pixel-ratio:1),(min-device-pixel-ratio:1) {
          &:before {
            width: 100%;
            height: 100%;
            transform: scale(1);
          }
        }
        @media (-webkit-min-device-pixel-ratio:2),(min-device-pixel-ratio:2) {
          &:before {
            width: 200%;
            height: 200%;
            transform: scale(0.5);
          }
        }
        @media (-webkit-min-device-pixel-ratio:3),(min-device-pixel-ratio:3) {
          &:before {
            width: 300%;
            height: 300%;
            transform: scale(0.333);
          }
        }
    }
    
  • 引入方式:

    `$

    头部引入:

    @import ‘~…/…/…/…/assets/global_style/border.scss’;

    代码中:

    @include border_bottom(#ccc);

    $`

11.头部(局部)

  • 布局+样式

  • 返回的箭头在首页时为无

    • 做法:加开关,记住在Layout中定义状态来控制

       constructor(props){
              super(props)
              this.state = {
                  goback_flag : false,
                  tab_flag: true
              }
          } 
          render() {
              const { tab_flag, goback_flag } = this.state
              return (
                  <div className = "layout">
                    { tab_flag &&  <Tab  goback_flag = { goback_flag }/>} 
                      <Home/>
                      <TabBar/>
                  </div>
              )
          }
      
    • 控制返回箭头(编程式导航)

      • 编程式导航

        使用js来跳转页面

        • push

        • replace

        • 问题: 当我们在tab组件中想要使用路由属性push和replace时,我们发现Tab组件没有,因为它没有被Route使用,所以它不是路由组件

        • 解决: 使用高阶组件withRouter,它可以将一个非路由组件转成伪路由组件,让它具备路由属性

          做法:

          import { withRouter} from 'react-router-dom'
          
          function App(props) {
            return (
              <div className="App">
                <LayOut {...props}/>
              </div>
            );
          }
          
          export default withRouter(App);
          

          layout组件接收后,tab组件就有了replace和push属性,然后写一个点击事件的函数来控制即可

    • // 头部
      
      import React from 'react'
      import './index.scss'
      
      const Tab = props => {
          function goBack(){
              //编程式导航
              //prop.history.replace("/home")
              // props.history.push("/home")
              props.history.go(-1)
          }
          return(
              <header>
                 { props.goback_flag && <i className = "fa fa-chevron-left" onClick = { goBack }></i>}
                  <h3> 首页 </h3>
              </header>
          )
      }
      
      export default Tab
      

12.中间(局部)

具有路由效果

路由:(文档在react-路由中)
  • 安装:$ yarn add react-router-dom

  • 可以在LayOut.js中引入路由组件:`$ import { Route} from ‘react-router-dom $’

  • 也可以在src下新建react.config.js,写路由(一个组件一个路由,渲染),并在全局index.js下路由模式,并在layout.js中引入

  • 加跳转链接,实现路由跳转:引入NavLink

    router.config.js
    
    import React,{useState}from 'react'
    import { Route,Switch,Redirect } from 'react-router-dom'
    import Home from './pages/home'
    import Category from './pages/category/index'
    import Recommend from './pages/recommend/index'
    import ShopCar from './pages/shopcar/index'
    import Mine from './pages/mine/index'
    
    import  List  from './pages/list/index';
    import Detail from './pages/detail/index'
    import Error from './pages/error/index'
    
    //懒加载
    // const Home = () =>{ import './pages/home'}
    
    const RouterComp = props => {
        const [routes] = useState([
            {
                id:1,
                path:'/home',
                component:Home
            },
            {
                id:2,
                path:'/category',
                component:Category
            },
            {
                id:3,
                path:'/recommend',
                component:Recommend
            },
            {
                id:4,
                path:'/shopcar',
                component:ShopCar
            },
            {
                id:5,
                path:'/mine',
                component:Mine
            },
            {
                id:5,
                path:'/mine',
                component:Mine
            },
            {
                id:6,
                path:'/list',
                component:List
            },
            {
                id:7,
                path:'/detail',
                component:Detail
            },
            {
                id:8,
                path:'',
                component:Error
            },
        ])
        
        function renderRoutes () {
            return routes.map( item => <Route key = {item.id} path = {item.path} component = {item.component} exact = {item.exact}></Route>)
        }
        
        
        return (
             /* Switch组件一次只渲染一个Route */
         /* Route是一个路由展示组件,通过component属性来确定渲染哪一个组件 */
         /* Redirect 是重定向组件  from 来源  to 目标     /  /home */
         /* exact 完全匹配 
            /home 
            /home/title
         */
            <Switch>
                <Redirect from = "/" to = "/home" exact/>
               { renderRoutes() }
            </Switch>
        )
    }
    
    export default RouterComp
    
    layout.js
    import React, { Component } from 'react'
    import Tab from '../components/tab';
    import TabBar from '../components/tabbar'
    // import Home from '../pages/home'
    import './index.scss'
    import RouterComp from '../router.config'***
    
    export default class LayOut extends Component {
        constructor(props){
            super(props)
            this.state = {
                goback_flag : false,
                tab_flag: true
            }
        } 
        render() {
            const { tab_flag, goback_flag } = this.state
            return (
                <div className = "layout">
                  { tab_flag &&  <Tab  goback_flag = { goback_flag }/>} 
                  <RouterComp/>***
                    <TabBar/>
                </div>
            )
        }
    }
    
    
    index.js
    /* react-route 5 提供了两种路由模式 HashRouter BrowserRouter
    ! HashRouter #/home hashchange事件 兼容高
    ! BrowserRouter /home h5 popchange事件
    
    */
    import {BrowserRouter as Router} from 'react-router-dom'
    
    ReactDOM.render(
    <Router>
        <App />
    </Router>
    , 
    document.getElementById('root'));
    
二级路由
  • 同一级路由相似

    list页面二级路由示例
    import React,{useState} from 'react'
    import './index.scss'
    import {NavLink,Route} from 'react-router-dom'
    import Picture from './Picture'; 
    import Head_phone from './Head_phone';
    import Text from './Text';
    
    const List = props => {
        const [navs] = useState([
            {
                id: 1,
                text: '壁纸',
                path: '/list/picture'
            },
            {
                id: 2,
                text: '头像',
                path: '/list/head_phone'
            },
            {
                id: 3,
                text: '文字',
                path: '/list/text'
            }
        ])
    
        function renderNavs (){
            return navs.map( item => <NavLink key = {item.id} to = {item.path}>{item.text} </NavLink>)
        }
    
        return(
            <div className = "list-box">
                {/* 导航 */}
                <div className = "list-nav">
                  {renderNavs()}
                </div>
                {/* 长列表 */}
                <Route path = "/list/picture" component = { Picture }/>
                <Route path = "/list/head_phone" component = { Head_phone }/>
                <Route path = "/list/text" component = { Text }/>
            </div>
        )
    }
    
    export default List
    

13.组件库(复习)

  • 引入组件库:yarn add antd-mobile -D

  • 按需引入:yarn add react-app-rewired customize-cra -D

  • 按照官网步骤进行:yarn babel-plugin-import --save-dev

  • 重启项目

  • 一轮播为例:可以使用swiper也可也使用组件库Ant Design

    • 此为组件库示例
    • 选择需要的效果引入
  • 解决滑动错误

    • 在index.css文件中加

      *{
      	touch-action:none;
      }
      

14.home页面的列表滑动(局部)

  • 头部

    • 布局+样式
    • 配置路由 -
  • 中间盒子(此结构必须为中间盒子加长列表)

    • 长列表

      1. 样式:必须将高度撑开,height:100%

      2. 配置反向代理

        • 新建src/setupProxy.js

        • 安装:yarn add http-proxy-middleware —网址:npm.js(根据文档配置)

        • 示例

          const proxy = require( 'http-proxy-middleware' )
          
          module.exports = function ( app ) {
            // app.use( proxy(标识符,options) )
            // http://m.maoyan.com/ajax/movieOnInfoList?token=
            app.use( proxy('/ajax',{
              target: 'http://m.maoyan.com',
              changeOrigin: true
            }))
          
          
            // app.use( proxy() )
          
          }
          
    • 长列表数据请求,并渲染数据

      - useEffect中做数据请求 ---阻止一直进行数据请求:if( movies.length != 0 ) return;
      
      - 利用axios来做数据请求,axios要进行封装(待复习)
      
      - 渲染数据+结构+样式
      
      - 长列表滚动:学习better-scorll网址 [https://ustbhuangyi.github.io/better-scroll/doc/zh-hans/#better-scroll%20%E6%98%AF%E4%BB%80%E4%B9%88](https://ustbhuangyi.github.io/better-scroll/doc/zh-hans/#better-scroll 是什么) 
      
      - 安装:yarn add better-scroll -S
      
      - 引入:import BScroll from 'better-scroll'
      
      - ```js
        //在导航页面应用BScroll
        
        import React,{useEffect} from 'react'
        import MovieList from './MovieList';
        import BScroll from 'better-scroll';
        
        const MovieHot = props =>{
            useEffect(()=>{
                new BScroll(document.querySelector('.movie-hot-box'))
            })
            return(
                <div className = "movie-hot-box">
                    <MovieList/>
                </div>
            )
        }
        
        export default MovieHot
        ```
      
      - 
      
      • movieItem上加跳转事件

        • 想要用js来写必须要用编程式导航

            function goDetail() {
                  props.history.push('/detail')
              }
          
        • 长列表上有一层遮罩层,需要去掉,否则点不到

            useEffect(()=>{
                  new BScroll(document.querySelector('.movie-hot-box'),{click: true}
                   )
                 
              })
          
    1. 配置路径别名

      • config.overrides.js配置文件【npm.js-- customize-cra --api.doc --addWebpackAlias(alias)】

        // webpack配置文件
        const {addWebpackAlias } = require('customize-cra');
         const path = require ('path');
        
          function pathResolve( alias ){
              return path.join(__dirname,alias)
          }
           //路径别名配置
           addWebpackAlias({
               //! 路径别名:对应的绝对路径
               '@':pathResolve('./src'),
               'gstyle':pathResolve('./src/assets/global_style'),
               'comps':pathResolve('./src/components'),
               'layout':pathResolve('./src/layout'),
               'pages':pathResolve('./src/pages'),
               'utils':pathResolve('./src/utils'),
        
           })
         );
        

15.分类-列表-详情(仿照亲亲网)

  • 分类
  1. 首先先配置反向代理,获得分类页面的数据

    • axios的封装(request.js)–必会 —npm.js上有文档学习,也可以使用中文文档( https://www.kancloud.cn/yunye/axios/234845 )/( http://www.axios-js.com/zh-cn/docs/ )

      //request.js
      
      import axios from 'axios'
      
      // axios默认配置
      axios.defaults.baseURL = 'https://api.example.com';//后端接口地址和域名还有端口
      // axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
      axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
      axios.create({
          timeout:1000
      })
      
      const request = ({
          //axios配置
          url,
          method,
          header,
          params,//get参数携带
          data,//post参数携带
          withCredentials = false,
      })  => {
       return new Promise( (resolve,reject) => {
              //  数据请求
          switch ( method ) {
                    case 'POST':
                        const p = new URLSearchParams()
                        for( var key in data){
                            p.append( key,data[key] )
                        }
                        axios({
                            url,
                            method,
                            header,
                            data: p
                        }).then( res => resolve( res ))
                        .catch( err => reject( err ))
                        break;
                
                    default:
                          axios({
                              url,
                              method,
                              heaader,
                              params
                          }).then( res => resolve( res ))
                          .catch( err => reject( err ))
                        break;
                }
      
          // axios拦截
          // 添加请求拦截器
              axios.interceptors.request.use(function (config) {
                  // 在发送请求之前做些什么
                  return config;
              }, function (error) {
                  // 对请求错误做些什么
                  return Promise.reject(error);
              });
      
              // 添加响应拦截器
              axios.interceptors.response.use(function (response) {
                  // 对响应数据做点什么
                  return response;
              }, function (error) {
                  // 对响应错误做点什么
                  return Promise.reject(error);
              });
              })
              }
      
      
      export default request
      
      1. 拦截
      • 作用:拦截用户无登录操作

        ​ 常用效果:loading

    // 添加请求拦截器
    axios.interceptors.request.use(function (config) {
    // 在发送请求之前做些什么
    return config;
    }, function (error) {
    // 对请求错误做些什么
    return Promise.reject(error);
    });

    // 添加响应拦截器
    axios.interceptors.response.use(function (response) {
    // 对响应数据做点什么
    return response;
    }, function (error) {
    // 对响应错误做点什么
    return Promise.reject(error);
    });

    
    3. 数据请求
    
    ```js
    import request from 'utils/request'
     export default class Category extends Component {
             constructor(props) {
              super(props)
        this.state = {
                  categorys:[]
             }
         }
             
    

​ async componentDidMount(){
​ // 先发送数据请求,赋值给组件的状态,在修改数据
​ const result = await request({
​ url:’/index.php’,
​ params:{
​ r:‘class/category’,
​ type:1
​ }
​ })
​ // console.log(‘result’,result)
​ this.setState({
​ categorys:result.data.data.data
​ })

     }
 
     render() {
         return (
             <div className = "category-box">
                 Category
             </div>
         )
     }
 }
 ```
  1. 对分类页面布局,使用组件库的Tabs

  2. 渲染数据

  • 列表

    • 将列表页面的数据请求封装成高阶组件来使用,是多个公用,优化代码:高阶组件
    • 页面的loading要写在拦截器中
  • 详情

    • 加入购物车

      import React,{useState} from 'react'
      import './index.scss'
      import qs from 'querystring'
      import {Button,Stepper} from 'antd-mobile'
      
      const Detail = props => {
        const {id,img,shop_name,price,name,juan_price} = qs.parse( props.location.search.slice(1))
         const [val,setVal] = useState(1)
          //修改val的方法
          function changeVal(val){
              setVal(val)
          }
           /* 加入购物车逻辑 
          ! 真实开发
            点击按钮,将这个商品的信息以参数的形式发送给后端,然后后端存数据库
          ! 模拟整个过程: 本地存储/node 后端
      
        */
      
          function getShopCar(){
              //获取数据
              return localStorage.getItem('shopcar') && JSON.parse(localStorage.getItem('shopcar'))|| []
          }
          function saveShopCar(data){
            return  localStorage.setItem('shopcar',JSON.stringify(data))
          }
      
          function checkShopCar(){
              const data = getShopCar()
              if( data ){//data存在
                  return true
              }else{//data不存在
                  return false
              }
          }
      
          function addShopCar(){
              /* 1. 先判断是不是第一次添加  */
              const t = checkShopCar()
               /* 2. 选择添加 */
               if( t ){
                  //true 说明data存在,判断是不是同一个商品
                  const data = getShopCar()
                    /* 判断这个商品在不在这个数组中 */
                    const flag = data.some(item => item.id == id)
      
                    if(flag){
                        // true 说明,这个商品已经在本地存储中了
                      // 只要给当前这一条加数量即可
                      data.map( item => {
                          if ( item.id == id ) {
                            item.num += 1
                            return 
                          }
                        })
                        saveShopCar(data)
      
                    }else{
                      // false 说明这个商品不再本地存储中,直接添加
                      data.push({
                          id,
                          name,
                          price,
                          img,
                          num:val,
                          juan_price
                      })
                    saveShopCar(data)
                    }
      
               }else{
                  // false 说明这个商品不再本地存储中,直接添加
                  const arr = []
                  arr.push({
                      id,
                      name,
                      price,
                      img,
                      num:val,
                      juan_price
                  })
                  saveShopCar(arr)
               }
      
          }
        
        return(
              <div className = "detail-box">
                  <img src= {img} alt=""/>
                  <h3> {name} </h3>
                  <p> 天猫价:{price}</p>
                  <p> 劵后价:{juan_price}</p>
                  <Stepper
                      style={{ width: '40%', minWidth: '100px' }}
                      showNumber
                      max={10}
                      min={1}
                      value={ val }
                      onChange={ changeVal }
                  />
                  <Button type = 'primary' onClick = {addShopCar}>加入购物车</Button>
              </div>
          )
      }
      
      export default Detail
      
    • 渲染购物车

      1. 购物车为空
      2. 购物车有数据
      3. 获得token值

16.路由传参

路由说明文档 https://reacttraining.com/react-router/web/api/Route

将分类页面的cid传递给列表页面,点击时传递用link 加to 属性

 <Link to = {{
                    pathname: "/list",
                    search: `?cid = ${item.api_cid} `,
                   
                }}
  • 两种写法:

    router.config.js
    
    {
                id:6,
                // path:'/list:id',//list/001?a=1&&b=2
                path:'/list',//list/?a=1&&b=2
                component:List
            },
    

17.路由接参:利用location接参,search的处理

list页面做数据请求,路由接参,渲染数据

用node中的qs模块将请求数据中的cid变成动态的

引入:import qs from 'querystring'

  let   [resource,setResource] = useState([])
   const  getData = async() =>{
       
    if(resource.length != 0)  return false;

    const search = qs.parse(props.location.search.slice(1))

    const result = await request({
        url: '/index.php',
        params:{
            r: 'class/cyajaxsub',
            page: 1,
            cid:search.cid,
            px: 't',
            cac_id: ''
        }
    })
        console.log('result',result)
        setResource(resource = result.data.data.content)
     
    }

   useEffect(() =>{
       getData()
   })

18.动态路由

19.路由监听

实现头部底部控制

  • layout

    import React, { Component } from 'react'
    import Tab from '../components/tab';
    import TabBar from '../components/tabbar'
    // import Home from '../pages/home'
    import './index.scss'
    import RouterComp from '../router.config'
    
    export default class LayOut extends Component {
        constructor(props){
            super(props)
            this.state = {
                goback_flag : false,
                tab_flag: true,
                needGoBack: ['/category','/recommend','/shopcar','/mine'],
                needTabBar: ['/home','/category','/recommend','/shopcar','/home/movie_hot'] 
            }
        } 
        componentDidMount () {
            this.checkGoBack() 
            this.checkTabBar()
          }
    
          componentWillReceiveProps ( nextProps ) {
            /* this.props.location.pathname 是上一个的路由路径 */
            this.checkGoBack(nextProps) 
            this.checkTabBar(nextProps)
          }
        
          checkGoBack = (nextProps) => {
            const { pathname } =nextProps && nextProps.location || this.props.location 
    
            const f = this.state.needGoBack.some( item => item ==pathname )
            if ( f ) {
              //true 要加
              this.setState({
                goback_flag: true
              })
            } else {
              // false 不加
              this.setState({
                goback_flag: false
              })
            }
          }
          
          checkTabBar = (nextProps) => {
            const { pathname } =nextProps && nextProps.location || this.props.location 
            const f = this.state.needTabBar.some( item => item == pathname ) 
            if ( f ) {
              //true 要加
              this.setState({
                tab_flag: true
              })
            } else {
              // false 不加
              this.setState({
                tab_flag: false
              })
            }
          }
    
    
    
    
        render() {
            const { tab_flag, goback_flag } = this.state
            return (
                <div className = "layout">
                  {  <Tab {...this.props} goback_flag = { goback_flag }/>} 
                  <RouterComp/>
                    {tab_flag && <TabBar/>}
                </div>
            )
        }
    }
    
    
  • tab

    // 头部
    
    import React from 'react'
    import './index.scss'
    
    const Tab = props => {
        function goBack(){
            //prop.history.replace("/home")
            // props.history.push("/home")
            props.history.go(-1)
        }
        var obj  = {
            '/home/movie_hot': '首页',
            '/category': '分类',
            '/recommend': '9.9包邮',
            '/shopcar': '购物车',
            '/mine': '我的'
        }
    
        const {pathname} = props.location
    
    
        return(
            <header>
               { props.goback_flag && <i className = "fa fa-chevron-left" onClick = { goBack }></i>}
                <h3> {obj[ pathname ]} </h3>
            </header>
        )
    }
    
    export default Tab
    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
React Router是React的一种路由管理工具,它允许我们在应用程序中建立路由,并通过不同的URL路径来加载不同的页面。 而react-router-config是React Router的一个附加库,它提供了一种以配置方式来定义应用程序路由的方法。 路由切入动画是指在切换页面时,为页面添加一些过渡效果和动画,以提升用户体验。 使用react-router-config实现路由切入动画的步骤如下: 1. 首先,在路由配置文件中定义各个页面的路由信息,并设置对应的组件。 2. 在路由配置文件中,为每个路由定义一个transition属性,用于标识该路由的过渡效果。 3. 在根组件中使用React Router提供的Switch组件来包裹所有路由,并使用TransitionGroup组件来包裹Switch组件。 4. 在根组件中使用自定义的AnimatedSwitch组件来替换React Router提供的Switch组件,并将路由配置文件传递给AnimatedSwitch组件。 5. 在AnimatedSwitch组件中根据当前路由的transition属性,为切换的页面添加不同的过渡效果和动画。 例如,可以定义一个FadeIn动画效果,在路由配置文件中为需要应用该动画效果的路由设置transition属性为'fade-in',然后在AnimatedSwitch组件中根据该属性为页面添加相应的CSS动画样式。 总而言之,使用react-router-config可以方便地配置应用程序的路由信息,并结合一些CSS动画库,可以实现各种炫酷的路由切入动画。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值