(翻译)Mantra官方文档

Mantra

事情草案-版本0.2.0

简介

这是一个Mantra草案范例,一个由Kadira竖立的Meteor的运用顺序架构。 它协助开发人员构建可保护的,面向未来的Meteor运用顺序。

版权

The MIT License (MIT)

Copyright (c) 2016 Kadira Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

转载我的翻译也要签名哦~

内容

(这儿有个目次,可我不想写啦,在我的博客中目次会自动天生哦~)

1 概述

Mantra是Meteor的运用顺序架构。 有了Mantra,我们试图完成以下两个主要目的。
1.可保护性
可保护性是与大型团队协作的关键因素。 我们经由过程对我们运用顺序的每一个部份举行单元测试来完成这一点,同时遵照一个规范。 如许很轻易让新手到场团队。
2.未来证实(Future Proof)
JavaScript就像是一个充溢挑选的地皮。 我们对每一个题目有不止一个最好解决方案。 如今很难说什么是最好的解决方案,未来会有什么变化。
Mantra依靠一套将延续很长时候的中心准绳,我们许可其他人依据须要举行变动。

1.1 Mantra里有什么?

  • 它有一个当代的,基于React的UI组件层。

  • 它有一个在你的运用顺序中定义营业逻辑的处所, 我们称之为 行动(action)

  • Mantra本身不供应状况治理,但它许可你运用林林总总的状况治理器,包括Meteor / Tracker,Redux,Rx.js Observable,Promise和险些任何其他的状况治理器。

  • 它有一种经由过程组合容器(containers)将状况(states)和行动(action)集成到UI组件中的要领。

  • 它许可你依靠注入。

  • 它协助你单元测试UI,行动和集成(容器)。

  • 它对目次规划,文件定名和其他内容都有一些规范。

1.2 Mantra不是什么?

  • 它不是一个运用顺序平台,运用顺序平台专注于运用打包,传输,布置等使命。Mantra运用Meteor作为运用顺序平台。

  • 它不是一个榜样,纵然我们有着一样的目次构造。

  • 它不是一个代码天生器,我们可以会有一个代码天生东西(译者注:已有了,详见mantra-cli),但这并非Mantra的中心部份

1.3 Mantra是什么?

  • 它是一套怎样构建Meteor运用顺序的规范。

  • 它还带有一套已被整理过的且被保护着的库,协助你在Meteor上完成Mantra。

1.4 为何要范例?

Mantra是一个运用顺序架构。 会有许多人运用Mantra,包括运用顺序开发人员,东西竖立者,教程作者和项目经理,所以具有一个每一个人都遵照的规范是非常主要的。 这就是为何要范例。

1.5 在你浏览之前

虽然本范例是以一种简朴易懂的语句编写的。 然则,假如你对以下范畴有充足的相识,你读起来可以会觉得流通。

  • ES2015

  • React

  • React Containers

  • Meteor基本(Pub / Sub,Tracker,ReactiveDict等)

请参阅附录A以相识有关上述范畴的更多信息

2 中心组件

以下是Mantra的中心组件及其构造体式格局:

2.1 聚焦客户端

Mantra迥殊注重你的运用顺序的客户端。 Mantra不会将客户端和服务端代码夹杂在一起;相反,它发起代码同享。原因是:

  • 客户端是你应当支付许多勤奋的处所。它是你的代码库中最大的一部份。服务器端代码库相对更轻易构造和治理。

  • 客户端运用顺序将运用schema与服务器交互。客户端运用顺序不该当体贴服务端怎样完成的。
    Mantra不支撑Universal Apps这个看法。它勉励差别的平台差别的运用顺序并在其之间代码同享。一般有一个服务器与几个客户端运用顺序之间交互。

基于上述看法,将客户端和服务端代码夹杂在一起并非一个好主意。
当我们在本范例中进一步议论Mantra时,它将指的是你运用顺序的客户端。

但是,大多数运用顺序将具有服务器端组件。因而,我们还供应一个服务器端的目次规划。有关概况,请参阅附录B。

2.2 ES2015语法和ES2015模块

我们依靠ES2015及其模块的许多新特征,因而,为了运用Mantra,你须要运用Meteor 1.3,它附带了ES2015模块。

2.3 运用React作为UI

