diff --git a/README-EN.md b/README-EN.md index 19144955..8c1ba190 100644 --- a/README-EN.md +++ b/README-EN.md @@ -1,6 +1,9 @@ ### 中文介绍 请查看 [README.md](https://github.com/chvin/react-tetris/blob/master/README.md) +### Introducción en español +Visite la documentación [README-ES.md](https://github.com/chvin/react-tetris/blob/master/README-ES.md) + ---- ## Use React, Redux, Immutable to code Tetris. diff --git a/README-ES.md b/README-ES.md new file mode 100644 index 00000000..305e0853 --- /dev/null +++ b/README-ES.md @@ -0,0 +1,251 @@ +### 中文介绍 +请查看 [README.md](https://github.com/chvin/react-tetris/blob/master/README.md) + +### English introduction +Please view [README-EN.md](https://github.com/chvin/react-tetris/blob/master/README-EN.md) + +---- +## Usa React, Redux, Immutable para crear Tetris. + +---- +Tetris es un juego clásico que siempre ha sido entusiastamente implementado en varios idiomas. Hay muchas versiones de él en Javascript por ello usar React para hacer Tetris se ha convertido en mi objetivo. + +Abre [https://chvin.github.io/react-tetris/?lan=es](https://chvin.github.io/react-tetris/?lan=es) para jugar! + +---- +### Prevista de la interfaz +![Interface review](https://img.alicdn.com/tps/TB1Ag7CNXXXXXaoXXXXXXXXXXXX-320-483.gif) + +Esta es una velocidad normal de grabación, puedes ver que tiene una experiencia suave. + +### Responsive +![Responsive](https://img.alicdn.com/tps/TB1AdjZNXXXXXcCapXXXXXXXXXX-480-343.gif) + +No solo se refiere a la adaptación de la pantalla, `sino que también depende de la plataforma, el uso del teclado en la PC y el uso del toque en el teléfono como entrada`: + +![phone](https://img.alicdn.com/tps/TB1kvJyOVXXXXbhaFXXXXXXXXXX-320-555.gif) + +### Guardado de datos +![Data persistence](https://img.alicdn.com/tps/TB1EY7cNXXXXXXraXXXXXXXXXXX-320-399.gif) + +La página web se actualiza, el programa se bloquea o el teléfono sé muere, simplemente reabra la conexión y puede continuar jugando. Los datos del estado se almacena en tiempo real en el `localStorage` al llamar el método `store.subscribe`, que registra exactamente todo el estado. + +### Prevista del estado de Redux ([Redux DevTools extension](https://github.com/zalmoxisus/redux-devtools-extension)) +![Redux state preview](https://img.alicdn.com/tps/TB1hGQqNXXXXXX3XFXXXXXXXXXX-640-381.gif) + +Redux maneja todo el estado que debe ser almacenado, lo que garantiza todo lo mencionado antes. + +---- +El juego usa React para ser construído [React](https://facebook.github.io/react/) + [Redux](http://redux.js.org/), together with [Immutable.js](https://facebook.github.io/immutable-js/). + +## 1. Qué es Immutable.js? +Immutable son datos que no pueden ser cambiados una vez que son creados. Cualquier modificación o adición a o eliminación de un objeto Immutable devuelve un nuevo objeto Immutable. + +### Acquaintance: +Echemos un vistazo al siguiente código: +``` JavaScript +function keyLog(touchFn) { + let data = { key: 'value' }; + f(data); + console.log(data.key); // Adivina qué sale de output +} +``` +Si no miramos `f`, y no sabemos lo que hizo a `data`, no podemos confirmar lo que se imprimirá. Pero si `data` es *Immutable*, puedes estar seguro de que `data` no ha cambiado y se imprime `value`: +``` JavaScript +function keyLog(touchFn) { + let data = Immutable.Map({ key: 'value' }); + f(data); + console.log(data.get('key')); // value +} +``` + +JavaScript usa una asignación de referencia, lo que significa que el nuevo objeto simplemente se refiere al objeto original, cambiar el nuevo también afectará al viejo: +``` JavaScript +foo = {a: 1}; bar = foo; bar.a = 2; +foo.a // 2 +``` + +Esto ayuda a reducir malgasto de memória cuando la applicación es compleja, y ayuda a reducir el riesgo de que el estado no sea controlable. Las ventajas de ahorrar memoria, en este caso, se convierten en más daño que beneficio. + +Con Immutable.js esto no sucede: +``` JavaScript +foo = Immutable.Map({ a: 1 }); bar = foo.set('a', 2); +foo.get('a') // 1 +``` + +### Conciso: +En `Redux`, es una buena práctica devolver un nuevo objeto (array) a cada `reducer`, por lo que a menudo vemos código como este: +``` JavaScript +// reducer +... +return [ + ...oldArr.slice(0, 3), + newValue, + ...oldArr.slice(4) +]; +``` +En orden de modificar un elemento en el array y devolver el nuevo objeto (array), el código tiene esta extraña apariencia de arriba, y se vuelve peor a medida que la estructura de datos se vuelve más profunda. +``` JavaScript +// reducer +... +return oldArr.set(4, newValue); +``` +No es más simple? + +### About “===”: +Sabemos que el operador ```===``` para el `Object` y `Array` compara la referencia a la dirección del objeto en lugar de su "comparación de valor", como: +``` JavaScript +{a:1, b:2, c:3} === {a:1, b:2, c:3}; // false +[1, 2, [3, 4]] === [1, 2, [3, 4]]; // false +``` + +Para lograr lo anterior, solo podríamos `deepCopy` y `deepCompare` para recorrer los objetos, pero esto no solo es engorroso, también perjudica el rendimiento. + +Vamos a ver el enfoque de `Immutable.js`! +``` JavaScript +map1 = Immutable.Map({a:1, b:2, c:3}); +map2 = Immutable.Map({a:1, b:2, c:3}); +Immutable.is(map1, map2); // true + +// List1 = Immutable.List([1, 2, Immutable.List[3, 4]]); +List1 = Immutable.fromJS([1, 2, [3, 4]]); +List2 = Immutable.fromJS([1, 2, [3, 4]]); +Immutable.is(List1, List2); // true +``` +Es suave como una brisa que sopla. + +React tiene una ventaja grande cuando se trata de optimización de rendimiento. Usa `shouldComponentUpdate()` para comprobar (como el nombre dice) si el componente debe ser re-renderizado, devuelve `true` por defecto, que siempre ejecuta el método `render()` seguido de la comparación del Virtual DOM. Si devuelve `false`, el componente no se renderiza. + +Si no devolvemos un nuevo objeto al hacer actualizaciones de estado, tendremos que usar `deepCopy` y `deepCompare` para calcular si el nuevo estado es igual al anterior, el consumo del rendimiento no vale la pena. Con Immutable.js, es fácil comparar estructuras profundas usando el método anterior. + +Para Tetris, imagina que el tablero es un `array bidimensional`. El cuadrado que se puede mover es `forma (también un array bidimensional) + coordenadas`. La superposición del tablero y la caja está compuesta por el resultado final de `Matrix`. Las propiedades anteriores están construidas por `Immutable.js`, a través de su método de comparación, puedes escribir fácilmente `shouldComponentUpdate`. Código fuente:[/src/components/matrix/index.js#L35](https://github.com/chvin/react-tetris/blob/master/src/components/matrix/index.js#L35) + +Material de aprendizaje para Immutable.js: +* [Immutable.js](http://facebook.github.io/immutable-js/) +* [Immutable Detallado y React en practica](https://github.com/camsong/blog/issues/3) + + +---- +## 2. Cómo usar Immutable.js en Redux +Meta: `state` -> Immutable. +Plugin importante: [gajus/redux-immutable](https://github.com/gajus/redux-immutable) +Será proporcionado por el combinador de reducers original de Redux proporcionado por el complemento anterior: +``` JavaScript +// rootReducers.js +// import { combineReducers } from 'redux'; // El método original +import { combineReducers } from 'redux-immutable'; // El nuevo método + +import prop1 from './prop1'; +import prop2 from './prop2'; +import prop3 from './prop3'; + +const rootReducer = combineReducers({ + prop1, prop2, prop3, +}); + + +// store.js +// Crea un store y el mismo método general +import { createStore } from 'redux'; +import rootReducer from './reducers'; + +const store = createStore(rootReducer); +export default store; +``` +Por el nuevo `combineReducers` el objeto de la tienda se almacenará como un objeto Immutable.js, el contenedor será ligeramente diferente, pero esto es lo que queremos: +``` JavaScript +const mapStateToProps = (state) => ({ + prop1: state.get('prop1'), + prop2: state.get('prop2'), + prop3: state.get('prop3'), + next: state.get('next'), +}); +export default connect(mapStateToProps)(App); +``` + + +---- +## 3. Web Audio Api + +Hay muchos efectos de sonido diferentes en el juego, pero solo mantenemos una referencia a un archivo de sonido: [/build/music.mp3](https://github.com/chvin/react-tetris/blob/master/build/música.mp3). Con la ayuda de `Web Audio Api`, puede reproducir audio con precisión de milisegundos, con una alta frecuencia, lo que no es posible con la etiqueta `