Socket
Socket
Sign inDemoInstall

hanzojs

Package Overview
Dependencies
551
Maintainers
1
Versions
50
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

    hanzojs

react/react-native + redux


Version published
Weekly downloads
0
decreased by-100%
Maintainers
1
Created
Weekly downloads
 

Readme

Source

hanzojs

  • 借鉴dva.js,在dva.js的基础上去掉以及定制了一些功能,用于redux和react框架的集成,目标是将繁琐的redux开发尽量简化,易于上手
  • 支持react-native,react,以及同构react,一个为实现三端融合开发的基础框架
  • 基于redux,redux-actions,react-navigation等

安装


npm install hanzojs --save

Get Started


  1. 创建一个hanzojs实例
import Hanzo from 'hanzojs/mobile' // for react-native and server-render react
or
import Hanzo from 'hanzojs' // for react pc

const app = new Hanzo()
  1. 注册模块
app.registerModule(require('./modules/a'))
app.registerModule(require('./modules/b'))
...
  1. 添加redux中间件
app.use({
  onAction: [
    promiseMiddleware({
      promiseTypeSuffixes: ['Loading', 'Success', 'Error'],
    }),
    thunkMiddleware,
  ]
})
  1. 配置路由
app.router(require('./routes.js'))
  1. 启动app
app.start() // for react-native and server-render react
or
app.start('#node') // for react pc

API


创建实例

创建一个react-native hanzoApp

import Hanzo from 'hanzojs/mobile' 
const app = new Hanzo()

创建一个react pc hanzoApp

import Hanzo from 'hanzojs' 
const app = new Hanzo()

创建一个react server render hanzoApp

import Hanzo from 'hanzojs/mobile' 
const app = new Hanzo({ isomorphic: true })

APP.USE

app.use接受一个配置对象,目前支持dev(调试模式),onAction(redux中间件),extraReducers(额外的reducer)

Example:
app.use({
  dev: devTools({
    name: Platform.OS,
    hostname: 'localhost',
    port: 5678,
  }),
  onAction: [
    dot,
    Validator(),
    promiseMiddleware({
        promiseTypeSuffixes: ['Loading', 'Success', 'Error'],
    }),
    thunkMiddleware,
  ],
  extraReducers: { ...states },
})

路由配置

hanzojs最新版本的路由采用的是react-navigation,具体使用方式和react-navigation一致,api参见react-navigation,1.x以下版本采用的是react-native-router-flux的路由风格

Example:
import { StackNavigator } from 'hanzojs/router'

module.exports = (modules) => StackNavigator({
    React: {
      path:'react',
      screen: StackNavigator({
        Register: {
          screen: modules.UserRegister,
          path: 'register',
          navigationOptions: {
            title: '欢迎注册链尚网'
          }
        },
        Login: {
          screen: modules.UserLogin,
          path: '',
          navigationOptions: {
            title: '欢迎登陆链尚网'
          }
        }
      })
    }
  })

hanzojs模块结构

一个标准的hanzojs模块结构由views目录,index.js,model.js,action.js组成。其中:

  • views目录存放UI界面
  • model.js存放redux相关的内容
  • action.js存放接口层相关的方法
  • index.js为模块入口文件,主要是connect,暴露出模块给hanzo注册
index.js

负责将整个模块暴露给hanzojs,将view层和reducer,initialState,以及view层所需的调用的方法通过connect绑定到一起。一个稍微复杂的todolist的示例:

import { connect } from 'hanzojs'
import model from './model'

module.exports = {
  models: model,
  views: {
    TodoApp: connect((state) => {
      return {
        ...state.todoApp,
        todos: state.todoApp.todos.filter(todo => {
          if (state.todoApp.filter === VisibilityFilters.ALL) {
            return true;
          } else if (state.todoApp.filter === VisibilityFilters.COMPLETED) {
            return todo.completed;
          } else if (state.todoApp.filter === VisibilityFilters.INCOMPLETE) {
            return !todo.completed;
          }
        })
      }
    }, model)(require('./views/index.js'))
  }
}

