用 react+moox 五分鐘寫一個 todomvc 應用

hellosean發表於2018-02-07

前言

使用 react, redux 開發一個應用是非常複雜的,moox 是基於 redux 的高效能狀態管理機,簡化了 redux 模板程式碼和提高了效率,本篇教程將帶領大家在五分鐘時間做一個 todomvc 應用。 當然,本篇教程不包括 react 環境搭建,推薦使用新的打包工具 Parcel

注:parcel 需要 node > 8.0

效果圖

原始碼地址:demo

用 react+moox 五分鐘寫一個 todomvc 應用

起步

npm install --save moox
npm install --save react-redux
複製程式碼

目錄結構

components/App.js
models/user.js
index.js
model.js
複製程式碼

入口檔案 index.js

import React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import App from './components/App'
import Model from './model'

const store = Model.getStore()
render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
)

複製程式碼

store 通過 getStore 方法獲取,傳給 Provider 元件。

model.js

import moox from '../src/index'
import user from './models/user'

export default moox({
  user
})

複製程式碼

Model 是通過 moox(Object) 生成的物件。

userModel 檔案 user.js

export default {
  // 初始化 state
  state: {
    list: ['tom', 'xiaoming'],
    status: 0,
    filterText: ''
  },
  // 帶Action 字尾的字串代表一個 action函式
  addUserSyncAction: null,
  requestStatusAction: null,
  changeFilterValueAction: (text)=>({
    text
  }),
  changeCurrentEditUserAction: (name, index) =>({
    name,
    index
  }),
  addUserAction: () => (
    {
      payload: new Promise((resolve) => {
        setTimeout(function () {
          resolve(100)
        }, 300)
      })
    }
  ),
  delUserAction: (index)=>{
    return {
      index: index
    }
  },  
  // 在 reducers 物件裡寫對應 action 的 state 處理函式,引數通過 action 物件獲取。
  reducers: {
    changeCurrentEditUserAction: function(state, action){
      state.list[action.index] = action.name
    },
    changeFilterValueAction: function(state, action){
      state.filterText = action.text
    },
    changeEditIndexAction: function(state, action){
      state.currentEditIndex = action.index
    },
    addUserAction: function (state, action) {
      state.list.push(getRandomName())
      state.status = 0
    },
    addUserSyncAction: function(state, action){
      state.list.push(getRandomName(5))
    },
    requestStatusAction: function (state, action) {
      state.status = 1
    },
    delUserAction: function(state, action){
      state.list.splice(action.index, 1)
    }
  }
}

function getRandomName(len=4){
  let str = ''
  while(len--) str += String.fromCharCode(97 + Math.ceil(Math.random()* 25))
  return str
}

複製程式碼

元件 App.js

import React from 'react'
import { connect } from 'react-redux'
import Model from '../model'

const App = (props) => {
  const handleClick = () => {
    if (props.user.status === 1) return;
    props.requestStatusAction()
    props.addUserAction()
  }
  const handleClickSync = () => props.addUserSyncAction()
  const delUser = (index) => ()=>props.delUserAction(index)
  const getContent = (item, index) => {
    return <input type="text" onChange={(event) => {
      props.changeCurrentEditUserAction(event.target.value, index)
    }} value={item} />
  }
  const list = props.user.list.filter(item=>{
    item = item + '';
    return !props.user.filterText || item.indexOf(props.user.filterText) !== -1
  })

  return <div style={{ width: 500, margin: '100px auto' }}>
    <div >
      <input placeholder="Filter" style={{height: 35, width: '100%', backgroundColor: '#eee'}} type="text" value={props.user.filterText} onChange={(event)=> props.changeFilterValueAction(event.target.value)} />
    </div>
    <div>
      <button style={{ height: '40px', margin: 30 }} onClick={handleClick}>Async Add Random Number</button>
      <button style={{ height: '40px', margin: 30 }} onClick={handleClickSync}>Add Random Number</button>
      {props.user.status === 1 ? 'loading...' : ''}
    </div>
    {list.map((item, index) => {
      return <div style={{ height: 30, margin: 15, backgroundColor: '#eee' }} key={index}>{}{getContent(item, index)} &nbsp; <span onClick={delUser(index)}>X</span></div>
    })}
  </div>
}
export default connect((state) => ({
  user: state.user
}), {
    addUserAction: Model.user.addUserAction,
    requestStatusAction: Model.user.requestStatusAction,
    delUserAction: Model.user.delUserAction,
    addUserSyncAction: Model.user.addUserSyncAction,
    changeCurrentEditUserAction: Model.user.changeCurrentEditUserAction,
    changeFilterValueAction: Model.user.changeFilterValueAction
  })(App)
複製程式碼

到這裡,我們已經完成了一個簡單的 todomvc 應用。

相關文章