我们运用React作为Mantra中的UI(示意)层。
UI组件不该当晓得关于运用顺序的其余部份的任何内容,而且不该当读取或修正运用顺序的状况。 用于衬着UI组件的数据和事宜处置惩罚顺序应经由过程props从容器通报或作为行动(action)从其内部的事宜处置惩罚顺序中通报。 偶然须要在UI组件内运用暂时部分状况,但该状况不该在其本身组件外援用。
在编写UI组件时,你可以将恣意React组件引入顺序,包括

  • 在运用顺序中定义的其他UI组件。

  • 来自NPM的UI组件(如material-ui)。

  • 运用中的任何容器(我们稍后会议论这个题目)。
    还可以导入任何库函数并在UI组件中运用它们。 你可以直接从NPM模块引入,但不能从任何Meteor软件包引入。 这些函数应当是纯函数

这里是一个简朴的UI组件:

import React from 'react';

const PostList = ({posts}) => (
  <div className='postlist'>
    <ul>
      {posts.map(post => (
        <li key={post._id}>
          <a href={`/post/${post._id}`}>{post.title}</a>
        </li>
      ))}
    </ul>
  </div>
);

export default PostList;

2.4 行动(Actions)

行动是你在app中写营业逻辑的处所,它们包括:

  • 考证

  • State 治理

  • 与长途数据源的交互
    一个行动是一个简朴的函数,它的第一个参数是全部运用的Context,其他参数一般来自函数挪用时。

注重: 在行动中,你所做的一切都应是基于运用的Context通报给行动的其他参数。你不能援用任何ES2015的modules 除了库以外。还应防备在行动中运用全局变量。

这是一个行动:

export default{
    create({Meteor,LocalState,FlowRouter},title,content){
        if(!title||!content){
            return LocalState.set('SAVING_ERROR','Title & Content are required!');
        }
    }
    LocalState.set('SAVING_ERROR',null);
    //这里挪用“config/method_stubs”中的一个method
    //这是我们怎样做耽误赔偿
    Meteor.call('posts.create', id, title, content, (err) => {
      if (err) {
        return LocalState.set('SAVING_ERROR', err.message);
      }
    });
    FlowRouter.go(`/post/${id}`);

    clearErrors({LocalState}){
        return     LocalState.set('SAVING_ERROR', null);
    }

};

2.5 状况(state)治理

在app中,我们须要处置惩罚差别品种的状况。我们可以把他们分为两类。

  1. 当地状况 – 历来不会同步到长途服务器的状况(毛病,考证信息,当前的页面)

  2. 长途状况 – 这是一般从长途服务器猎取并与其同步的state。
    我们有差别的解决方案来治理我们app中的states,包括:

  • Meteor/MiniMongo (长途状况)

  • Tracker/ReactiveDict (当地状况)

  • FlowRouter (当地状况)

  • Redux (当地状况)

  • GraphQL (长途状况)

  • Falcor (长途状况)
    这就是JavaScript社区一直在立异的处所。因而,Mantra在涉及到状况治理时是天真的。你可以运用任何你想运用的。

举个例子,你可以在你的运用启动时运用以下状况:

  • Meteor/MiniMongo (长途状况)

  • Tracker/ReactiveDict (当地状况)

  • FlowRouter (当地状况)
    以后你也可以换用其他解决方案。

注重: Mantra在治理状况时有一些强迫划定规矩

  • 一切的状况的写操纵都要在其对应的行动中完成。

  • 你既可以在行动中读取状况也可以在容器中读取状况。

  • 不许可直接在UI 组件中读写状况,UI 组件不该当晓得任何运用顺序中的状况。

下面的链接是一些关于状况的运用例子
Reading from local state – inside a container
Writing into local state – inside an action
Reading from a remote state – inside a container

2.6 容器(Containers)

容器是Mantra的鸠合层,他们实行这些操纵:

  • 运用状况来修正变量,并经由过程props将它们通报到UI组件。

  • 将行动(action)通报到UI组件中。

  • 将运用Context中的项目通报到UI组件中
    容器是一个React component。

容器运用react‐komposer,它支撑差别的数据源,包括 Meteor/Tracker, Promises, Rx.js Observable,和险些一切其他的数据源。

一般情况下,在容器中须要些下面这些函数:

  • composer函数用来从状况治理中猎取数据。

  • mapper函数从依靠注入层猎取数据。
    竖立容器的一些划定规矩:

  • 单个文件中应当只要一个容器,而且这个容器必需是默许引出的(default export)

  • composer函数和mapper函数必需从容器模块引出(exported)

  • composer函数只能运用props通报变量

  • mapper函数必需是纯函数(Pure function)

