JSX похож на смесь XML и HTML. Вы используете JSX в коде React, чтобы легко создавать компоненты для своих приложений. JSX превращается в JavaScript, когда React компилирует код.
Прелесть React в том, что вы можете создавать повторно используемый код и легко структурировать свое приложение на основе мышления компонентов. Наконец, разрыв между макетированием каркасов семантически сформированных идей и их реализацией никогда не был ближе.
Ваш первый вкус JSX
Вот пример использования JSX для рендеринга HTML:
js var div = <div className="foo" />; ReactDOM.render(div, document.getElementById('example'));
Чтобы создать компонент, просто используйте локальную переменную, которая начинается с заглавной буквы , например:
« `js var MyComponent = React.createClass ({/ … /}); var myElement = <MyComponent someProperty = {true} />;
ReactDOM.render (myElement, document.getElementById (‘пример’)); « `
Примечание. В JSX есть зарезервированные слова, поскольку в конце концов это по сути JavaScript, поэтому такие ключевые слова, как class
и for
не рекомендуется использовать в качестве имен атрибутов. Вместо этого компоненты React ожидают имена свойств React, например, такие как className
и htmlFor
.
Вложенные теги
Укажите детей внутри вашего JSX следующим образом:
« `js var Пользователь, Профиль;
// Вы пишете в JSX: var app =
// Что будет выводиться в JS: var app = React.createElement (User, {className: ”vip-user”}, React.createElement (Profile, null, “click”)); « `
Тестирование JSX
Используйте Babel REPL, чтобы проверить JSX.
Подкомпоненты и пространства имен
Создать форму легко с помощью JSX и его подкомпонентов, например:
« `js var Form = FormComponent;
var App = (
); « `
Чтобы это работало, вы должны создать подкомпоненты как атрибуты основного компонента:
« `js var FormComponent = React.createClass ({…});
FormComponent.Row = React.createClass ({…}); FormComponent.Label = React.createClass ({…}); FormComponent.Input = React.createClass ({…}); « `
Выражения
Чтобы использовать JavaScript для создания результата для использования в значении атрибута, React просто нужно, чтобы вы завернули его в {}
фигурные скобки следующим образом:
« `js // Вы пишете в JSX: var myUser = <User username = {window.signedIn? window.username: »} />;
// станет в JS: var myUser = React.createElement (Пользователь, {username: window.signedIn? Window.username: »}); « `
Вы также можете просто передать логическое значение для атрибутов формы, таких как disabled
, checked
и т. Д. Эти значения также могут быть жестко запрограммированы, если хотите, просто написав простой HTML.
« `js // Сделать поле обязательным ; <input type = ”text” name = ”username” required = {true} />;
// Проверяем по умолчанию <input type = ”checkbox” name = ”RememberMe” value = ”true” checked = {true} />;
// Включить поле <input type = ”text” name = ”captcha” disabled = {false} /> « `
Атрибуты спреда
Если вы хотите установить несколько атрибутов, убедитесь, что вы делаете это при объявлении вашего компонента, а не после. Последующее объявление становится опасным анти-шаблоном, что означает, что вы, возможно, не сможете получить данные свойства намного позже при выполнении.
Добавьте несколько свойств к вашему компоненту, используя новый оператор распространения ES6.
js var props = {}; props.username = username; props.email = email; var userLogin = <userLogin {...props} />;
Вы можете использовать эти переменные пропа несколько раз. Если вам нужно переопределить одно из свойств, это можно сделать, добавив его к компоненту после оператора ...
spread, например:
js var props = { username: 'jimmyRiddle' }; var userLogin = <userLogin {...props} username={'mickeyFinn'} />; console.log(component.props.username); // 'mickeyFinn'
Комментарии в JSX
Вы можете использовать как многострочные комментарии //
и /* ... */
внутри вашего JSX. Например:
« `js var components = (
); « `
Распространенные ошибки с JSX
Есть несколько вещей, которые могут запутать некоторых людей с помощью JSX, например, при добавлении атрибутов к собственным элементам HTML, которых нет в спецификации HTML.
React не будет отображать атрибуты для собственных элементов HTML, которых нет в спецификации, если вы не добавите префикс data-
следующим образом:
« « HTML
« `
Кроме того, рендеринг HTML в динамическом контенте может сбить с толку из-за экранирования и встроенной React защиты XSS. По этой причине React предоставляет dangerouslySetInnerHTML
.
js <div dangerouslySetInnerHTML={{__html: 'Top level » Child'}} />
Пример чата
Возможно, вы видели приложение Gitter . Это приложение для онлайн-чата, предназначенное в основном для разработчиков. Многие люди используют его для обсуждения своих проектов на GitHub, благодаря его простой интеграции с GitHub и возможности создания канала для вашего хранилища.
Приложение такого типа может быть легко создано с помощью React путем реализации API WebRTC
для создания чата p2p в браузере. Для этого мы будем использовать модули PeerJs
и socket.io
для Node.
Чтобы дать вам четкое представление об архитектуре приложения, вот базовая низкоуровневая диаграмма UML:
ChatServer получает сигнальные сообщения с PeerJS, и каждый клиент будет использовать его в качестве прокси для обеспечения прохождения NAT.
Мы запустим приложение с нуля, чтобы дать вам хорошее представление о том, как создать приложение React. Сначала создайте новый каталог для вашего приложения, а внутри него создайте package.json
.
json { "name": "react-webrtc-chat", "version": "0.0.0", "description": "React WebRTC chat with Socket.io, BootStrap and PeerJS", "main": "app.js", "scripts": { "start-app": "node app.js", "start": "npm run start-app" }, "keywords": [ "webrtc", "react" ], "license": "MIT", "dependencies": { "express": "~4.13.3", "peer": "~0.2.8", "react": "~0.12.2", "react-dom": "^0.14.1", "socket.io": "~1.0.6" }, "devDependencies": { "babel-preset-react": "^6.0.14", "babelify": "^7.1.0", "browserify": "^12.0.1" } }
Этот файл package.json
используется npm
для простой настройки вашего приложения. Мы указываем наши зависимости: express
, веб-фреймворк, который мы будем использовать для обслуживания нашего приложения; peer
, сервер peerjs, который мы будем использовать для сигнализации; socket.io
который будет использоваться для опроса и реализации webRTC. react-bootstrap
и bootstrap
— пакеты для использования CSS-фреймворка Twitter для стилизации нашего приложения.
Нам также понадобятся дополнительные пакеты, и для этого мы будем использовать bower
.
Создайте bower.json
и добавьте следующее:
json { "name": "react-webrtc-chat", "main": "app.js", "version": "0.0.0", "ignore": [ "**/.*", "node_modules", "bower_components", "public/lib", "test", "tests" ], "dependencies": { "react": "~0.12.2", "jquery": "~2.1.4", "eventEmitter": "~4.2.7", "peerjs": "~0.3.14", "bootstrap": "~3.3.5" } }
В этой конфигурации мы eventEmitter
react
, jQuery
, bootstrap
, eventEmitter
для eventEmitter
событий и клиентскую библиотеку peerJS
для переноса WebRTC.
Наконец, укажите, где это установить, установив файл .bowerrc
:
json { "directory": "src/lib" }
Отсюда, просто сидеть сложа руки и установить свои зависимости с помощью:
bash $ bower install && npm install
После выполнения этой команды вы увидите новый каталог node_modules
и src/lib
. Они содержат модули, готовые к использованию.
Теперь создайте app.js
в главном каталоге вместе с package.json
и т. Д. Это будет основной точкой входа вашего приложения.
« `js // Настройка наших сервисов var express = require (‘express’), PeerServer = require (‘peer’). PeerServer, events = require (‘./ src / Events.js’), app = express () , port = process.env.PORT || 3001;
// Сообщаем экспрессу использовать каталог ‘src’ app.use (express.static (__dirname + ‘/ src’));
// Настройка http-сервера и PeerJS-сервера var expressServer = app.listen (port); var io = require (‘socket.io’). listen (expressServer); var peer = новый PeerServer ({порт: 9000, путь: ‘/ chat’});
// Вывести на печать некоторые данные консоли console.log (‘#### — Сервер работает — ####’); console.log («Прослушивание порта», порт);
peer.on (‘connection’, function (id) {io.emit (events.CONNECT, id); console.log (‘# Connected’, id);});
peer.on (‘отключить’, функция (id) {io.emit (events.DISCONNECT, id); console.log (‘# Disconnected’, id);}); « `
Это просто создаст сервер Express, сделав src/
файлы, которые мы только что получили с bower
теперь доступными через HTTP. Затем был socket.io
экземпляр socket.io
для прослушивания объекта expressServer
. Это используется для опроса и облегчения следующего шага для PeerServer
, который на самом деле выполняет часть чата WebRTC.
Чтобы настроить PeerServer
, все, что вам нужно сделать, это указать port
и path
на котором будет работать сервер, а затем начать настройку событий с .on
метода .on
. Мы используем отдельный файл с именем Events.js
чтобы указать события нашего приложения.
js peer.on('connection', function (id) { io.emit(events.CONNECT, id); console.log('# Connected', id); });
Здесь мы используем событие events.CONNECT
чтобы указать, когда пользователь подключился к нашему приложению. Это будет использоваться состояниями наших компонентов представления для обновления их дисплеев в режиме реального времени.
Для этого нам нужно создать Сервер для наших одноранговых соединений через прокси.
Создайте файл в src/Server.js
и добавьте следующее:
« `js / * global EventEmitter, events, io, Peer * / ‘use strict’;
function ChatServer () {EventEmitter.call (this); this._peers = {}; }
ChatServer.prototype = Object.create (EventEmitter.prototype);
ChatServer.prototype.onMessage = function (cb) {this.addListener (events.MSG, cb); };
ChatServer.prototype.getUsername = function () {вернуть this._username; };
ChatServer.prototype.setUsername = function (username) {this._username = username; };
ChatServer.prototype.onUserConnected = function (cb) {this.addListener (events.CONNECT, cb); };
ChatServer.prototype.onUserDisconnected = function (cb) {this.addListener (events.DISCONNECT, cb); };
ChatServer.prototype.send = function (пользователь, сообщение) {this._peers [пользователь] .send (сообщение); };
ChatServer.prototype.broadcast = function (msg) {for (var peer in this._peers) {this.send (peer, msg); }};
ChatServer.prototype.connect = function (имя пользователя) {var self = this; this.setUsername (имя пользователя); this.socket = io (); this.socket.on (‘connect’, function () {self.socket.on (events.CONNECT, function (userId) {if (userId === self.getUsername ()) {return;} self._connectTo (userId ); self.emit (events.CONNECT, userId); console.log (‘Пользователь подключен’, userId);}); self.socket.on (events.DISCONNECT, function (userId) {if (userId === self .getUsername ()) {return;} self._disconnectFrom (userId); self.emit (events.DISCONNECT, userId); console.log (‘Пользователь отключен’, userId);});}); console.log («Соединение с именем пользователя», имя пользователя); this.peer = new Peer (имя пользователя, {host: location.hostname, порт: 9000, путь: ‘/ chat’}); this.peer.on (‘open’, function (userId) {self.setUsername (userId);}); this.peer.on (‘connection’, function (conn) {self._registerPeer (conn.peer, conn); self.emit (events.CONNECT, conn.peer);}); };
ChatServer.prototype._connectTo = function (имя пользователя) {var conn = this.peer.connect (имя пользователя); conn.on (‘open’, function () {this._registerPeer (имя пользователя, conn);} .bind (this)); };
ChatServer.prototype._registerPeer = function (имя пользователя, conn) {console.log (‘Регистрация’, имя пользователя); this._peers [имя пользователя] = conn; conn.on (‘data’, function (msg) {console.log (‘Message Receive’, msg); this.emit (events.MSG, {content: msg, author: username});} .bind (this) ); };
ChatServer.prototype._disconnectFrom = function (имя пользователя) {удалить this._peers [имя пользователя]; }; « `
Это основные внутренности приложения. Здесь мы настраиваем объект ChatServer
со всеми его функциями.
Сначала мы используем socket.io
чтобы установить сигнализацию нового пользователя, подключенного через events.CONNECT
следующим образом:
js ChatServer.prototype.connect = function (username) { var self = this; this.setUsername(username); this.socket = io(); this.socket.on('connect', function () { self.socket.on(events.CONNECT, function (userId) { if (userId === self.getUsername()) { return; } self._connectTo(userId); self.emit(events.CONNECT, userId); console.log('User connected', userId); });
Затем, чтобы подключиться к PeerServer, мы используем следующее:
js this.peer = new Peer(username, { host: location.hostname, port: 9000, path: '/chat' });
Затем мы прослушиваем события с помощью метода on
:
js this.peer.on('open', function (userId) { self.setUsername(userId); }); this.peer.on('connection', function (conn) { self._registerPeer(conn.peer, conn); self.emit(events.CONNECT, conn.peer); });
У нас также есть наши внутренние компоненты JSX в каталоге components/chat
. Не торопитесь, чтобы просмотреть все из них в хранилище. Сейчас я сосредоточусь на компоненте ChatBox
:
« `js / ** @jsx React.DOM * /
«использовать строгое»;
var ChatBox = React.createClass ({
getInitialState: function () {return {users: []}; },
componentDidMount: function () {this.chatProxy = this.props.chatProxy; this.chatProxy.connect (this.props.username); this.chatProxy.onMessage (this.addMessage.bind (это)); this.chatProxy.onUserConnected (this.userConnected.bind (это)); this.chatProxy.onUserDisconnected (this.userDisconnected.bind (это)); },
userConnected: function (user) {var users = this.state.users; users.push (пользователь); this.setState ({users: users}); },
userDisconnected: function (user) {var users = this.state.users; users.splice (users.indexOf (user), 1); this.setState ({users: users}); },
messageHandler: function (message) {message = this.refs.messageInput.getDOMNode (). value; this.addMessage ({content: message, автор: this.chatProxy.getUsername ()}); this.chatProxy.broadcast (сообщение); },
addMessage: function (message) {if (message) {message.date = new Date (); this.refs.messagesList.addMessage (сообщение); }},
render: function () {return (<div className = «chat-box» ref = «root»> <div className = «chat-header ui-widget-header»> React p2p Web RTC Chat </ div> <div className = «строка-chat-content-wrapper»> <UsersList users = {this.state.users} username = {this.props.username} ref = ”usersList”> </ UsersList>
</ div> <MessageInput ref = ”messageInput” messageHandler = {this.messageHandler}> </ MessageInput> </ div>); }}); « `
Этот класс использует ChatServer
мы создали ранее, используя его в качестве прокси для компонента ChatBox
.
Наконец, все компоненты и библиотеки отображаются на странице с помощью index.html
и index.html
помощью узла express.
Чтобы запустить приложение, запустите npm start
и в браузере укажите http://localhost:3001
чтобы взглянуть на чат.
Вживую на Heroku
С Heroku обслуживать из облака очень просто. Зарегистрируйте бесплатную учетную запись, и тогда вы сможете установить heroku
инструмент heroku в свою систему. Узнайте больше о настройке Heroku в Центре разработки Heroku .
Теперь, когда у вас есть Heroku
, войдите в систему и создайте новый проект следующим образом:
bash $ git clone [email protected]:tomtom87/react-p2p-chat.git $ cd react-p2p-chat $ heroku create Creating sharp-rain-871... done, stack is cedar-14 http://sharp-rain-871.herokuapp.com/ | https://git.heroku.com/sharp-rain-871.git Git remote heroku added
Здесь вы получите случайное имя от Heroku и URL своего приложения — в нашем примере это http://sharp-rain-871.herokuapp.com/
. Heroku также создает git-репо для этого приложения.
Теперь это так же просто, как подтолкнуть ваш код к героку:
bash $ git push heroku master
Как только загрузка будет завершена, вы сможете запустить свой веб-сервис следующим образом:
bash $ heroku ps:scale web=1
Теперь просто перейдите по указанному URL-адресу или в качестве ярлыка используйте команду open
следующим образом:
bash $ heroku open
Выводы
Вы узнали, как создавать компоненты JSX и связывать их с React, с подробным примером приложения чата. Потратьте некоторое время, чтобы просмотреть код и посмотреть, как работают React и каталог components/chat
.
В сочетании с развертыванием в Heroku
вы можете приступить к взлому и созданию собственных приложений React
для облака!