JSX类似于XML和HTML的混合。 您可以在React代码中使用JSX轻松为您的应用程序创建组件。 当React编译代码时,JSX转换为JavaScript。
React的优点在于,您可以创建可重用的代码,并可以轻松地从基于组件的思想结构构建应用程序。 最后,模拟语义上形成的想法的线框与实施它们之间的鸿沟从未弥合。
您对JSX的初尝
这是用于渲染HTML的JSX的示例:
var div =
;
ReactDOM.render(div, document.getElementById('example'));
要创建组件,只需使用以大写字母开头的局部变量,例如:
var MyComponent = React.createClass({/*...*/});
var myElement = <MyComponent someProperty={true} />;
ReactDOM.render(myElement, document.getElementById('example'));
注意:JSX中有保留字,因为它毕竟是JavaScript,因此不建议使用class
和for
class
关键字作为属性名。 相反,React组件期望使用React属性名称,例如className
和htmlFor
。
嵌套标签
在JSX中指定子项,如下所示:
var User, Profile;
// You write in JSX:
var app =
click
;
// What will get outputted in JS:
var app = React.createElement(
User,
{className:"vip-user"},
React.createElement(Profile, null, "click")
);
测试JSX
使用Babel REPL测试JSX。
子组件和命名空间
使用JSX和子组件很容易创建表单,例如:
var Form = FormComponent;
var App = (
);
为了使这项工作有效,您必须将子组件创建为主组件的属性:
var FormComponent = React.createClass({ ... });
FormComponent.Row = React.createClass({ ... });
FormComponent.Label = React.createClass({ ... });
FormComponent.Input = React.createClass({ ... });
表达方式
要使用一些JavaScript创建用于属性值的结果,React只需要将其包装在{}
大括号中,如下所示:
// You write in JSX:
var myUser = <User username={window.signedIn ? window.username : ''} />;
// Will become this in JS:
var myUser = React.createElement(
User,
{username: window.signedIn ? window.username : ''}
);
您也可以只为表单属性(例如disabled
, checked
等)传递布尔值。 如果您愿意,只需编写纯HTML,也可以对这些值进行硬编码。
// Make field required;
<input type="text" name="username" required={true} />;
// Check by default
<input type="checkbox" name="rememberMe" value="true" checked={true} />;
// Enable a field
<input type="text" name="captcha" disabled={false} />
传播属性
当您要设置多个属性时,请确保在声明组件时执行此操作,不要再执行此操作。 以后的声明成为一种危险的反模式,这意味着您可能要等到执行得多后才能拥有属性数据。
使用ES6的new ...
spread运算符 ,可以向组件中添加多个属性。
var props = {};
props.username = username;
props.email = email;
var userLogin = <userLogin {...props} />;
您可以多次使用这些prop变量。 如果您需要覆盖其中一个属性,可以通过将其附加到...
扩展运算符之后的组件中来完成,例如:
var props = { username: 'jimmyRiddle' };
var userLogin = <userLogin {...props} username={'mickeyFinn'} />;
console.log(component.props.username); // 'mickeyFinn'
JSX中的评论
您可以在JSX中使用//
和/* ... */
多行样式注释。 例如:
var components = (
{/* child comment, put {} around */}
<User
/* multi
line
comment here */
name={window.isLoggedIn ? window.name : ''} // Here is a end of line comment
/>
);
JSX的常见陷阱
有些事情会使JSX感到困惑,例如,当向HTML规范中不存在的本机HTML元素添加属性时。
除非您添加如下data-
前缀,否则React不会在规范中未包含的本机HTML元素上呈现任何属性:
此外,由于转义和React内置的XSS保护,动态内容中HTML呈现可能会引起混淆。基于这个原因,React提供dangerouslySetInnerHTML
SetInnerHTML。
<div dangerouslySetInnerHTML={{__html: 'Top level » Child'}} />
聊天应用程序示例
您可能已经看到了Gitter应用程序。 这是一个主要针对开发人员的实时Web聊天应用程序。 由于它易于与GitHub集成并且能够为您的存储库创建通道,因此许多人正在使用它在GitHub上讨论他们的项目。
通过实现WebRTC
API在浏览器中创建p2p聊天,可以使用React轻松创建此类应用程序。 为此,我们将对Node使用PeerJs
和socket.io
模块。
为了让您清楚地了解应用程序的体系结构,这是一个基本的低级UML图:
ChatServer通过PeerJS接收信号消息,每个客户端都将其用作代理,以处理NAT遍历。
我们将从头开始启动该应用程序,使您对如何创建React应用程序有一个很好的了解。 首先为您的应用程序创建一个新目录,并在其中创建package.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"
}
}
npm
使用此package.json
文件来轻松配置您的应用程序。 我们指定我们的依赖关系: express
,我们将用于服务应用程序的Web框架; peer
,我们将用于信令的peerjs服务器; socket.io
,将用于轮询和webRTC实施。 react-bootstrap
和bootstrap
是用于使用TwitterCSS框架来设置应用程序样式的软件包。
我们还将需要一些其他软件包,为此,我们将使用bower
。
创建一个bower.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"
}
}
通过这种配置,我们可以关闭react
, jQuery
, bootstrap
, eventEmitter
来eventEmitter
事件,并使用peerJS
Client库来包装WebRTC。
最后,通过设置.bowerrc
文件来指定安装此文件的位置:
{
"directory": "src/lib"
}
在这里,只需坐下来并通过以下方法安装依赖项:
$ bower install && npm install
该命令完成后,您将看到一个新目录node_modules
和src/lib
。 这些包含准备使用的模块。
现在,在package.json
等旁边的主目录中创建一个app.js
这将是您应用程序的主要入口点。
//Configure our Services
var express = require('express'),
PeerServer = require('peer').PeerServer,
events = require('./src/Events.js'),
app = express(),
port = process.env.PORT || 3001;
//Tell express to use the 'src' directory
app.use(express.static(__dirname + '/src'));
//Configure the http server and PeerJS Server
var expressServer = app.listen(port);
var io = require('socket.io').listen(expressServer);
var peer = new PeerServer({ port: 9000, path: '/chat' });
//Print some console output
console.log('#### -- Server Running -- ####');
console.log('Listening on port', port);
peer.on('connection', function (id) {
io.emit(events.CONNECT, id);
console.log('# Connected', id);
});
peer.on('disconnect', function (id) {
io.emit(events.DISCONNECT, id);
console.log('# Disconnected', id);
});
这将简单地创建一个Express服务器,使我们刚刚通过bower
获得的src/
文件现在可以通过HTTP访问。 然后创建一个socket.io
实例以侦听expressServer
对象。 这用于轮询和促进PeerServer
,该步骤实际上将完成WebRTC聊天部分。
要配置PeerServer
,您所需要做的就是指定服务器将在其上运行的port
和path
,然后开始使用.on
方法配置事件。 我们正在使用一个名为Events.js
的单独文件来指定应用程序的事件。
peer.on('connection', function (id) {
io.emit(events.CONNECT, id);
console.log('# Connected', id);
});
在这里,我们使用events.CONNECT
事件来指定用户何时连接到我们的应用。 视图组件的状态将使用它来实时更新其显示。
为此,我们需要为对等连接创建服务器以代理。
在src/Server.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 () {
return 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 (user, message) {
this._peers[user].send(message);
};
ChatServer.prototype.broadcast = function (msg) {
for (var peer in this._peers) {
this.send(peer, msg);
}
};
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);
});
self.socket.on(events.DISCONNECT, function (userId) {
if (userId === self.getUsername()) {
return;
}
self._disconnectFrom(userId);
self.emit(events.DISCONNECT, userId);
console.log('User disconnected', userId);
});
});
console.log('Connecting with username', username);
this.peer = new Peer(username, {
host: location.hostname,
port: 9000,
path: '/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 (username) {
var conn = this.peer.connect(username);
conn.on('open', function () {
this._registerPeer(username, conn);
}.bind(this));
};
ChatServer.prototype._registerPeer = function (username, conn) {
console.log('Registering', username);
this._peers[username] = conn;
conn.on('data', function (msg) {
console.log('Message received', msg);
this.emit(events.MSG, { content: msg, author: username });
}.bind(this));
};
ChatServer.prototype._disconnectFrom = function (username) {
delete this._peers[username];
};
这是应用程序的主要内容。 在这里,我们使用所有功能配置ChatServer
对象。
首先,我们使用socket.io
建立通过events.CONNECT
连接的新用户的信令:
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:
this.peer = new Peer(username, {
host: location.hostname,
port: 9000,
path: '/chat'
});
然后,我们通过on
方法监听事件:
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);
});
在components/chat
目录中,我们还拥有我们的JSX内部组件。 花点时间浏览存储库中的所有内容。 我现在将专注于ChatBox
组件:
/** @jsx React.DOM */
'use strict';
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));
this.chatProxy.onUserConnected(this.userConnected.bind(this));
this.chatProxy.onUserDisconnected(this.userDisconnected.bind(this));
},
userConnected: function (user) {
var users = this.state.users;
users.push(user);
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,
author : this.chatProxy.getUsername()
});
this.chatProxy.broadcast(message);
},
addMessage: function (message) {
if (message) {
message.date = new Date();
this.refs.messagesList.addMessage(message);
}
},
render: function () {
return (
React p2p Web RTC Chat
<UsersList users={this.state.users} username={this.props.username} ref="usersList"></UsersList>
<MessageInput
ref="messageInput"
messageHandler={this.messageHandler}>
</MessageInput>
);
}
});
这个类在的使用ChatServer
我们之前创建的,利用它作为一个代理ChatBox
部件。
最后,所有组件和库都使用index.html
呈现在页面上,并通过node express服务。
要启动该应用程序,请运行npm start
并将您的浏览器指向http://localhost:3001
以查看聊天记录。
在Heroku上直播
使用Heroku,从云服务真的很容易。 注册一个免费帐户,然后您就可以在系统上安装heroku
工具带了。 了解更多关于得到Heroku
建立在Heroku的开发中心 。
现在您已经有了Heroku
,请登录并创建一个新项目,如下所示:
$ git clone git@github.com: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 repo。
现在,就像将代码推送到heroku一样简单:
$ git push heroku master
推送完成后,您将可以通过以下方式启动Web服务:
$ heroku ps:scale web=1
现在,只需访问提供的URL,或作为快捷方式使用open
命令:
$ heroku open
结论
您已经学会了如何创建JSX组件以及如何将它们与React交互,并提供了聊天应用程序的详细示例。 花一些时间浏览代码,看看React和components/chat
目录是如何工作的。
结合到Heroku
的部署,您可以开始黑客攻击并为云创建自己的React
应用程序!
翻译自: https://code.tutsplus.com/tutorials/using-jsx-and-react--cms-25131