umi入門

花時(shí)間學(xué)習(xí)了umi笔链,算是對自己的學(xué)習(xí)總結(jié)珠闰,寫了兩個(gè)簡單的demo:計(jì)數(shù)器和todoList凭需。

1. 搭建項(xiàng)目

通過官網(wǎng)的介紹的腳手架搭建一個(gè)簡單的項(xiàng)目辙谜,選擇需要的功能的時(shí)候選擇antd俺榆、dva后面會用到,完成后能在瀏覽器中 http://localhost:8000/ 看到項(xiàng)目筷弦。

2. 修改基礎(chǔ)項(xiàng)目結(jié)構(gòu)

  1. 在 src/pages 目錄下新建2個(gè)文件夾:
  • count/index.jsx
export default function () {
  return (
    <div>count</div>
  )
}
  • todoList/index.jsx
export default function () {
  return (
    <div>todoList</div>
  )
}
  1. 修改 src/pages/index.js 實(shí)現(xiàn)首頁到這兩個(gè)新建頁面的跳轉(zhuǎn)
import styles from './index.css';
import Link from 'umi/link'

export default function () {
  return (
    <div className={styles.normal}>
      <div><Link to="/count">計(jì)數(shù)器</Link></div>
      <div><Link to="/todoList">todoList</Link></div>
    </div>
  );
}

現(xiàn)在在首頁點(diǎn)擊跳轉(zhuǎn)回到404頁面肋演,這是因?yàn)檫€沒有配置路由,路由配置在根目錄下的 .umirc.js烂琴,

routes: [
    {
      path: '/',
      component: '../layouts/index',
      routes: [
        { path: '/', component: '../pages/index' }
      ]
    }
  ],

嘗試使用umi的約定路由方式,umi 會根據(jù) pages 目錄自動生成路由配置蜕乡,
將.umirc.js的routes配置注釋奸绷,不注釋會以配置文件中的路由配置為主
,現(xiàn)在路由就能正常跳轉(zhuǎn)了层玲。

3. 實(shí)現(xiàn)計(jì)數(shù)器功能

image

1. 實(shí)現(xiàn)簡單的加号醉、減

  1. 實(shí)現(xiàn)基本的頁面結(jié)構(gòu),修改count/index.jsx
import { Button } from 'antd'
import styles from './index.css'

function Count() {
return (
  <div>
    <h3>數(shù)量:1</h3>
    <div className={styles.buttons}>
      <Button type="primary">加</Button>
      {' '}
      <Button type="primary">減</Button>
    </div>
  </div>
)
}

export default Count
  1. 在count目錄下新建model.js文件辛块,用來進(jìn)行狀態(tài)數(shù)據(jù)的管理
export default {
  namespace: 'count',
  state: {
    count: 0
  },
  reducers: {
    increment(state) {
      return {
        count: state.count + 1
      }
    },
    decrement(state) {
      return {
        count: state.count - 1
      }
    }
  },
}
  1. 添加點(diǎn)擊事件畔派,實(shí)現(xiàn)數(shù)字的加、減

count/index.jsx

import { Button } from 'antd'
import styles from './index.css'
import { connect } from 'dva'

function Count({ count, increment, decrement }) {
  return (
    <div>
      <h3>數(shù)量:{count}</h3>
      <div className={styles.buttons}>
        <Button type="primary" onClick={() => { increment() }}>加</Button>
        {' '}
        <Button type="primary" onClick={() => { decrement() }}>減</Button>
      </div>
    </div>
  )
}

const mapStateToProps = state => {
  return {
    count: state.count.count
  }
}

const mapDispatchToProps = dispatch => {
  return {
    increment: () => dispatch({ type: 'count/increment' }),
    decrement: () => dispatch({ type: 'count/decrement' })
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(Count)

完成上述操作润绵,應(yīng)該能實(shí)現(xiàn)簡單的加线椰、減功能了。

2. 實(shí)現(xiàn)帶延遲的加尘盼、減

  1. 在count/model.js中添加異步操作的管理憨愉,實(shí)現(xiàn)延遲1s加、延遲2s減卿捎。
export default {
  ...
  effects: {
    *incrementAsync(actions, { put, call }) {
      yield call(delay, 1000)
      yield put({ type: 'increment' })
    },
    *decrementAsync(actions, { put, call }) {
      yield call(delay, 2000)
      yield put({ type: 'decrement' })
    }
  }
}

function delay(timeout) { // 延遲函數(shù)
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve()
    }, timeout)
  })
}
  1. 在 count/index.jsx 中添加異步操作
import { Button } from 'antd'
import styles from './index.css'
import { connect } from 'dva'

function Count({ count, increment, decrement, incrementAsync, decrementAsync }) {
  return (
    <div>
      <h3>數(shù)量:{count}</h3>
      <div className={styles.buttons}>
        <Button type="primary" onClick={() => { increment() }}>加</Button>
        {' '}
        <Button type="primary" onClick={() => { decrement() }}>減</Button>
      </div>
      <div className={styles.buttons}>
        <Button type="primary" onClick={() => { incrementAsync() }}>延遲1s加</Button>
        {' '}
        <Button type="primary" onClick={() => { decrementAsync() }}>延遲2s減</Button>
      </div>
    </div>
  )
}

