使用JSX和React

最终产品图片
您将要创造的

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,因此不建议使用classfor class关键字作为属性名。 相反,React组件期望使用React属性名称,例如classNamehtmlFor

嵌套标签

在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 : ''}
);

您也可以只为表单属性(例如disabledchecked等)传递布尔值。 如果您愿意,只需编写纯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使用PeerJssocket.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-bootstrapbootstrap是用于使用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"
  }
}

通过这种配置,我们可以关闭reactjQuerybootstrapeventEmittereventEmitter事件,并使用peerJS Client库来包装WebRTC。

最后,通过设置.bowerrc文件来指定安装此文件的位置:

{
  "directory": "src/lib"
}

在这里,只需坐下来并通过以下方法安装依赖项:

$ bower install && npm install

该命令完成后,您将看到一个新目录node_modulessrc/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 ,您所需要做的就是指定服务器将在其上运行的portpath ,然后开始使用.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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值