注重:假如须要通报运用Context给一个组件,请运用mapper函数函数经由过程props通报。

这是一个容器的例子:

import PostList from '../components/postlist.jsx';
import {useDeps, composeWithTracker, composeAll} from 'mantra-core';

export const composer = ({context}, onData) => {
  const {Meteor, Collections} = context();
  if (Meteor.subscribe('posts.list').ready()) {
    const posts = Collections.Posts.find().fetch();
    onData(null, {posts});
  }
};

export default composeAll(
  composeWithTracker(composer),
  useDeps()
)(PostList);

2.7 运用Context

运用Context可用于一切操纵和容器,因而这是运用顺序中同享变量的处所,他们包括:

  • Meteor namespace

  • Meteor Collections

  • 当地状况

  • FlowRouter

  • 其他Meteor包

  • Redux Stores

  • Rest Clients

  • DDP Clients
    这是一个简朴的运用Context的例子:

import * as Collections from '/lib/collections';
import {Meteor} from 'meteor/meteor';
import {FlowRouter} from 'meteor/kadira:flow-router';
import {ReactiveDict} from 'meteor/reactive-dict';
import {Tracker} from 'meteor/tracker';

export default function () {
  return {
    Meteor,
    FlowRouter,
    Collections,
    LocalState: new ReactiveDict(),
    Tracker
  };
}

2.8 依靠注入

Mantra运用依靠注入来断绝运用顺序的差别部份,包括UI组件和行动(actions)。

我们运用一个名为react-simple-di的项目,它在背景运用React Context。 它同时接收运用Context和行动(action)作为依靠。

一旦设置,运用顺序Context会注入到每一个action中,它是action的第一个参数,因而你不须要手动通报运用Context。

运用顺序Context也可以在容器中接见。

2.8.1 设置依靠注入

依靠关联将注入到运用顺序的顶级组件中,一般是一个规划组件,你可以在你的路由中注入,看一下这个例子:

import React from 'react';
export default function (injectDeps) {
  //这是注入部份:
  const MainLayoutCtx = injectDeps(MainLayout);

  // 路由相干代码
  //......
}

2.9 路由和组件挂载(Mounting)

注重:当我们提到组件时,会同时包括容器(containers)和UI组件(UI components)

我们一般运用路由去挂载组件到UI,这可以有多种解决方案(比方Flow RouterReact Router)

路由只是一个东西,它在Mantra中的唯一功用就是将组件挂载到UI上。

看一下运用FlowRouter当作路由的例子:

import React from 'react';
import {FlowRouter} from 'meteor/kadira:flow-router';
import {mount} from 'react-mounter';

import MainLayout from '/client/modules/core/components/main_layout.jsx';
import PostList from '/client/modules/core/containers/postlist';

export default function (injectDeps) {
  const MainLayoutCtx = injectDeps(MainLayout);

  FlowRouter.route('/', {
    name: 'posts.list',
    action() {
      mount(MainLayoutCtx, {
        content: () => (<PostList />)
      });
    }
  });
}

注重:假如你须要依据某些前提重定向(比方用户未被受权),请运用action来替代像FlowRouter的triggersEnter如许的路由选项。 从组件或容器的composer函数挪用action。

2.10 库

每一个运用顺序都有一些有用的功用去完成差别的使命,你也可以经由过程NPM猎取它们。这些库将引出(export)函数。所以,你可以在运用顺序的任何位置援用他们,包括行动,组件和容器。

当在组件库中运用库函数时,它应当是纯函数。

2.11 测试

测试是Mantra的一个中心部份,Mantra协助你测试运用顺序的每一个部份。我们强迫实行这些划定规矩有助于你编写测试顺序。你可以运用熟习的东西,如MochaChaiSinon来举行测试。

运用Mantra,你可以在运用顺序中单元测试以下三个中心部份:

2.11.1 UI测试

我们运用enzyme为UI举行测试,点击这里看一些简朴的测试用例。

2.12 Mantra 模块

Mantra遵照模块化架构。 除了“运用顺序Context”以外,Mantra的一切组件都应驻留在模块中。

你可以竖立许多许多的模块,并经由过程imports使它们竖立联络。

2.12.1 运用顺序Context和模块的关联

运用顺序Context是运用顺序的中心。 它须要在不属于任何模块的处所定义。 一切模块可以作为依靠关联接见运用顺序Context,模块不该更新运用顺序Context。

2.12.2 模块的定义

