React + Antd + Mobx改进之前简单的todolist

栏目: JavaScript · 发布时间: 6年前

内容简介:可以先学习官方文档熟悉基本概念7.改造components/Form.js重新运行yarn start,至此使用mobx对todolist改造完毕。
  1. 使用react-app-rewired
yarn add customize-cra react-app-rewired @babel/plugin-proposal-decorators --save
复制代码
  1. 项目根目录新建config-overrides.js文件加入以下代码
const { override, addDecoratorsLegacy } = require('customize-cra');
module.exports = override(
 addDecoratorsLegacy()
 );
复制代码
  1. 修改package.json文件如下
"scripts": {
 "start": "react-app-rewired start",
 "build": "react-app-rewired build",
 "test": "react-app-rewired test",
 "eject": "react-app-rewired eject"
  },
复制代码

2. 了解mobx

可以先学习官方文档熟悉基本概念

  1. 按照上面改造create-react-app创建的项目后,引入mobx
yarn add mobx mobx-react
复制代码
  1. 修改APP.js实现一个简单的domo
  • @observable 可以在实例字段和属性 getter 上使用, 对于对象的哪部分需要成为可观察的
  • @action 用来修改observables状态
  • @computed可以根据现有的状态或其它计算值衍生出的值,可以在任意类属性的 getter 上使用 @computed 装饰器来声明式的创建计算属性
  • @observer 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();

复制代码

3. 使用mobx管理todolist的状态

  1. 修改之前的项目 react-antd-todolist-simple ,添加mobx相关包
yarn add mobx mobx-react
复制代码
  1. 按照上面的步骤修改使其支持装饰器
  2. 新建store/index.js
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()
复制代码
  1. 新建Provider组件作用和react-redux里面的Provider类似,父子组件之间通过context将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;
  }
}
复制代码
  1. 改造components/TodoItem.js
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;
复制代码
  1. 改造components/DataList.js
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.js

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;
复制代码
  1. 改造componets/Footer.js
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;
复制代码
  1. 将所有改过的组件都引入到todoList中
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改造完毕。

相关: React + Antd + Redux改进之前简单的todolist

React + Antd + Redux改进之前简单的todolist


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Cyberwar

Cyberwar

Kathleen Hall Jamieson / Oxford University Press / 2018-10-3 / USD 16.96

The question of how Donald Trump won the 2016 election looms over his presidency. In particular, were the 78,000 voters who gave him an Electoral College victory affected by the Russian trolls and hac......一起来看看 《Cyberwar》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试