前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >react全家桶之router使用

react全家桶之router使用

作者头像
一粒小麦
发布2019-07-18 17:37:49
1.1K0
发布2019-07-18 17:37:49
举报
文章被收录于专栏:一Li小麦一Li小麦

今天看直播课,心里感叹一个主打前端技能教学的网站,用的居然还是flash播放器和angular1.x。实在说不过去。

然而这样确实有他的道理。假使上课的有1000人,那应该通宵开发出来。而在没有那么多人的情况下,也许还能在用几年。

事实上真正的技术驱动公司还是少之又少,即便有这样的岗位,也是为大牛准备的。而前端缺乏改进产品的核心竞争力,在工作中出于一个更加弱势的地位。

当这个职业的红利期结束,行业开始回归沉淀,其实你会发现,所谓的大前端思维,其实是非常局限的。

react-router使用(v4)

最新版本已经是5.0了。不过本文用例均可跑通。

安装:

npm install --save react-router-dom
 npm install --save react-router
设定路由器

先引入最常用的三个依赖 BrowserRouter,Link,Route,然后用 <BrowserRouter>把页面包裹起来。这样页面就能拥有 router的一系列属性。

再加个Link导航

import {BrowserRouter,Link,Route} from 'react-router-dom'
<BrowserRouter>
  {/*导航*/}
    <nav>
        <Link to="/">水果列表</Link>| <Link to="/add">添加水果</Link>
  </nav> 
  content...
</BrowserRouter>
拆分组件结构

exact表示独占页面的路由。

function HooksTest({fruits,addFruit,asyncFetch}) {
    const [fruit, setFruit] = useState("草莓");
    // 全局属性
    useEffect(() => {
        asyncFetch(["草莓", "香蕉"] )
    }, []);
    return (
        <BrowserRouter>
            <nav>
            <Link to="/">水果列表</Link>| <Link to="/add">添加水果</Link>
            </nav>

            <div>
                {/* <p>{fruit === "" ? "请选择喜爱的水果:" : `您的选择是:${fruit}`}</p> */}
                <Route path="/add" component={AddFruit}/>
                <Route exact path="/" render={()=>{
                    return (fruits.length==0?<div>loading...</div>:<FruitList setFruit={setFruit} fruits={fruits}></FruitList>)
                }}/>
            </div>            
        </BrowserRouter>    
    );
}
传参

现在需要加一个详情页面,势必用到传参。

首先在页面定义一个路由组件,使用 /detail/:fruit跳转:

<Route path="/detail/:fruit" component={FruiteDetail}/>

然后开始写 FruiteDetail组件,

通过传参,可以用 match.params.fruit(占位符,fruit)拿到水果字段。

function FruiteDetail({match,history,location}){
    console.log(match,history,location)
    return (
        <div>
            {match.params.fruit}详情
        </div>
    )
}

解构出来的参数是什么信息呢?可以看一下:

有了 history这个api,可以像react原生api一样,做返回操作:

function FruiteDetail({match,history,location}){
    console.log(match,history,location)
    return (
        <div>
            {match.params.fruit}详情
            <div>
                <button onClick={()=>{history.goBack()}}>返回</button>
            </div>
        </div>
    )
}

location则可以获取当前的地址。

嵌套

Route组件嵌套在其他页面组件中就产生了嵌套关系 。

假设存在这样的需求,我点击详情,不出现详情页面,而是直接在FruitList中展示。

于是改写FruitList

// 水果列表
function FruitList({ fruits, setFruit }) {
    let result = fruits.map(f => 
    <li  onClick={() => { setFruit(f) }} key={f}>
    <Link to={`/list/detail/${f}`}>{f}</Link>
    </li>)
    return <div>
        <ul>
            {result}
        </ul>
        <Route path="/list/detail/:fruit" component={FruiteDetail}/>
    </div>;
}

去掉exact。

<Route  path="/list" render={()=>{
                    return (fruits.length==0?<div>loading...</div>:<FruitList setFruit={setFruit} fruits={fruits}></FruitList>)
                }}/>
404

route不加path即可匹配全部页面。

<Route component={() => <h3>页面不存在</h3>}></Route>

但是匹配的所有。需要引入switch。

{/* 添加Switch表示仅匹配一个 */}
<Switch>
                <Route  path="/list" render={()=>{
                    return (fruits.length==0?<div>loading...</div>:<FruitList setFruit={setFruit} fruits={fruits}></FruitList>)
                }}/>
                    <Route component={() => <h3>页面不存在</h3>}></Route> 
                </Switch>
路由守卫

我想让add页面变为私有页面,怎么做?

react-router已有的特性可实现类似vue中路由守卫的功能

你可以创建高阶组件包装route使其具有权限判断。

事实上几乎所有守卫的高阶函数都可以这么用:

// 创建高阶组件,使其可以验证登录态。
function privateRoute(props){
    // console.log(props)
    const { component: Component, isLogin, ...rest }=props;
    const redirect=props.path;
    return (
        <Route  
        {...rest}
        render={props=>
        (isLogin)?<Component  {...props}/>:<Redirect to={{
            pathname:'/login',
            state: { referrer: redirect }           
        }}/>}
        ></Route>
    )
}

接下来完成登录逻辑:点击直接登录:

//登录,需要拿到isLogin和login操作
function getLogin(props){
    const {location,isLogin,login}=props;
    // 获取重定向地址
    const redirect=location.state.referrer||'/';
    if(isLogin){
        return <Redirect to={{pathname:location.state.referrer}} />
    }
    return (
        <div>
            <div>
            <input type="text" placeholder="username"/>
            </div>
            <div>
                <input type="password" placeholder="password"/>
            </div>
            <div>
                <button onClick={login}>login</button>
            </div>
        </div>
    )
}

isLogin应该跟redux拿。新建一个userReducer.js

// uerReducer.js
export const login= (payload) => {
    return dispatch => {
        setTimeout(() => {
            dispatch({ type: 'login', payload});
        }, 1000);
    };
};

export default function(state = {
    isLogin: false
}, action) {
    switch (action.type) {
        case "login": // 登录
            return {isLogin:true}
        case "logout":
            return {isLogin:false}
        default:
            return state;
    }
}

//Hook.js
import {login} from "../store/userReducer"
// isLogin中,两个组件都需要
const Login=connect(mapStateToProps,mapDispatchToProps)(getLogin)
const PrivateRoute= connect(mapStateToProps,mapDispatchToProps)(privateRoute)

那么add现在就不能直接用原生的路由了。而应该用包装过的路由:

<PrivateRoute path="/add" component={AddFruit}/>

功能实现。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-06-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 一Li小麦 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 今天看直播课,心里感叹一个主打前端技能教学的网站,用的居然还是flash播放器和angular1.x。实在说不过去。
  • react-router使用(v4)
    • 设定路由器
      • 拆分组件结构
        • 传参
          • 嵌套
            • 404
              • 路由守卫
              相关产品与服务
              云直播
              云直播(Cloud Streaming Services,CSS)为您提供极速、稳定、专业的云端直播处理服务,根据业务的不同直播场景需求,云直播提供了标准直播、快直播、云导播台三种服务,分别针对大规模实时观看、超低延时直播、便捷云端导播的场景,配合腾讯云视立方·直播 SDK,为您提供一站式的音视频直播解决方案。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档