React+umi+dva

Umi基本使用

安装

	npm install umi -g

项目目录

	md umi-app
	cd umi-app

新建 index页

	umi g page index
	umi g page about

起服务

	umi dev

动态路由
以$开头的文件或目录

	umi g page users/'$id'

获取参数和以前写法相同

	export default function({match}) {
  return (
    <div>
      <h1>user id: {match.params.id}</h1>
    </div>
  );
}

嵌套路由
目录下面出现_layout组件则会转换路由配置为嵌套路由

	// 创建父组件 umi g layout ./users
	export default function(props) {
	  return (
	    <div>
	      <h1>Page _layout</h1>
	      <div>{props.children}</div>
	    </div>
	  )
	}
	// 创建兄弟组件 umi g page users/index

页面跳转

	// 用户列表跳转至用户详情页, users/index.js
import Link from "umi/link";
import router from "umi/router";
 
export default function() {
  return (
    <div className={styles.normal}>
      <h1>用户列表</h1>
      <ul>
        {users.map(u => (
          // 声明式
          // <li key={u.id}>
          //   <Link to={`/users/${u.id}`}>{u.name}</Link>
          // </li>
          // 命令式
          <li key={u.id} onClick={()=>router.push(`/users/${u.id}`)}>{u.name}</li>
        ))}
      </ul>
    </div>
  );
}

404页面
约定 pages/404.js 为 404 页面,需返回 React 组件。
创建404页面: umi g page ./404
布局页

约定 src/layouts/index.js 为全局路由,返回一个 React 组件,通过 props.children 渲染子组件。
创建布局页面: umi g page …/layouts/index

	export default function(props) {
  return (
    <div className={styles.normal}>
      <h1>布局页面</h1>
      {props.children}
    </div>
  );
}

针对特定路由指定布局页

	if (props.location.pathname === '/404') {
    return <SimpleLayout>{ props.children }</SimpleLayout>
}

通过注释扩展路由
约定路由文件的首个注释如果包含 yaml 格式的配置,则会被用于扩展路由。
权限路由,about.js

	/**
	 * title: About Page
	 * Routes:
	 *   - ./routes/PrivateRoute.js
	 */

创建./routes/PrivateRoute.js

	import Redirect from "umi/redirect";
 
	export default props => {
	  if (new Date().getDay() % 2 === 1) {
	    // 单数日需要登陆
	    return <Redirect to="/login"/>;
	  }
	  return (
	    <div>
	      <div>PrivateRoute</div>
	      {props.children}
	    </div>
	  );
	};

创建登录页面验证: umi g page login
安装umi-plugin-react

	npm install umi-plugin-react -D

配置
创建配置文件: .umirc.js

export default {
  plugins: [
    ['umi-plugin-react', {
      dva: true,
    }]
  ]
}

创建model
新建src/models/goods.js

	export default {
  namespace: 'goods', // model的命名空间,区分多个model
  state: [{ title: "苹果" },{ title: "橘子" }], // 初始状态
  effects:{}, // 异步操作
  reducers: {} // 更新状态
}

使用状态
类似redux,使用connect获取数据状态并映射给组件
创建页面goods.js: umi g page goods

	export default connect(
  state => ({
    goodsList: state.goods // 获取指定命名空间的模型状态
  }),
)(function({ goodsList }) {
  return (
    <div className={styles.normal}>
      <h1>Page goods</h1>
      <ul>
        {goodsList.map(good => (
          <li key={good.title}>{good.title}</li>
        ))}
      </ul>
    </div>
  );
});

更新模型src/models/goods.js

	export default {
  reducers: {
    addGood(state, action) {
      return [...state, {title: action.payload}];
    }
  }
}

调用reducer:goods.js

	export default connect(
  state => ({}),
  {
    addGood: title => ({
      type: "goods/addGood", // action的type需要以命名空间为前缀+reducer名称
      payload: title
       })
  }
)(function({ goodsList, addGood }) {
  return (
    <div className={styles.normal}>
      <button onClick={() => addGood("商品" + new Date().getTime())}>
        添加商品
      </button>
    </div>
  );
});

数据mock:模拟数据接口
mock目录和src平级,新建mock/goods.js

	let data = [
  {title:"苹果"},
  {title:"橘子"}
];
 
export default {
  // "method url": Object 或 Array
  // "get /api/goods": { result: data },
  
  // "method url": (req, res) => {}
  'get /api/goods': function (req, res) {
    setTimeout(() => {
      res.json({ result: data })
    }, 250)
  },
}

effect处理异步:基于redux-saga,使用generator函数来控制异步流程
请求接口,models/goods.js

	// 首先安装axios
	import axios from 'axios';
	 
	// api
	function getGoods(){
	  return axios.get('/api/goods')
	}
	 
	export default {
	  state: [
	    // {title:"苹果"},
	    // {title:"梨子"}
	     ],
  effects: { // 副作用操作,action-动作、参数等,saga-接口对象
    *getList(action, {call, put}){      
      const res = yield call(getGoods)
      yield put({ type: 'initGoods', payload: res.data.result })
    }
  },
  reducers: {
    initGoods(state,{payload}){
      return payload
    }
  }
}

组件调用,goods.js

	import {useEffect} from 'react';
export default connect(
  state => ({}),
  {
    addGood: title => ({}),
    getList: () => ({ // 获取数据
      type: "goods/getList"
    }),
  }
)(function({ goodsList, addGood,getList }) {
  useEffect(()=>{ // 调用一次
    getList();
  },[])
  return ();
});

加载状态
利用内置的dva-loading实现,获取加载状态,goods.js

	connect(
	  state => ({
	    loading: state.loading // 通过loading命名空间获取加载状态
	  }),
	  {...}
	)(function({ goodsList, addGood, getList, loading }) {
	    console.log(this.props.loading);
	    if (this.props.loading.models.goods) {
	      return <div>加载中...</div>
	    }
	    ...
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值