React + MobX + Electron + Node.js + MongoDB 全栈项目开发实践(一)

丰富功能

继续参照上一篇中介绍的知乎文章,借鉴一些想法,又加入本身的一些想法,开始初步完成一个应用的闭环。css

任务拆分

一开始只是实现了很是简单的加分减分功能,这样虽然方便本身给本身记分,可是限制太少,也没有具体的目标。所以,为了作出相对完整的功能,开始细化任务及其数据结构。react

设想了一下每日任务打卡的场景,画了一些流程草图,逐步定下来了任务的相关数据:数据库

任务 id (暂时先用任务标题)
用户 id (目前是单用户,默认为 0)
标题(任务名称)
描述
类型(是任务仍是欲望)
分数(根据类型决定加分仍是减分)
天天最多使用次数
建立时间
最近更新

复制代码

目前,任务以 JSON 格式存储在一个 JS 文件中。以后会将其存入数据库中。数组

任务的相关功能:缓存

  • 添加任务
  • 查询任务
  • 修改任务
  • 删除任务
  • 打卡

无非就是数据库的 CURD 工做。bash

组件/页面设计

数据(或者 state)要由组件来承载。如今构思到的组件是:分数显示组件、任务组件以及导航组件。antd

导航组件贯穿整个 APP,首页显示分数组件,经过导航进入任务/欲望界面,并在该界面显示相应的任务/欲望。数据结构

在第 0 篇中,由于刚写出来的乞丐乞丐版是真·SPA,因此只须要用 local state,加上 localStorage 来缓存数据以便以后读取。post

代码长这样:学习

import React, { Component } from 'react';
import './App.css';
import { Row, Button, Icon } from 'antd';

class App extends Component {
  constructor(props){
    super(props);
    this.state = {
      score: localStorage.getItem('score') ? parseInt(localStorage.getItem('score')) : 0
    };
    this.increase = this.increase.bind(this);
    this.decrease = this.decrease.bind(this);
    this.clearScore = this.clearScore.bind(this);

  }

  increase(){
    this.setState({
      score: this.state.score + 1
    });
  }

  decrease(){
    this.setState({
      score: this.state.score - 1
    });
    console.log(this.state.score);
  }

  clearScore(){
    this.setState({
      score: 0
    });
  }

  componentDidUpdate() {
    localStorage.setItem('score', this.state.score);
  }

  render() {
    return (
      <div className="App">
        <Row>
          <Button className="operation" onClick={this.increase}>
            <Icon type="plus" />
          </Button>
        </Row>
        <Row>
          <Button className="operation" onClick={this.decrease}>
            <Icon type="minus" />
          </Button>
        </Row>
        <div className="score">
          <h2>{this.state.score}</h2>
        </div>
        <div className="clear">
          <Button onClick={this.clearScore}>Clear</Button>
        </div>
      </div>
    );
  }
}

export default App;

复制代码

local storage 有个小坑,就是存进去的数值被转化成字符串了。所以每次读取的时候都须要转回数字。

有了页面、组件之后,更新分数的方法被绑在了 task 组件上,这样不能更新到上一级页面的分数。因此每次点击完都须要刷新页面,让任务页面组件读取本地缓存。

// ListPage 做为全部项目的容器
import React, { Component } from 'react';
import { Row, Col, Button } from 'antd';
import "./ListPage.css";

class ListPage extends Component {
  constructor(props) {
    super(props);
    this.state = {
      score: localStorage.getItem('score') ? parseInt(localStorage.getItem('score')) : 0
    };
  }

  clearScore() {
    this.setState({
      score: 0
    });
  }

  componentDidUpdate() {
    localStorage.setItem('score', this.state.score);
  }

  render() {
    const { type } = this.props.match.params;
    console.log(type);
    return (
      <div> <Row> <div className="score-list"> <h2>{this.state.score}</h2> </div> </Row> </div>
    );
  }
}

export default ListPage;

复制代码
// 容器中读取 list 数据,每个数据对应一个 ListItem
import React, { Component } from 'react';
import { Card, Row, Col, Button } from 'antd';

import "./ListItem.css";

class ListItem extends Component {
  constructor(props){
    super(props)
    this.state = {
      buttonVisible: false
    }
  }
  onClickListItem(itemInfo) {
    console.log(itemInfo.name, itemInfo.type)
    this.setState({
      buttonVisible: !this.state.buttonVisible
    })
  }
  changeScore(itemInfo) {
    let score = parseInt(localStorage.getItem("score"))
    if(itemInfo.type === "task") {
      score += itemInfo.score
    } else {
      score -= itemInfo.score
    }
    localStorage.setItem("score", score)
  }
  render(){
    const { itemInfo } = this.props
    return (
      <Card className="list-item" onClick={() => {this.onClickListItem(itemInfo)}}> <Row> <Col span={16} className="list-item-info"> <h3>{itemInfo.name}</h3> <p>{itemInfo.desc}</p> </Col> <Col span={8}> {itemInfo.type==="task" && <div className="item-score">+{itemInfo.score}</div>} {itemInfo.type==="desire" && <div className="item-score-desire">-{itemInfo.score}</div>} </Col> </Row> {this.state.buttonVisible && (<Row> <Button onClick={() => {this.changeScore(itemInfo)}}>打卡</Button> </Row>)} </Card>
    )
  }
}

export default ListItem;
复制代码

这时就须要一个全局的状态管理。 (是否有更简单暴力的方法呢?好比自动刷新页面?或许能够,可是这会影响使用体验,且不利于之后增长其余功能,迟早会形成混乱。)

曾经使用过 Redux,刚入门的时候感受到很是痛苦。又要 action,action types,reducer,store。虽然最后大体搞明白了,可是仍是留下了一些坑,还有一个更新数据会赋值为对象的一个奇怪 bug。因此,接下来的文章中,我会边学习 MobX 边总结 Redux 的思想,将二者进行对比。

系列文章

React + MobX + Electron + Node.js + MongoDB 全栈项目开发实践(零)

相关文章
相关标签/搜索