module.exports暴露一个JS模块,这个模块包含两个必须的属性,一个是models,一个是views。models一般只接受model.js导出的model就可以了,views接受一个或若干个使用connect处理过的view,键值对存放。

connect接受两个参数,一个是类似redux中常使用的mapStateToProps,一个是model,主要功能类似于mapDispatchToProps

model.js

一个标准的model.js的写法如下:

module.exports = {
  namespace: '',
  state: {
  },
  handlers: [
  ],
  reducers: {
  },
}
  • namespace 命名空间,该模块下所有的redux dispatch出的事件会自动加namespace前缀。reducer接受的事件也会默认加上该namespace前缀。同时,namespace也对应了redux state tree中state所处的部分,支持层级结构,例如:namespace: 'a/b/c'
  • state 相当于redux中的 initialState
  • handlers的底层实现使用的是redux-actions,三种用法:
handlers: [
  'justAString',
  { name: 'handlerName', action: 'handlerActionFromActionJS' },
  { name: 'handlerName2', handler: 'handlerFromAnotherModule' }
]

第一种顾名思义,直接接受一个字符串,将所传入的参数直接dispatch出去

第二种接受一个action属性,代表这个handler具体的实现(例如和后台交互等),具体的实现一般放在action.js

第三种接受一个handler属性,一个字符串,代表跨模块调用其他模块的方法。例如要调用A模块下的b方法,handler直接写'A.b'

  • reducers也是基于redux-actions,由键值对组成。键为事件名称,和handler里的方法名一一对应,值就是一个reducer处理函数。有两点需要注意:
    1. 如果有redux中间件的集成,事件名称和handler名称有可能不见得是一一对应关系。比如引入了redux-promise-middleware中间件,那么事件名称需要在handler名称后面加上相应的异步状态后缀
    2. 如果需要处理一些跨模块的事件或者全局事件,事件需要以 / 作为前缀 一个完整的todolist的model的示例如下:
import _ from 'lodash';
import { VisibilityFilters } from './enums'
import { addTodo } from './action'

module.exports = {
  namespace: 'todoApp',
  state: {
    todos: [],
    filter: VisibilityFilters.ALL,
    addModal: {
      visible: false
    }
  },
  handlers: [
    'showAll',
    'showCompleted',
    'showIncomplete',
    'showModal',
    'hideModal',
    { name: 'addTodo', action: addTodo },
    'completeTodo',
    'incompleteTodo',
  ],
  reducers: {
    showModal: (state, action) => ({
      ...state,
      addModal: {
        visible: true
      }
    }),
    hideModal: (state, action) => ({
      ...state,
      addModal: {
        visible: false
      }
    }),
    showAll: (state, action) => ({
      ...state,
      filter: VisibilityFilters.ALL,
    }),
    showCompleted: (state, action) => ({
      ...state,
      filter: VisibilityFilters.COMPLETED,
    }),
    showIncomplete: (state, action) => ({
      ...state,
      filter: VisibilityFilters.INCOMPLETE,
    }),
    addTodo: (state, action) => ({
      ...state,
      todos: [
        ...state.todos,
        action.payload
      ]
    }),
    completeTodo: (state, action) => {
      var index = _.findIndex(state.todos, (todo) => todo.id === action.payload);
      if (index === -1) {
        return {
          ...state
        }
      }
      return {
        ...state,
        todos:[
          ...state.todos.slice(0, index),
          Object.assign({}, state.todos[index], {
            completed: true
          }),
          ...state.todos.slice(index + 1)
        ]
      };
    },
    incompleteTodo: (state, action) => {
      var index = _.findIndex(state.todos, (todo) => todo.id === action.payload);
      if (index === -1) {
        return {
          ...state
        }
      }
      return {
        ...state,
        todos: [
          ...state.todos.slice(0, index),
          Object.assign({}, state.todos[index], {
            completed: false
          }),
          ...state.todos.slice(index + 1)
        ]
      };
    },
  }
}

DEMO

其他学习

开源许可

基于 MIT License 开源,使用代码只需说明来源,或者引用 license.txt 即可。

FAQs

Last updated on 16 Aug 2017

Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc