---
github: [maka.js](https://github.com/makajs/maka)
留下您宝贵的STAR!谢谢
---


# maka

-  maka源于中文码咖,意为写代码的大咖
- 一眼即可看懂的前端框架,简约而不简单


## 1、安装

``` bash
sudo npm i -g @makajs/cli
```

依赖项:
- npm 
- yarn
``` bash
sudo npm i -g yarn
```

## 2、快速上手

``` bash
maka app helloworld
cd helloworld
yarn start
```
*创建一个名叫helloworld的应用,并且运行起来*


## 3、入门概念

### 3.1、State

``` js
const state = {
    data: {
        content: \'hello \',
        input: \'\'
    }
}
```

- state很简单,可以理解为是应用的数据部分
- 引擎内部状态的存储结构是immutable类型
- 每次状态变化会通知view,重新render


### 3.2、Action

``` js
@actionMixin(\' \')
class action {
    constructor(option) {
        .assign(this, option.mixins)
    }

    = (e) => {
        this. .setState({ \'data.input\': e.target.value })
        console.log(this. .getState(\'data.input\'))
    }
}
```

- action很简单,可以理解为是一些提供给ui调用的函数
- actionMixin,混入外部action,默认混入了maka引擎
- 详细参见后面高级概念


### 3.3、View

``` js
const view = {
    component: \'div\',
    className: \'hello\',
    children: [{
        component: \'div\',
        children: \'{{data.content + data.input}}\'
    }, {
        component: \'input\',
        placeholder: \'world\',
        value: \'{{data.input}}\',
        : \'{{$ }}\'
    }]
}
```

- view很简单,可以理解为react的json化表示
- component是react组件名
- 详细参见后面高级概念

## 4、高级概念

### 4.1、表达式
*view的所有属性值支持表达式语法*

*表达式可以支持js语法,见下面示例*

- 绑定state中path为data.content的数据
```js
{
    ...
    value: `{{data.content}}`  //value = state.data.content
    ...
}
```

- 绑定action中方法名为 的函数
```js
{
    ...
    :`{{$ }}` // = action.$
    ...
}

```

- 函数体
```js
{
    : `{{{
        debugger;
        return $
    }}}`

    /* 
    = new Function(`
        debugger;
        return action.
    `)() 
    */
}
```

### 4.2、view节有哪些系统属性?


```
{
    component: \'div\',
    children: \'hello\',
    _visible: \'true\'
}
```

 这里说的系统属性就是上面例子中的component、children、_visible等;
 除系统属性外还可以设置控件支持的任何属性;
 主要支持下面描述的几种系统属性;

- component
组件名,缺省可使用所有html元素
```
{ component: \'div\' } //<div></div>
```
- children
子组件
```
{
    component: \'div\'
    children: {
        component: \'div\',
        children: \'children\'
    }
}

/*
<div>
    <div>chidlren</div>
</div>
*/
```

- _visible
是否显示,值支持表达式, 默认true

```
{
    component: \'div\',
    _visible: false
}

```
*_visible设置为false,将不创建该组件*

- _for
循环,支持for嵌套

```
const state = {
    data: {
        list: [{a:1}, {a:2}, {a:3}]
    }
}

const view = {
    component: \'div\',
    children: {
        _for: \'item in data.list\', // or (item,index) in data.list
        component: \'div\',
        children: \'{{item.a}}\'
    }
}
```

- _function
函数,当组件的某个属性要求是一个函数并返回react 元素时使用它

```

import {registerComponent} from \'maka\'

class CustomComponent extends React.PureComponent {
    render(){
        var {getSub}  = this.props
        return (
            <div>
                {getSub(\'aaa\',\'bbb\')}
            </div>
        )
    }
}

registerComponent(\'CustomComponent\', CustomComponent)

const view = {
    component: \'div\',
    children: {
        component: \'CustomComponet\'
        getSub: {
            _function: \'(a,b)\',
            component: \'div\',
            children: \'{{a+b}}\'
        }
    }
}

```

### 4.3、如何使用自定义组件?

*view可以使用自定义组件或者外部的react组件,见下面示例*

```
import React from \'react\'
import { registerComponent } from \'maka\'
import { Button } from \'antd\'

class CustomComponent extends React.PureComponent {
    render() {
        return (<div>custom component</div>)
    }
}

registerComponent(\'CustomComponent\', CustomComponent)
registerComponent(\'antd.Button\', Button)

const view = {
    component: \'div\',
    children: [{
        component: \'CustomComponent\'
    },{
        component: \'antd.Button\',
        children: \'Button\'
    }]
}
```


### 4.4、如何自定义模板组件?
*模板组件是为了减少view json的代码量提出的概念,把相似度很高、并且经常使用的一些json定义为模板组件,在使用中能有效减少代码量,见下面示例*

```
import { registerTemplate } from \'maka\'

const CustomTemplate = function(props) {
    return {
        component: \'div\',
        children: [{
                component: \'div\',
                children: props.content
            },{
                component: \'div\',
                children: props.content
            }
        ]
    }
}

registerTemplate( \'CustomTemplate\', customTemplate)

const view = {
    component: \'CustomTemplate\',
    content: \'hello\'
}

```


### 4.5、ActionMixin

*ActionMixin提供了低耦合方式混入外部行为的可能,缺省并至少需要混入了Maka框架的 行为*


- maka引擎混入的 提供了哪些可用行为?

方法名 | 描述 | action中使用示例 | view中使用示例
--- | -- | --- | ---
getState  | 获取状态 | this. .getState(\'data.input\') | $ .getState(\'data.input\')
setState  | 设置状态 | this. .setState({\'data.input\', \'hello\'}) | $ .setState({\'data.input\', \'hello\'})
gs | =getState |  this. .gs(\'data.input\') | $ .gs(\'data.input\')
ss | =setState | this. .ss({\'data.input\', \'hello\'}) |$ .ss({\'data.input\', \'hello\'})
context | 上下文,支持get、set方法 | this. .context.get(\'currentUser\') or this. .context.set(\'currentUser\', {name: \'zhang\'}) | $ .context.get(\'currentUser\')

- 如何混入自定义的行为类?

```
import { actionMixin, registerAction } from \'maka\'

class CustomAction {
    alert = () => {
        alert()
    }
}

registerAction(\'CustomAction\', CustomAction)

@actionMixin(\' \', \'CustomAction\')
class action {
    constructor(option) {
        .assign(this, option.mixins)
    }
}

const view = {
    component: \'div\',
    : \'{{$CustomAction.alert}}\'
}
```


## 5、app & hub

### 5.1 app

*把一个大型网站拆分成许多开发模式相同的app,这些app又可以独立运行、调试、分享,通过弱耦合的方式又能组合在一起成为一个网站*

- app来源
  - maka add 命令增加依赖, 会从hub.makajs.org下载依赖,类似yarn add
  - package.json中subAppDir属性指向的目录,目录中如果存在应用代码会被扫描到
  - 手动拷贝app.js 和 app.css到发布目录
  
- 组合使用

```
const view = {
    component: \'div\',
    className: \'hello\',
    children: [{
        component: \'AppLoader\',
        appName: \'app-test\', //app name
        content: \'hello\' //app支持的属性
    }]
}
```

- 手工创建
```
import {createAppElement} from \'maka\'
...
var ele = createAppElement(\'appName\', {content: \'hello\'}) //第一个参数:app name,第二参数:app props
...
```

- 预加载
修改index.html
```
 maka.load([\'appName1\', \'appName2\']).then(()=>{
     ...
 }
```

- navigate切换

```
import {navigate} from \'maka\'

navigate.redirect(\'/appName/\')
```
### 5.2 hub
- maka提供hub.makajs.org网站用于分享开发者开发的应用 
- 您可以通过maka publish分享您的应用,publish前请使用 maka build 、maka build --dev 、maka pkg 构建应用资源

## 6、maka Api

```  
import {registerComponent, registerAction} from \'maka\'
```
*如上registerComponent,reigsterAction是两个api,所有支持的api如下*

api | 参数 |  描述 | 
--- | -- | -- | 
registerComponent | (key, component)  | 注册组件
registerAction | (key, action) | 注册行为
registerTemplate | (key, template) | 注册模板
getComponent | (key) | 通过组件名获取组件
load | [应用名...] | 加载应用
createAppElement | (appName, appProps) | 创建app React Element
setHoc | (hoc) | 设置最外层高阶React Element
fetch | 对象类型,不需要参数  | 提供fetch对象,可以调用后台接口,或者mock
navigate | 对象类型,不需要参数 | 提供navigate对象
render | (appName, targetHtmlElementName) | render

## 7、ajax & mock

### 7.1、ajax
*可以使用maka引擎提供fetch对象实现ajax,示例如下*

*action.js*
```
import {fetch} from \'maka\'

...
fetch.post(\'/v1/login\',{user: \'admin\', password: \'123\'})
...
```

*index.html, 配置fetch对象*
```
    window.main = function (maka) {
        maka.utils.fetch.config({
            mock: false, //默认是true
            token: \'\', 
            after: function (response, url) {
                return response
            }
        })
    }
```

*package.json,配置本地调试的webpack dev server proxy*
```
...
\"server\": {
    \"proxy\": {
        \"/v1/*\": {
            \"target\": \"http://www.***.com:8080/\"
        }
    },
    \"port\": 8000
  }
...
```

### 7.2、使用纯前端mock
*可以使用maka引擎提供fetch对象实现mock,示例如下*

*action.js*
```
import {fetch} from \'maka\'

...
fetch.post(\'/v1/login\',{user: \'admin\', password: \'123\'})
...
```


*mock.js*
```
import { fetch } from \'maka\'

const mockData = fetch.mockData

function initMockData() {
    if (!mockData.users) {
         mockData.users = [{
            id: 1,
            account: 13334445556,
            password: \'c4ca4238a0b923820dcc509a6f75849b\',
            name: \'zlj\'
        }]
    }
}

fetch.mock(\'/v1/login\', (option, headers) => {
    initMockData()
    const user = mockData.users.find(o => o.account == option.account && o.password == option.password)
    if (user) {
        return {
            result: true,
            token: `${user.id},${user.account},${user.password},${user.name ? user.name : \'\'}`,
            value: option
        }
    }
    else {
        return { result: false, error: { message: \'请输入正确的用户名密码(系统内置用户user:13334445556,pwd:1)\' } }
    }
})
```

*index.js*
```
import \'mock.js\'
```

*index.html*
```
window.main = function (maka) {
    maka.utils.fetch.config({
        mock: true
    })
}
```


## 8、类似router的能力

### 8.1、redirect

```
import {navigate} from \'maka\'
navigate.redirect(\'/portal\') //https://www.***.com/#/portal
```

### 8.2、goBack

```
import {navigate} from \'maka\'
...
navigate.redirect(\'/sign-in\') //https://www.***.com/#/sign-in
...
navigate.redirect(\'/portal\') //https://www.***.com/#/portal
...
navigate.goBack() //https://www.***.com/#/sign-in
```

### 8.3、listen 
```
navigate.listen((location.action)=>{
    debugger
    //自定义处理
})
```


## 9、maka cli 命令

*maka cli 支持的所有命令如下*

- maka app

```bash
maka app test 
```
创建一个名为test应用

- maka start
```bash
maka start 
maka start --dev //dev模式启动
```
启动app,可以通过浏览器访问应用的运行结果,http://127.0.0.1:8000

- maka build
```bash
maka build 
maka build --dev //dev模式编译
```
编译应用,会在当前目录build目录下生成编译结果

- maka pkg
```bash
maka pkg
maka pkg --dev //dev模式打包
```
打包应用, 会在当前目录build目录下生成打包结果,打包结果可用于网站直接部署使用

- maka add
```bash
maka add appName
```
增加依赖,增加依赖会修改package.json文件,start或者pkg命令时会把依赖app的编译结果copy当前应用运行目录下

- maka adduser
```bash
maka adduser
```
类似npm adduser功能,成功会在hub.makajs.org创建用户,并登录

- maka publish
```bash
maka publish
```
使用publish命令分享您的app到hub.makajs.org,其他开发人员就可以通过maka add来引用您发布的应用,注意publish前请使用 maka build 、maka build --dev 、maka pkg 构建应用资源


## 10、结束

- 感谢您对maka的关注!

收藏 打印