react-imvc 是 Isomorphic(同构) mvc 的 react 实现,它是一个 Web 框架。通过 react-imvc,我们可以更便利地实现同构 Web 应用的开发
作为同构应用,它可以
react-imvc 里的 MVC 三个部分都是 Isomorphic
的,所以它可以做到:只编写一份代码,在 Node.js
里做 Server-Side-Rendering
服务端渲染,在 Browser
里做 Client-Side-Rendering
客户端渲染。
npm install --save react react-dom@16.8.0 react-imvc@16.8.0
在 package.json 中添加启动命令
{
"scripts": {
"start": "react-imvc start"
}
}
react-imvc项目文件的基本结构为
project
├─ imvc.config.js
└─ src
├─ index.js
└─ page
└─ Todo
├─ Controller.js
├─ Model.js
└─ View.js
src
目录下的 index.js
即为路由入口,每个page为一个文件夹
// index.js
export default [
{
path: '/',
controller: () => import('./page/Todo/Controller')
}
]
对于每个page而言,View
是可选的,当页面视图结构较为简单时,可以将 View 写在 Controller 里,同时,当 View
的结构比较复杂,包含多个子组件(可以是React组件)时,也可以使用多个 js/jsx
对 View
进行拆分
└─Todo
├─ Controller.js
├─ Model.js
└─ View
├─ Footer.jsx
├─ Header.jsx
├─ index.jsx
├─ List.jsx
└─ Todo.jsx
在 index.jsx
中向Controller进行暴露
// index.jsx
import React from 'react'
import Header from './Header'
import List from './List'
import Footer from './Footer'
export default function View() {
return (
<div>
<Header></Header>
<List></List>
<Footer></Footer>
</div>
)
}
每个page的 Model.js
对该页面中的数据进行状态管理,定义页面的初始状态 initialState
和改变状态的函数 actions
,state 在创建后后存储在 controller.store
下,通过 relite 进行管理。在 action 中,state 应当是不可变数据,action 是不包含副作用的纯函数。
// Model.js
export const initialState = {
todos: [
{ id: 1, text: 'sleeping', done: true },
{ id: 2, text: 'eating', done: true },
{ id: 3, text: 'coding', done: false }
]
}
export const ADD_TODO = (state, todo) => {
const newTodos = [todo, ...state.todos]
return {
...state,
todos: newTodos
}
}
Model.js
也是可选的
在 Controller.js
中,引入 Model 和 View
// Controller.js
import Controller from 'react-imvc/controller'
import * as Model from './Model'
import View from './View'
export default class Todo extends Controller {
View = View
Model = Model
}
在 Controller 中还具有一些生命周期方法
使用 componentDidFirstMount
可以在页面创建时读取 localstorage 使用本地存储
// Controller.js
componentDidFirstMount() {
const localData = localStorage.getItem('react-imvc-todo')
const todos = (localData && JSON.parse(localData)) || []
this.store.actions.INITIAL_TODOS(todos)
this.store.subscribe((data) => {
localStorage.setItem('react-imvc-todo', JSON.stringify(data.currentState.todos))
})
}