以前用redux改進了todolist,用redux對應用狀態進行管理,今天換成mobx。項目地址css
yarn add customize-cra react-app-rewired @babel/plugin-proposal-decorators --save
複製代碼
const { override, addDecoratorsLegacy } = require('customize-cra');
module.exports = override(
addDecoratorsLegacy()
);
複製代碼
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-app-rewired eject"
},
複製代碼
能夠先學習官方文檔熟悉基本概念react
yarn add mobx mobx-react
複製代碼
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
// import App from './App';
import * as serviceWorker from './serviceWorker';
import {observable, action, computed} from 'mobx'
import {observer} from 'mobx-react'
class Store {
@observable timer = 0
@computed get doubleTimer () {
return this.timer * 2
}
@action.bound add () {
this.timer ++
}
}
@observer
class App extends React.Component {
render () {
const {doubleTimer, add} = this.props.store
return (
<div>
<span>{doubleTimer}</span>
<button onClick={() => add()}>+</button>
</div>
)
}
}
ReactDOM.render(<App store={new Store()}/>, document.getElementById('root'));
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
複製代碼
yarn add mobx mobx-react
複製代碼
import {observable, action} from 'mobx'
import list from '../data'
class Store {
@observable todos = list
@action addTodo = (todo) => { // 增
this.todos = [...this.todos, todo]
}
@action deleteTodo = (id) => { // 刪
this.todos = this.todos.filter(item => {
return item.id !== id
})
}
@action completeTodo = (id) => { // 改
this.todos = this.todos.map(item => {
let obj = item.id === id ? {...item, isComplete: !item.isComplete} : item
return obj
})
}
@action searchTodo = (content) => { // 查
if (content === '') {
this.todos = list
} else {
this.todos = this.todos.filter(item => {
return item.content.indexOf(content) !== -1
})
}
}
}
export default new Store()
複製代碼
import React, {Component} from 'react';
import PropTypes from 'prop-types'
export default class Provider extends Component {
static propTypes = {
store: PropTypes.object.isRequired,
};
static childContextTypes = {
store: PropTypes.object,
};
getChildContext() {
return {
store: this.props.store
}
}
render() {
return this.props.children;
}
}
複製代碼
import React from 'react';
import { Typography, Button } from 'antd';
import PropTypes from 'prop-types'
import {observer} from 'mobx-react'
import './TodoItem.less'
const { Text } = Typography;
@observer
class TodoItem extends React.Component {
static contextTypes = {
store: PropTypes.object,
};
render () {
let { content, isComplete, id } = this.props
let { completeTodo, deleteTodo } = this.context.store
return (
<div className="item-container" onDoubleClick={() => completeTodo(id)} style={{cursor: 'pointer'}}>
<Text delete={isComplete}>{content}</Text>
<Button type="primary" icon="delete" onClick={() => deleteTodo(id)}></Button>
</div>
)
}
}
export default TodoItem;
複製代碼
import React from 'react';
import {observer} from 'mobx-react'
import TodoItem from './TodoItem'
import PropTypes from 'prop-types'
import { List } from 'antd';
@observer
class DataList extends React.Component {
static contextTypes = {
store: PropTypes.object,
};
render () {
const {todos} = this.context.store
return (
<List
bordered
dataSource={todos}
renderItem={item => (
<List.Item>
<TodoItem {...item}/>
</List.Item>
)}
/>
)
}
}
export default DataList;
複製代碼
7.改造components/Form.jsgit
import React from 'react';
import {observer} from 'mobx-react'
import PropTypes from 'prop-types'
import { Input } from 'antd';
const Search = Input.Search;
@observer
class Form extends React.Component {
static contextTypes = {
store: PropTypes.object,
};
render () {
const {searchTodo} = this.context.store
return (
<Search
placeholder="請輸入搜索內容"
style={{marginBottom: '8px'}}
onSearch={value => searchTodo(value)}
enterButton
/>
)
}
}
export default Form;
複製代碼
import React, { Component } from 'react';
import {observer} from 'mobx-react'
import { Button, Input } from 'antd';
import PropTypes from 'prop-types'
@observer
class Footer extends Component {
static contextTypes = {
store: PropTypes.object,
};
constructor(props) {
super(props)
this.state = {
isAdd: false,
addTodo: {}
}
}
handleClick () {
this.setState({
isAdd: true
})
}
handleChange (e) {
this.setState({
addTodo: {
content: e.target.value,
id: new Date(),
completed: false
}
})
}
handleConfirm () {
this.context.store.addTodo(this.state.addTodo)
this.setState({
isAdd: false
})
}
render () {
let addBtn = <Button type="primary" onClick={this.handleClick.bind(this)}>新增</Button>
let addComponent = <div style={{display: 'flex'}}>
<Input onChange={e => this.handleChange(e)} style={{marginRight: '10px'}}/>
<Button type="primary" onClick={this.handleConfirm.bind(this)}>確認</Button>
</div>
let component = this.state.isAdd ? addComponent : addBtn
return (
<div style={{marginTop: '10px'}}>
{component}
</div>
)
}
}
export default Footer;
複製代碼
import React from 'react'
import {observer} from 'mobx-react'
import { Layout } from 'antd';
import Form from './components/Form'
import DataList from './components/DataList'
import Footer from './components/Footer'
import './todolist.less'
import store from './store'
import Provider from './components/Provider'
const { Header, Content} = Layout;
const TodoListApp = observer(() => {
return (
<Provider store={store}>
<Layout className="todolist-layout">
<Header>
<h3 className="logo">TodoList</h3>
</Header>
<Content className="todolist-content">
<Form />
<DataList />
<Footer />
</Content>
</Layout>
</Provider>
)
})
export default TodoListApp
複製代碼
從新運行yarn start,至此使用mobx對todolist改造完畢。github