2016-04-15 12 views
7

Ich habe vor kurzem ein paar isomporphen/universellen Projekten mit dem React-Redux-Express-Mongoose-Stack gebaut.Datenmodelle und Geschäftslogik in isomorpher (React/Redux/Express/Mongo) App

In meinen Mungo-Modellen steckt viel Business-Logik. Als sehr einfaches Beispiel (entschuldigen Sie meine ES6):

import mongoose, {Schema} from 'mongoose'; 

const UserSchema = new Schema({ 
    name: String, 
    password: String, 
    role: String 
}); 

UserSchema.methods.canDoSomeBusinessLogic = function(){ 
    return this.name === 'Jeff'; 
}; 

UserSchema.methods.isAdmin = function(){ 
    return this.role === 'admin'; 
}; 

Dies alles toll auf dem Server ist jedoch, wenn diese Modelle im Browser als Ebene JSON-Objekte mit Feuchtigkeit versorgt werden, muss ich dann das gleiche Geschäft neu implementieren Logik in einigen React-Komponenten oder Redux Reducer, die sich für mich nicht sehr sauber anfühlen. Ich frage mich, wie ich das am besten angehen kann.

Beim Lesen von Mongoose scheint die Browser-Unterstützung begrenzt zu sein, meistens nur für die Überprüfung von Dokumenten. Ich nehme meine wichtigsten Optionen sind:

  • Verschieben Sie alle Business-Logik in einige „normale“ JS-Klassen und alle über dem Platz instanziiert. Zum Beispiel:

    # JS Class definition - classes/user.js 
    export default class User { 
        constructor(data = {}){ 
         Object.assign(this,data); 
        } 
    
        canDoSomeBusinessLogic(){ 
         return this.name === 'Jeff'; 
        }; 
    
        isAdmin(){ 
         return this.role === 'admin'; 
        } 
    } 
    
    # Server - api/controllers/user.js 
    import UserClass from 
    User.findById(1,function(err,user){ 
        let user = new UserClass(user.toJSON(); 
    }); 
    
    # Client - reducers/User.js 
    export default function authReducer(state = null, action) { 
        switch (action.type) { 
        case GET_USER: 
         return new UserClass(action.response.data); 
        } 
    } 
    
    # Client - containers/Page.jsx 
    import {connect} from 'react-redux'; 
    
    @connect(state => ({user: state.user})) 
    export default class Page extends React.Component { 
        render(){ 
         if(this.props.user.isAdmin()){ 
         // Some admin 
         } 
        } 
    } 
    
  • Verschieben Sie alle Business-Logik in einem einige statische Hilfsfunktionen. Ich werde nicht wieder die ganze Beispiel schreiben, aber im Wesentlichen:

    # helpers/user.js 
    export function isAdmin(user){ 
        return user.role === 'admin'; 
    } 
    

Ich nehme an, den Unterschied zwischen dem obigen 2 ist nur eine persönliche Vorliebe. Aber hat jemand andere Gedanken über isomorphe Apps und Datenmodellierung? Oder ich habe ein Open-Source-Beispiel von Leuten gesehen, die dieses Problem lösen.

Als eine Erweiterung des oben genannten, was ist mit einer isomorphen save() - Funktion, z. User.save(). Wenn es also auf dem Client aufgerufen wird, könnte es einen POST zu dem relevanten API-Endpunkt ausführen, und wenn es auf dem Server ausgeführt würde, würde es die Mongoose-Funktion save() aufrufen.

Antwort

1

Spoiler: Erwarten Sie eine eigenwillige Antwort. Es gibt keinen "richtigen" Weg, es zu tun.

Zunächst einmal möchte ich den difference between isomorphic and universal klar machen, so dass Sie genau wissen, was wir reden:

Isomorphismus ist die funktionale Aspekt nahtlos zwischen client- und serverseitiges Rendering Schalt ohne den Staat zu verlieren. Universal bezeichnet die Tatsache, dass ein bestimmter Teil des JavaScript-Codes in mehreren Umgebungen ausgeführt werden kann.

Lohnt es sich, dass viel Abstraktion in eine universelle App?

Im Allgemeinen möchten Sie eine universelle App für den Client und den Server, die die App vorrendern, beide laden den gleichen Code. Obwohl Sie die API von demselben Server aus ausführen können, auf dem die App vorgerendert wird, würde ich sie eher als Proxy verwenden und in einem anderen Prozess ausführen.

Lassen Sie mich Ihnen zwei verschiedene Reagieren Repositories:

Erikras bekannten vorformulierten seine universelle App nutzt Abhängigkeiten global zu teilen, und Code zwischen dem Server, der die Seite vorreitet, und dem Client. Obwohl er konnte, teilt er die Validierung nicht. Survey API validation

Wellyshen hat keine API, aber er teilt auch seine Abhängigkeiten und Code, obwohl nur zwischen dem Server und dem Client. Die server lädt die Routen, das Geschäft und alles, was von der Client-App ausgeführt wird. Das ist Isomorphie zu liefern.

Wenn Sie das gesagt haben, liegt es an Ihnen, ob Sie alle Validierungen an einem Ort verschieben. Ich würde es wahrscheinlich nur für komplizierte Validierungsfälle in Betracht ziehen, wie eine E-Mail-Validierung, für die Sie tatsächlich einen Helfer haben könnten. (Das war nur ein Beispiel, für die Validierung von E-Mails haben Sie bereits validator). In bestimmten Fällen kann es praktischer sein, sich auf die API-Validierung zu verlassen, auch wenn dies nicht die beste Vorgehensweise ist.

Einfache Validierungen, wie die in Ihren Beispielen, können problemlos mit redux-form durchgeführt werden, die ich weiß, dass es keine direkte Möglichkeit gibt, es auf der API zu übersetzen. Stattdessen sollten Sie wahrscheinlich nach express-validator darauf suchen.

Noch eine Sache, trotz der Tatsache, dass einige sehr populäre React-Boilerplates die API und den Client zusammen haben, tendiere ich dazu, mit zwei verschiedenen Repositories zu arbeiten: dem React + Server-Side-Rendering und der API. Auf lange Sicht wird es zu einem saubereren Code führen, der völlig unabhängig voneinander sein wird. organizing-large-react-applications

Verwandte Themen