Mantra模块可以包括定义它的主文件文件。 它暴露行动,路由和接收context的函数。 一般是 index.js 文件。

一个简朴的模块定义像如许:

export default {
  // 可选的
  load(context, actions) {
    // 做一些模块的初始化事情
  },
  // 可选的
  actions: {
    myNamespace: {
      doSomething: (context, arg1) => {}
    }
  },
  // 可选的
  routes(injectDeps) {
    const InjectedComp = injectDeps(MyComp);
    // 加载路由并将"被注入的组件"显现在屏幕上。
  }
};
2.12.3 隐式模块

假如一个模块没有任何action和路由,或许不须要任何初始化,那末可以防备运用定义文件。这类隐式模块可以包括以下内容:

  • UI组件

  • 容器

2.12.4 模块容器和UI组件的关联

模块容器和UI组件应可以经由过程ES2015模块引入(imported)。

2.12.5 模块行动

模块可以经由过程定名空间暴露行动。 这些定名空间关于运用顺序是全局的,模块应当保证它们是唯一的。 一个模块可以暴露多个定名空间。

末了,来自每一个模块的一切这些定名空间都被兼并,而且可以在action和容器内接见。

2.12.6 路由

你可以运用恣意的路由库举行路由。假如须要,也可以在多个模块中运用路由定义。

2.12.7 中心模块

Mantra是100%模块化的,运用顺序中应最少有一个模块, 我们称之为中心模块。 它只是一个简朴的模块,但你须要在任何其他模块之前加载它。 这个模块最好放在下面这些处所:

  • 中心路由

  • 运用设置

  • 通用库

  • 通用行动
    和其他特定的运用代码中。

依据运用顺序,有多种体式格局构造模块,详见附录C

2.12.8 子模块

在一个模块中,不能 包括子模块。这是为防备不必要的复杂性而做出的决议。 不然,编写多层嵌套模块是会很难治理。

2.13 单一进口

运用Mantra,我们愿望我们的运用是可与展望的。因而,你的运用只能有一个进口点,它就是client/main.js

它将初始化运用顺序Context并加载运用顺序中的一切模块。 这里有一个client / main.js文件示例:

import {createApp} from 'mantra-core';
import {initContext} from './configs/context';

// 模块
import coreModule from './modules/core';
import commentsModule from './modules/comments';

// 初始化 context
const context = initContext();

// 竖立 app
const app = createApp(context);
app.loadModule(coreModule);
app.loadModule(commentsModule);
app.init();

3 目次规划

在Mantra中,我们强迫运用一个大众目次构造。 这是任何运用顺序的可保护性的中心部份。

在本节中,我们只议论客户端目次规划。 要相识怎样构造服务器端目次规划,请参阅附录B。

3.1 顶层目次构造

一切与Mantra相干的代码都保留在运用顺序的client目次中。 在内部,一般有两个目次和一个JavaScript文件。 他们是:

* configs
* modules
* main.js

让我们详细分析下他们中的每一个。

3.1.1 configs

此目次包括运用顺序中的根级别设置。 一般,这是一个安排一切模块通用的运用顺序局限的全局设置的处所。
此目次中的一切JavaScript文件都应运用默许引出函数(default export function),该功用可启动某些使命,并在须要时返回。

注重:我们一般将运用Context安排在这里的context.js中。

3.1.2 modules

此目次包括运用顺序中的一个或多个模块(在本身的目次中)。 这里最少应当有一个模块,它一般被称为core
在modules目次中,一般有这些内容:

* actions
* components
* configs
* containers
* libs
* routes.jsx
* index.js

让我们进修更多关于这个目次下的目次和文件。

3.1.2.1 actions

此目次包括模块中的一切action。 这里有一个目次规划的示例:

* posts.js
* index.js
* tests
    - posts.js

posts.js是一个ES2015模块,它引出具有action的JavaScript对象。 比方,下面是一个简朴的action模块:

export default {
  create({Meteor, LocalState, FlowRouter}, title, content) {
    //...
  },

  clearErrors({LocalState}) {
    //...
  }
};

然后,在index.js中,我们引入一切action模块并聚合一切action。 我们给每一个模块一个定名空间。

import posts from './posts';

export default {
  posts
};

在上面的例子中,我们给posts.js这个action模块一个定名空间posts

注重:这些定名空间在运用顺序中应当是唯一的。 这是模块的义务。

在tests目次中,我们运用action的名称为每一个action模块编写测试。 请参阅附录D以相识有关测试文件定名商定的更多信息。

