• React+Mobx+Koa2+LeanCloud 搭建个人版TodoList


    最近在看Mobx和Koa相关的内容,实践初出真知,我们来做一个小项目实践一下。最容易想到的就是Todolist了,这次我们做得稍微实用一点,放到自己的vps上日常用用也是不错的~

    用到的装备:

    • React
    • Mobx
    • Koa2
    • LeanCloud
    • pm2

    因为项目比较简单,bundler我用的是parcel,一行配置都不用写确实很爽,编译速度也非常快。数据存储我用的是LeanCloud,有开发版可以免费试用,就是请求数量会有一定的限制。当然你也可以使用MongoDB,这边用云存储主要是为了方便。

    最终效果图如下:


    前端项目

    https://github.com/zebrallel/Todolist

    src/app.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    // 和Redux一样,mobx也给我们提供了一个Provider,注入所有的应用数据
    import { Provider } from 'mobx-react'

    ReactDOM.render(
    <Provider {...stores}>
    <Todo />
    </Provider>,
    document.getElementById('root')
    )

    src/store/TodoStore

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    import { observable, action } from 'mobx'

    // 这里就类似于Redux里的Reducer了
    class TodoStore {
    @observable todos
    @observable currMonth
    @observable currDay

    constructor() {
    const today = new Date()

    this.todos = []
    this.currMonth = today.getMonth()
    this.currDay = today.getDate()
    }

    // 加载todolist
    @action
    loadTodos = nextTodos => {
    this.todos.clear()
    nextTodos.forEach(item => {
    this.todos.push(item)
    })
    }

    // 更新月份
    @action
    updateCurrMonth = nextMonth => {
    this.currMonth = nextMonth
    }

    // 更新日期
    @action
    updateCurrDay = nextDay => {
    this.currDay = nextDay
    }

    // 添加一条todo
    @action
    insertNewItem = item => {
    this.todos.push(item)
    }
    }

    export default new TodoStore()

    接下来是action
    src/actions/TodoAction

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    import todoStore from '../../store/TodoStore'
    import ApiService from '../../service/ApiService'

    const loadTodos = async (date) => {
    const res = await ApiService.get(`/api/todos/query/${date}`)

    if(res.code === 0){
    todoStore.loadTodos(res.data)
    }
    }

    const updateMonth = month => {
    todoStore.updateCurrMonth(month)
    }

    const updateDay = day => {
    todoStore.updateCurrDay(day)
    }

    const insertNewItem = (item) => {
    todoStore.insertNewItem(item)
    }

    const updateItem = async (nextItem) => {
    await ApiService.post('/api/todos/update', nextItem)
    }

    export default {
    loadTodos,
    updateMonth,
    updateDay,
    updateItem,
    insertNewItem
    }

    store, action都有了,最后就是我们的component了
    src/components/Todo

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    import { todoActions as actions } from '../../actions'
    import { observable, action } from 'mobx'
    import { observer, inject } from 'mobx-react'

    // 我们用inject把数据和组件连接起来,类似connect
    // observer帮助我们实现数据变化后组件能够实时刷新
    @inject(store => ({ ...store.todoStore }))
    @observer
    export default class TodoList extends React.Component {
    @observable addModalVisible = false
    @observable newItemValue = ''

    @action
    changeVisible = visible => {
    this.addModalVisible = visible
    }

    @action
    onNewItemValueChange = value => {
    this.newItemValue = value
    }

    @action
    clearNewItemValue = () => {
    this.newItemValue = ''
    }

    // ...
    }

    Koa项目

    https://github.com/zebrallel/Minos

    入口
    src/app.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    const Koa = require('koa')
    const app = new Koa()
    const convert = require('koa-convert')
    const initStorage = require('./modules/storage')
    const hbs = require('koa-hbs')
    const rootRouter = require('./routes')
    const bodyParser = require('koa-bodyparser')

    const port = process.env.PORT || 4000

    app.use(bodyParser())

    // access log
    app.use(async (ctx, next) => {
    const date = new Date().toLocaleString()
    const body = ctx.method.toLowerCase() === 'get' ? ctx.querystring : JSON.stringify(ctx.request.body)

    console.log(`[${date}]:::${ctx.method}:::${ctx.url}:::${body}`)

    await next()
    })

    // init view engine
    app.use(
    hbs.middleware({
    viewPath: `${__dirname}/views`
    })
    )

    // router entry
    app.use(rootRouter.routes())
    app.use(rootRouter.allowedMethods())

    // final router
    app.use(async ctx => {
    switch (ctx.method.toLowerCase()) {
    case 'get':
    await ctx.render('pages/404')
    break
    case 'post':
    ctx.body = { code: -1, message: 'request path can not match!' }
    break
    }
    })

    app.listen(port, '127.0.0.1', null, () => {
    console.log(`Server is running on ${port}`)
    })

    CURD
    src/routes/todos

    这边的CURD操作都是用了LeanCloud提供的Api,使用起来非常简单,具体大家可以去看官方文档

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    const Router = require('koa-router')
    const router = new Router()
    const AV = require('../../modules/storage')

    // 保存一条新数据
    router.post('/save', async (ctx, next) => {
    const { date, content } = ctx.request.body
    const TodoModel = AV.Object.extend('TodoModel')
    const item = new TodoModel()

    item.set('date', date)
    item.set('content', content)
    item.set('completed', false)

    try {
    const res = await item.save()

    ctx.body = { code: 0, message: 'success', data: { id: res.id } }
    } catch (error) {
    ctx.body = { code: -1, message: error.rawMessage, error }
    }
    })

    // 查询
    router.get('/query/:year-:month-:day', async (ctx, next) => {
    const { year, month, day } = ctx.params
    const dateQuery = new AV.Query('TodoModel')

    dateQuery.equalTo('date', `${year}-${month}-${day}`)

    try {
    const results = await dateQuery.find()
    const data = results.map(item => {
    const { date, content, completed } = item.attributes

    return {
    id: item.id,
    date,
    content,
    completed
    }
    })

    ctx.body = { code: 0, message: 'success', data }
    } catch (error) {
    ctx.body = { code: -1, message: error.rawMessage, error }
    }
    })

    // 更新
    router.post('/update', async (ctx, next) => {
    const { id, content, date, completed } = ctx.request.body
    const todo = AV.Object.createWithoutData('TodoModel', id)

    todo.set('content', content)
    todo.set('completed', completed === 'true')
    todo.set('date', date)

    try {
    await todo.save()
    ctx.body = { code: 0, message: 'success' }
    } catch (error) {
    ctx.body = { code: -1, message: error.rawMessage, error }
    }
    })

    module.exports = router

    好了,代码都有了,最后一步就是将我们的代码部署到vps上了

    如果大家有国内的云主机是最好的,响应速度最快,我的vps本来是用来搭ssFQ的,机房在美国,所以使用起来响应会很慢。

    部署项目主要做这么几件事情:

    1. 安装nginx
    2. 上传前端静态资源,交给nginx托管
    3. 配置nginx反向代理,将前端发出的异步请求代理到node service端口
    4. 安装Node
    5. 安装pm2
    6. 运行node service

    下面以安装Node过程举例说明一下,nginx同理,具体可以看这里

    1. 登陆你的云主机

    下载Node最新版,这里提醒一下,先用uname看一下机器的架构,是x86还是x64的,下载对应的32位或者64位binary包,不然是运行不起来的。如果还是不放心,你也可以下载源码包,手动编译

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    cd ~
    mkdir packages
    cd packages
    wget https://nodejs.org/dist/v9.5.0/node-v9.5.0-linux-x64.tar.xz
    tar xvf node-v9.5.0-linux-x64.tar.xz
    cd node-v9.5.0-linux-x64
    cd bin
    ./node -v

    // v9.5.0 // 看到这行就安装成功了
    1. 把bin目录添加到PATH

    修改~/.bashrc, 添加以下内容:

    1
    export PATH=~/packages/node-v9.5.0-linux-x64/bin:$PATH

    保存并退出,执行 source ~/.bashrc 让配置生效,然后试一下npm -v,成功说明配置生效了

    1. 安装pm2
    1
    npm install -g pm2
    1. 把代码从github down下来,然后运行 pm2 start app.js

    最后,用ip访问试一下,能看到页面的话就大功告成~

     
     
     
  • 相关阅读:
    团队冲刺阶段二第五次站立会议
    团队冲刺阶段二第四次站立会议
    团队冲刺阶段二第三次站立会议
    团队冲刺阶段二第二次站立会议
    团队冲刺阶段二第一次站立会议
    第一冲刺阶段总结报告
    团队冲刺阶段一第九次站立会议
    团队冲刺阶段一第八次站立会议
    团队冲刺阶段一第七次站立会议
    团队冲刺阶段一第六次站立会议
  • 原文地址:https://www.cnblogs.com/guochongbin/p/10715429.html
Copyright © 2020-2023  润新知