React 路由以及状态管理的用法

10 篇文章 1 订阅
4 篇文章 0 订阅

React 路由

安装react-router-dom

 npm install react-router-dom@5.3.0 -S
  • v5文档:React Router: Declarative Routing for React.js

  • React路由的编程特点:组件化、hooks api、withRouter

  • 安装react-router-dom(v5.3.0),会使用HashRouter、Route、Switch、Redirect、Link。

  • 使用@loadable/component(React.lazy、Suspense)实现“代码分割”。

  • 安装antd-mobile,把tabbar组件搞进来。

  • 在react-router-dom路由系统中,不是每个React组件都能访问到路由api。只有那些被Route直接包裹过的React页面组件可以通过props访问到路由api。

  • 那些未被Route直接包裹的React组件默认无法访问路由api,怎么办呢?

    • 可以通过属性继承{...props}语法,把页面组件的props(路由API)手动向后代组件传递。

    • 使用withRouter这个高阶组件,向组件中注入路由API。(非Hooks编程中用得比较多)

    • 使用react-router-dom(v5)提供的hooks api直接使用路由API。

    • 修改react-router-dom出口,把路由上下文对象抛出来,useContext()直接使用这些路由API。

  • 路由传参:params动态路由传参,query传参。

  • 嵌套视图:Route所包裹的组件中又使用了Route。

    • 在嵌套视图时,一定要用Switch把二级Route路由包裹起来。

    • 在编写Route规则,不要“一刀切地加exact”,注意exact对 / 的影响。

function App() {
  return (
    <Switch>
      <Route path='/list' component={List} />
    </Switch>
  )
}
function List() {
  return (
    <Switch>
      <Route path='/list/video' component={ListVideo} />
    </Switch>
  )
}

 在v6中如何解决“嵌套视图”的问题(v6中用element渲染组件)

<Routes>
  <Route path='/' element={<Home />}></Route>
  <Route path='/find' element={<Find />}>
    <Route path='video' element={<Video />}></Route>
    <Route path='image' element={<Image />}></Route>      
  </Route>
</Routes>
​
function Find() {
  return (
    <div>something</div>
    <Outlet />
  )
}

路由懒加载

可以使用React.lazy 和 React Router 这类的第三方库,来配置基于路由的代码分割,实现按需加载。

import React, { Suspense, lazy } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
​
const Home = lazy(() => import('./routes/Home'));
const About = lazy(() => import('./routes/About'));
​
const App = () => (
  <Router>
    <Suspense fallback={<div>Loading...</div>}>
      <Switch>
          //exact 为精准匹配路由,适用于网站的首页。
        <Route exact path="/" component={Home}/>
        <Route path="/about" component={About}/>
      </Switch>
    </Suspense>
  </Router>
);

但由于React.lazy 和 Suspense 技术还不支持服务端渲染,所以React给我们推荐了 @loadable/component 代码示例:

import loadable from '@loadable/component'
const OtherComponent = loadable(() => import('./OtherComponent'))
function MyComponent() {
  return (
    <div>
      <OtherComponent />
    </div>
  )
}

注意:使用上面的库我们需要在babel文件中引入这两个插件(plugins)

{
  "presets": ["@babel/preset-react"],
  "plugins": ["@babel/plugin-syntax-dynamic-import"]
}

携带参数跳转页面

import React from 'react';
import {Route,Redirect,Switch,BrowserRouter,useHistory} from 'react-router-dom';

import T from './views/T' //导入要跳转的React页面

const B=()=>{
  const hist = useHistory()
  return (
    <div onClick={()=>{
      hist.push(`/res/1fejwdhla`)
    }}>
      页面跳转
    </div>
  )
}

function App() {
  return (
    <>
    <BrowserRouter>
      <Switch >
        <Route exact path='/'>
          {/* 当路径为/时显示 */}
            <B/>
        </Route>
        <Route path='/res/:id' component={T}>
          {/* 使用 :id  可以将路由后面的参数以id的参数值传递到res路由的页面 */}
        </Route>
        <Redirect to="/">
            {/* 当之前的路由都不满足时,重定向为根页面 */}
        </Redirect>
      </Switch>
    </BrowserRouter>
    </>
  );
}
export default App;
import React from 'react';

export default (props => {
    console.log(props)
    return (
        <React.Fragment>
            <h1>这是T页面</h1>
        </React.Fragment>
    )
})

 我们可以通过props可以查看到上一个页面传过来的携带过来路由信息。

状态管理

mobx

安装mobx

monbx(V6) + mobx-react(v7) 

  • 安装mobx(v6),用面向对象语法编写store和子store的代码逻辑。
  • 安装mobx-react(v7),在APP根组件中,使用<Provider {...store}>
  • 在React组件中,使用inject('user')(observer(props=>(<div></div>)))

  安装:

npm i mobx mobx-react -S

modx的使用

根store的入口文件  

//创建一个store文件
import UserStore from "./user";

class Store {
    constructor(){
        this.user= new UserStore()
        this.dd=789456
    }
    dd=456
}

export default new Store()

子store 文件

import {
  makeAutoObservable,
  observable,
  action,
  flow
} from 'mobx'

import { fetchArticleList } from '../api'

export default class UserStore {
  constructor() {
    //makeAutoObservable自动转换该类中的属性和方法
    // makeAutoObservable(target, annotations?, options?)
    // target:指定要转化的目标实例对象 一般都指向当前Clas
    // annotations: 注解对象
    // key:指定要转化的属性或方法
    // value:annotation(注解,从 mobx 引入的方法),指定要转换成什么
    // 所有 自有 属性都成为 observable。
    // 所有 getters 都成为 computed。
    // 所有 setters 都成为 action。
    // 所有 prototype 中的 functions 都成为 autoAction。
    // 所有 prototype 中的 generator functions 都成为 flow。(需要注意,generators 函数在某些编译器配置中无法被检测到,如果 flow 没有正常运行,请务必明确地指定 flow 注解。)

    // 即:把当前对象上的成员属性变成observable变量,把成员方法变成action方法。
    makeAutoObservable(this, {
      token: observable,
      list: observable,
      num: observable,
      num2: computed,
      changeNum: action,
      //当在action中需要用到同步的async/await时,建议使用 flow,编写generator的语法。
      getList: flow
    })
  }
  token = 'token'
  list = []
  num = 1
  get num2() {
    return this.num * 100
  }
  changeNum(payload) {
      this.num += payload
    }
  * getList(params) {
    const list = yield fetchArticleList(params) //此处是发送请求获取返回列表的示例
    this.list = list
  }
}

 注意:我们要在jsx页面文件中获取到store数据,我们需要使用Provider提供store数据

// 引入mobx状态管理
import { Provider } from 'mobx-react';
import store from './store';
...
 <Provider {...store}>
        {/* 这里为需要store数据的jsx组件页面 */}
 </Provider>
...

react  T.jsx页面

import React from 'react';

import { inject , observer} from 'mobx-react'

// 注意: 要先观察再注入即 inject(observer(...))
// 'user','dd' 为要从store注入的数据  
export default inject('user','dd')( 
    // observer(UI) 把当前组件变成观察者,当store数据发生变化时,组件将会自动更新
    observer(
        ({user,dd}) => {
            console.log(user,dd)
            return (
                <React.Fragment>
                    <h1>这是T页面</h1>
                    <div>{user.num}</div>
                    {/* 调用userstore中的action方法 */}
                    <button onClick={()=>user.changeNum(1)}> num +1 </button>
                </React.Fragment>
            )
        }
    )
)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值