点击这里检察action的目次规划

3.1.2.2 components

Components包括模块化UI组件。 它的目次规划以下:

* main_layout.jsx
* post.jsx
* style.css
* tests
  - main_layout.js
  - post.js
  • 在这个目次下一切的.jsx文件都必需默许引出。他们必需是一个React类。

  • 你可以编写与这些React组件相干的CSS文件,Meteor将为你绑定它们。
    就像在actions中,这里也有一个tests目次。请参阅附录D以相识有关测试文件定名商定的更多信息。

点击这里检察components的目次规划

3.1.2.3 containers

此目次包括一组.js文件,每一个文件示意一个容器。 每一个文件应当作为React Container类默许引出。

这是一个一般的目次规划:

* post.js
* postlist.js
* tests
    - post.js
    - postlist.js

这个目次下也有一个tests目次。请参阅附录D以相识有关测试文件定名商定的更多信息。
点击这里检察containers的目次规划

3.1.2.4 configs

这个目次包括运用中模块条理的设置。

此目次中的一切JavaScript文件必需引出一个默许函数,该函数可启动任何使命,并在须要时返回一些内容。 该函数可以接收“运用顺序Context”作为第一个参数。

这是一个简朴的config文件:

export default function (context) {
  // do something
}

这些设置可以在加载这个模块时被援用和挪用。

注重:一般,这是我们保留用于乐观更新的Meteor要领存根的处所。

点击这里检察configs的目次规划

3.1.2.5 libs

此目次包括一组有用引出函数的JavaScript文件(.js.jsx)。 这也被称为库。 您可以在tests的子目次中编写库的测试。

3.1.2.6 routes.jsx

这是包括模块的路由定义的文件。 它有一个默许引出,它是一个函数。 下面是一个典范的路由定义:

import React from 'react';
import {FlowRouter} from 'meteor/kadira:flow-router';
import {mount} from 'react-mounter';

import MainLayout from '/client/modules/core/components/main_layout.jsx';
import PostList from '/client/modules/core/containers/postlist';

export default function (injectDeps) {
  const MainLayoutCtx = injectDeps(MainLayout);

  FlowRouter.route('/', {
    name: 'posts.list',
    action() {
      mount(MainLayoutCtx, {
        content: () => (<PostList />)
      });
    }
  });
}

如上所示,在加载模块时,将运用一个名为injectDeps的函数来挪用此默许引出,injectDeps函数可以将依靠项注入到React组件(或容器)中。

3.1.2.7 index.js

这是模块的定义文件(主文件)。假如不须要实行以下使命则不须要此文件:

  • 加载路由

  • 定义action

  • 在加载模块时运转设置
    这是一个典范的模块定义文件:

import methodStubs from './configs/method_stubs';
import actions from './actions';
import routes from './routes.jsx';

export default {
  routes,
  actions,
  load(context) {
    methodStubs(context);
  }
};

在模块定义中,当模块加载时,会挪用.load()要领,所以,这里是挪用设置的处所。

3.1.3main.js

这是Mantra运用顺序的进口点。 它初始化运用顺序Context并加载模块。 因而,它运用一个名为mantra-core的有用顺序库。

这是一个简朴的main.js文件的例子:

import {createApp} from 'mantra-core';
import initContext from './configs/context';

// 模块
import coreModule from './modules/core';
import commentsModule from './modules/comments';

// 初始化 context
const context = initContext();

// 竖立运用(app)
const app = createApp(context);
app.loadModule(coreModule);
app.loadModule(commentsModule);
app.init();

4 未来的事情

Mantra是一个草稿,将有缺失的部份和我们可以做的革新。 我们已肯定以下功用对Mantra很主要,他们将在不久的未来可用。
(懒得翻了 过过再更~)

4.1 Server-Side Rendering (SSR)

It’s extremely possible to do SSR with Mantra. We are trying to do this in a tool‐agnostic manner, but the reference implementation will be based on FlowRouter SSR.

4.2 Distributing Mantra Modules via NPM

We could distribute Mantra modules via NPM. Once we do that, we could do reuse a lot of code between apps and organizations.

4.3 Standard for Styling

It’s better to have a standard for styling UI components.

4.4 Standard for Tests

It’s better to have a standard for writing test cases.

4.5 Reusing Composers

Sometimes, we can use reuse composers for the same function in many places. We need to find a pattern for doing that.

    原文作者:图南Style
    原文地址: https://segmentfault.com/a/1190000007562744
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