const mapStateToProps = state => {
  return {
    count: state.count.count
  }
}

const mapDispatchToProps = dispatch => {
  return {
    increment: () => dispatch({ type: 'count/increment' }),
    decrement: () => dispatch({ type: 'count/decrement' }),
    incrementAsync: () => dispatch({ type: 'count/incrementAsync' }),
    decrementAsync: () => dispatch({ type: 'count/decrementAsync' })
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(Count)

做完以上的步驟一個(gè)簡單的計(jì)數(shù)器就基本完成了配紫。

4. 實(shí)現(xiàn)一個(gè)todoList

image

1. 完成靜態(tài)頁面

  • 在 todoList 新建componets文件夾用來存放頁面組件

components/AddTodo.jsx

import { Input, Button } from 'antd'
import styles from './addTodo.css'

function AddTodo() {

  return (
    <div className={styles.addDiv}>
      <Input placeholder="請輸入相關(guān)事項(xiàng)" className={styles.input}  />
      <Button type="primary">添加</Button>
    </div>
  )
}


export default AddTodo

components/Todo.jsx

import { Typography, Button } from 'antd';
import styles from './todo.css'

const { Text } = Typography;

function Todo() {
  return (
    <div className={styles.todo}>
      <Text className={styles.text}>123</Text>
      <div className={styles.buttons}>
        <Button type="link">刪除</Button>
        <Button type="link">修改</Button>
      </div>
    </div>
  )
}

export default Todo

todolist.jsx

import AddTodo from './components/AddTodo'
import Todo from './components/Todo'
import { List } from 'antd'
import styles from './index.css'

function TodoList() {

  return (
    <div className={styles.todoList}>
      <AddTodo></AddTodo>
      <List
        className={styles.list}
        bordered
        dataSource={[]}
        renderItem={(item) => (
          <List.Item>
            <Todo ></Todo>
          </List.Item>
        )}
      />
    </div>
  )
}

export default TodoList

完成靜態(tài)頁面

image

2. 修改AddTodo組件,完成輸入框輸入午阵,點(diǎn)擊添加按鈕顯示輸入的內(nèi)容

函數(shù)組件沒有生命周期和state躺孝,這里用到了react hook的usestate

import { Input, Button } from 'antd'
import styles from './addTodo.css'
import { useState } from 'react'

function AddTodo() {
  const [inputValue, setInputValue] = useState('')

  return (
    <div className={styles.addDiv}>
      <Input placeholder="請輸入相關(guān)事項(xiàng)" className={styles.input} onChange={(e) => { setInputValue(e.target.value) }} />
      <Button type="primary" onClick={() => { console.log(inputValue) }}>添加</Button>
    </div>
  )
}

export default AddTodo

在input中輸入一段文字就能在控制臺看到輸入的內(nèi)容了。

3. 新增models進(jìn)行狀態(tài)管理

  • todoList/models/todoList.js,新建初始state
export default {
  namespace: 'todoList',
  state: {
    list: [
      {
        content: '123',
        completed: false
      }
    ],
  }
}
  • 在todoList中展示state的內(nèi)容
import AddTodo from './components/AddTodo'
import Todo from './components/Todo'
import { List } from 'antd'
import { connect } from 'dva'
import styles from './index.css'

function TodoList({ list }) {

  return (
    <div className={styles.todoList}>
      <AddTodo></AddTodo>
      <List
        className={styles.list}
        bordered
        dataSource={list}
        renderItem={(item) => (
          <List.Item>
            <Todo {...item}></Todo>
          </List.Item>
        )}
      />
    </div>
  )
}

const mapStateToProps = state => {
  return {
    list: state.todoList.list
  }
}

export default connect(mapStateToProps)(TodoList)

修改Todo.js

import { Typography, Button } from 'antd';
import styles from './todo.css'

const { Text } = Typography;

function Todo({ completed, content }) {
  return (
    <div className={styles.todo}>
      <Text className={styles.text} delete={completed}>{content}</Text>
      <div className={styles.buttons}>
        <Button type="link">刪除</Button>
        <Button type="link">修改</Button>
      </div>
    </div>
  )
}

export default Todo

4. 完成增植袍、刪伪很、改的功能

  • 修改 models/todoList.js, 添加reducers
reducers: {
    addTodo(state, { payload: value }) { // 增
      return {
        list: [...state.list, { content: value, completed: false }]
      }
    },
    removeTodo(state, { payload: index }) { // 刪
      let newList = state.list.filter((item, i) => i !== index)
      return {
        list: newList
      }
    },
    modifyTodo(state, { payload: index }) { // 改
      let newList = state.list.map((item, i) => {
        let flag = index === i ? !item.completed : item.completed
        return { ...item, completed: flag }
      })
      return {
        list: newList
      }
    }
  },
  • 修改AddTodo.jsx實(shí)現(xiàn)添加奋单,將先前打印出的輸入文字添加到list中來
import { Input, Button } from 'antd'
import styles from './addTodo.css'
import { useState } from 'react'
import { connect } from 'dva'

function AddTodo({ addTodo }) {
  const [inputValue, setInputValue] = useState('')

  return (
    <div className={styles.addDiv}>
      <Input placeholder="請輸入相關(guān)事項(xiàng)" className={styles.input} onChange={(e) => { setInputValue(e.target.value) }} />
      <Button type="primary" onClick={() => { addTodo(inputValue) }}>添加</Button>
    </div>
  )
}

const mapDispatchToProps = dispatch => {
  return {
    addTodo: value => dispatch({ type: 'todoList/addTodo', payload: value })
  }
}

export default connect(null, mapDispatchToProps)(AddTodo)
  • 修改 Todo.jsx锉试,實(shí)現(xiàn)刪除和修改
import { Typography, Button } from 'antd';
import styles from './todo.css'
import { connect } from 'dva'

const { Text } = Typography;

function Todo({ completed, content, index, removeTodo, modifyTodo }) {
  return (
    <div className={styles.todo}>
      <Text className={styles.text} delete={completed}>{content}</Text>
      <div className={styles.buttons}>
        <Button type="link" onClick={() => { removeTodo(index) }}>刪除</Button>
        <Button type="link" onClick={() => { modifyTodo(index) }}>修改</Button>
      </div>
    </div>
  )
}

const mapDispatchToProps = dispatch => {
  return {
    removeTodo: index => dispatch({ type: 'todoList/removeTodo', payload: index }),
    modifyTodo: index => dispatch({ type: 'todoList/modifyTodo', payload: index })
  }
}

export default connect(null, mapDispatchToProps)(Todo)
  • 在 todoList/index.jsx中Todo添加index
 <List
        className={styles.list}
        bordered
        dataSource={list}
        renderItem={(item, index) => (
          <List.Item>
            <Todo {...item} index={index}></Todo>
          </List.Item>
        )}
      />

5. 使用后臺數(shù)據(jù)替換本地list的數(shù)據(jù)

使用umi-request來向后臺發(fā)送請求,后臺使用easy-mock進(jìn)行數(shù)據(jù)模擬

  • 安裝umi-request
yarn add umi-request
  • 請求放在models/todoList中處理
effects: {
    *getListAsync(actions, { put, call }) {
      const res = yield call(request, 'http://localhost:7300/mock/5dd4fcaebe523217231cce587/react-api/getList')
      yield put({ type: 'getList', payload: res.data.list })
    }
  }
  • 修改 todoList/index.jsx览濒, 這里用到了useEffect
import { useEffect } from 'react'

function TodoList({ list, getList }) {
  useEffect(() => {
    getList()
  }, [getList])
  
......

const mapDisPatchToProps = dispacth => {
  return {
    getList: () => dispacth({ type: 'todoList/getListAsync' })
  }
}

export default connect(mapStateToProps, mapDisPatchToProps)(TodoList)

至此呆盖,兩個(gè)簡單的demo基本實(shí)現(xiàn)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
禁止轉(zhuǎn)載贷笛,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者应又。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市乏苦,隨后出現(xiàn)的幾起案子株扛,更是在濱河造成了極大的恐慌,老刑警劉巖汇荐,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件洞就,死亡現(xiàn)場離奇詭異,居然都是意外死亡掀淘,警方通過查閱死者的電腦和手機(jī)旬蟋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來革娄,“玉大人倾贰,你說我怎么就攤上這事±雇铮” “怎么了匆浙?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長厕妖。 經(jīng)常有香客問我首尼,道長,這世上最難降的妖魔是什么叹放? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任饰恕,我火速辦了婚禮,結(jié)果婚禮上井仰,老公的妹妹穿的比我還像新娘埋嵌。我一直安慰自己,他們只是感情好俱恶,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布雹嗦。 她就那樣靜靜地躺著范舀,像睡著了一般。 火紅的嫁衣襯著肌膚如雪了罪。 梳的紋絲不亂的頭發(fā)上锭环,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機(jī)與錄音泊藕,去河邊找鬼辅辩。 笑死,一個(gè)胖子當(dāng)著我的面吹牛娃圆,可吹牛的內(nèi)容都是我干的玫锋。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼讼呢,長吁一口氣:“原來是場噩夢啊……” “哼撩鹿!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起悦屏,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤节沦,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后础爬,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體甫贯,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年幕帆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了获搏。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,785評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡失乾,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出纬乍,到底是詐尸還是另有隱情碱茁,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布仿贬,位于F島的核電站纽竣,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏茧泪。R本人自食惡果不足惜蜓氨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望队伟。 院中可真熱鬧穴吹,春花似錦、人聲如沸嗜侮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至顷霹,卻和暖如春咪惠,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背淋淀。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工遥昧, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人朵纷。 一個(gè)月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓炭臭,卻偏偏與公主長得像,于是被迫代替她去往敵國和親柴罐。 傳聞我的和親對象是個(gè)殘疾皇子徽缚,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評論 2 354