javascript - helmet - Cómo hacer que React y Meteor encajen
react meta tags (3)
No sé si se trata más de un problema de Reacción o Meteoro , tal vez ambos, pero actualmente estoy construyendo una aplicación web con estos dos marcos y estoy enfrentando un problema de programador. No soy un desarrollador de JavaScript, sino un desarrollador de Java (utilizo GWT a diario), así que tal vez cometí algunos errores de novato.
Mi aplicación sigue creciendo y tengo más y más componentes de React, unos veinte más o menos. Ahora que tengo una opinión que está bien, he agregado algunas funcionalidades a mis componentes, pero resulta que agrego más y más lógica en los componentes de reacción, lo que es, creo, en contra de los principios de MVC.
Sin embargo, no sé cómo mover la lógica en "Componentes del controlador de meteoros". En este momento, utilizo Meteor para su modelo y eso es todo. Vi muchas veces esta charla de Pete Hunt y cómo construyó su aplicación, pero solo tiene un componente ''simple''.
De hecho, sin React, la vista estaría en archivos html, definidos con plantillas. El controlador estaría en archivos js y la lógica parecería estar allí. Puedo ver claramente la división entre la vista y el controlador .
Archivo Html (del ejemplo de tabla de clasificación):
<template name="leaderboard">
...
</template>
<template name="player">
<div class="player {{selected}}">
...
</div>
</template>
Archivo Javascript (del ejemplo de la tabla de clasificación):
...
Template.leaderboard.players = function () {
return Players.find({}, {sort: {score: -1, name: 1}});
};
Template.leaderboard.selected_name = function () {
var player = Players.findOne(Session.get("selected_player"));
return player && player.name;
};
...
Dado que React es javascript, es muy fácil y tentador poner todo lo que queremos en los componentes de React.
Soy consciente de que estos marcos son relativamente nuevos para todos, pero me pregunto si existen algunas convenciones sobre cómo diseñar una aplicación MVC de este tipo con el fin de tener una aplicación web flexible y mantenible, ¿cuáles son las pautas a seguir? No estoy buscando la "mejor" manera de hacerlo, sino algunas opiniones.
Nota: deliberadamente no puse una gran cantidad de código aquí para no centrarme en él, pero siéntase libre de ilustrar su respuesta con lo que quiera (código, esquema, enlaces ...).
Aquí hay un ejemplo de lo que estoy haciendo. En este ejemplo, todo se hace en clases de reacción, quizás sea la mejor manera de hacerlo, tal vez no, necesito tus pensamientos.
En resumen, crea una lista de elementos (Boostrap list group) de una matriz dada como entrada (algo como [{name: itemName1, type: itemType1}, {name: itemName2, type: itemType2} ...] que genera una vista como:
- itemName1
- itemName2
- ...
Cada elemento tiene su propio estilo según su tipo. Luego, a través del cuadro de texto de entrada, el usuario puede hacer una búsqueda a través de esta lista, filtra la lista y genera una nueva que se compone con los elementos coincidentes (el algoritmo de búsqueda no es correcto y se cambiará). Además, hay comandos adicionales con cierta tecla del teclado. Todo funciona bien, pero como pueden ver, todo está en clases de reacción, no me imagino cómo encajar Meteor con React.
Archivo Meteor:
if (Meteor.isClient) {
Meteor.startup(function() {
//Build the view
React.renderComponent(
<Search items={initialItems}/>,
document.getElementById(''main'')
);
});
}
Reaccionar archivo:
Search = React.createClass({
getInitialState : function() {
return (
{
items : flat(this.props.items),
active : 0
}
);
},
setListVisibility: function(visibility) {
this.refs.list.getDOMNode().style.visibility = visibility;
},
onchangeHandler: function() {
var re = new RegExp(this.refs.search.getDOMNode().value, "i");
var res = [];
//filter on props.items and not state.items
flat(this.props.items).map(function(item){
if(item.name.search(re) >= 0)
res.push(item);
});
this.setState({ items : res, active : 0});
},
onkeydownHandler: function(event){
if(event.key == "ArrowDown" || event.key == "ArrowUp"){
var shift = event.key == "ArrowDown" ? 1 : -1;
var newActive = this.state.active + shift;
if(newActive >= 0 && newActive < this.state.items.length)
this.setState({ active : this.state.active + shift });
} else if(event.key == "ArrowRight"){
if(this.state.items.length > 0){
var item = this.state.items[this.state.active];
var newItems = retrieveItem(this.props.items, item.name, typeToSubType[item.type]);
newItems = flat(newItems);
if(newItems.length > 0)
this.setState({ items : newItems, active : 0 });
}
} else if(event.key == "ArrowLeft"){
this.setState({ items : flat(this.props.items), active : 0});
} else if(event.key == "Enter"){
if(this.state.items.length > 0){
var item = this.state.items[this.state.active];
console.log("Add "+item.name+" "+item.type+" to the view");
}
}
},
render: function () {
return (
<div>
<nav className="navbar navbar-default" role="navigation">
<div className="container-fluid">
<div className="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<form className="navbar-form navbar-left" role="search">
<div className="form-group">
<input ref="search" type="text" className="form-control" placeholder="Search" size="100"
onChange={this.onchangeHandler}
onKeyDown={this.onkeydownHandler}
onFocus={this.setListVisibility.bind(this, "visible")}
onBlur={this.setListVisibility.bind(this, "hidden")}/>
</div>
</form>
</div>
</div>
</nav>
<List ref="list" items={this.state.items} active={this.state.active}/>
</div>
);
}
});
List = React.createClass({
render: function () {
var createItem = function(item, index) {
var cl = "list-group-item";
if(index == this.props.active)
cl += " active";
var gly = "glyphicon ";
switch(item.type){
case "dimension":
gly += "glyphicon-certificate";
break;
case "hierarchy":
gly += "glyphicon-magnet";
break;
case "level":
gly += "glyphicon-leaf";
break;
case "measure":
gly += "glyphicon-screenshot";
break;
}
return (<a href="#" className={cl} key={item.type+"/"+item.name}>
<span className={gly}></span>{" "}{item.name}
</a>);
};
return (
<div className="list-group search-list">
{this.props.items.map(createItem, this)}
</div>
);
}
});
Hoy podrías considerar esta agradable paz de código: https://github.com/reactjs/react-meteor
Este repositorio define un paquete Meteor que integra automáticamente el marco de representación de React tanto en el cliente como en el servidor, para complementar o reemplazar el sistema de plantillas predeterminado de Handlebars.
Su enfoque es sólido: Meteorito para el modelo y React para View y ViewController.
Cualquier funcionalidad que no tenga nada que ver con la presentación debe estar en el modelo (lógica comercial, reglas de validación, etc.).
Cualquier cosa que tenga que ver con la presentación y responder a la entrada del usuario debe estar en Reaccionar (entrada, salida de validación, etc.).
A partir de Meteor 1.3 hay una forma oficialmente compatible para integrar React with Meteor. Entonces, para cualquier persona que encuentre esta pregunta hoy, aquí está la respuesta Meteor 1.3+:
Para usar Reaccionar como capa de vista de Meteorito, primero agregue los paquetes Reaccionar de npm:
meteor npm install --save react react-dom
Ahora puede simplemente importar Reaccionar y usarlo en su proyecto. Para representar un componente React simple, cree un contenedor HTML simple:
client / main.html
<body>
<div id="app"></div>
</body>
Y renderice su componente Reaccionar en él:
client / main.jsx
import React from ''react'';
import { Meteor } from ''meteor/meteor'';
import { render } from ''react-dom'';
class HelloWorld extends React.Component {
render() {
return <p>Hello World!</p>;
}
}
Meteor.startup(() => {
render(<HelloWorld />, document.getElementById(''app''));
});
Para usar fuentes de datos de Meteor reactivas, como las colecciones Minimongo dentro de los componentes de React, debe usar el paquete react-meteor-data
.
Lea más en la guía oficial Meteor