React编写聊天室(1)
2016-01-11 17:15
816 查看
由于angular性能的问题,转投react的怀抱,学了半个月有了,写了一个聊天室的demo。
源码https://github.com/zezhipeng/react-socket.io-chat
例子的地址是 http://120.26.109.186:3000/?name=zezhipeng&&room=1
name 与room 分别为用户名和房间号,可以随意修改。
在同一个房间内可以相互聊天。
建议用手机打开,或者chrome用手机模式打开。
需要用到:
express
react
webpack
jade
bootstrap
mongoose
socket.io
和一堆中间件和包
首先关于webpack,就是一个web客户端的包管理工具。比较实际的感受就是,可以在js里面写require了(配合npm),或者可以说可以ES6来写前端了,还是蛮好用的。
我的webpack.config是
然后执行
就可以安心改代码了。如果你没用过webpack,网上有很多关于这个的资料,youtube上也有比较好的教程,由于篇幅问题我就不多说什么了。
最终效果图如下
从图上我们可以看到,我把app分成了3个子模块,
MsgForm //发送文字表单
MsgContent //信息展示模块
MsgTool //聊天模块的一些插件
首先关于父级组件app.jsx
初始化的时候,我定义了3个状态
这里还要讲一下的是,
关于MsgForm模块,
从代码中可以看到,最外层用了bootstrap的input-group类,里面包裹了3个div,表情列表呼出按钮,发送文字表单和发送文字按钮.。
利用componentDidMount函数,我设置了一个定时器,检查this.state.count是否大于0并且为禁用状态,如果是的话,计数减1
不是的话,设置为非禁用,初始话计数为3。这样,每次发送一条消息后会有4秒的禁言时间,防止刷屏。
这里的socketEmitMsg属性是从父组件app.jsx传递过来的一个方法,就是一个简单的socket.emit方法
关于表情emojilist.jsx
这里表情库是从github上找来的一个免费的,有兴趣的可以上他们官网http://emojione.com/ 看看。
这里要注意的是,我们转换过来的html代码加入以{emojione.shortnameToImage(v)}这样的形式显示的话,react会直接将他显示为文本,先要转换为string类型后,通过dangerouslySetInnerHTML来显示。
未完待续。。。。
源码https://github.com/zezhipeng/react-socket.io-chat
例子的地址是 http://120.26.109.186:3000/?name=zezhipeng&&room=1
name 与room 分别为用户名和房间号,可以随意修改。
在同一个房间内可以相互聊天。
建议用手机打开,或者chrome用手机模式打开。
需要用到:
express
react
webpack
jade
bootstrap
mongoose
socket.io
和一堆中间件和包
首先关于webpack,就是一个web客户端的包管理工具。比较实际的感受就是,可以在js里面写require了(配合npm),或者可以说可以ES6来写前端了,还是蛮好用的。
我的webpack.config是
module.exports={ entry:"./public/js/app.jsx", output:{ path:"./public/js", filename:"bundle.js" }, resolve:{ extensions: ['', '.js', '.jsx'] }, module:{ loaders:[ { test: /\.jsx$/, loader: 'babel-loader', exclude: /node_modules/, query: { presets: ['es2015', 'react'] } } ] } }
然后执行
webpack -d --watch
就可以安心改代码了。如果你没用过webpack,网上有很多关于这个的资料,youtube上也有比较好的教程,由于篇幅问题我就不多说什么了。
最终效果图如下
从图上我们可以看到,我把app分成了3个子模块,
MsgForm //发送文字表单
MsgContent //信息展示模块
MsgTool //聊天模块的一些插件
首先关于父级组件app.jsx
var React = require("react"); var ReactDOM = require("react-dom"); var socket = io(); var marked = require('marked'); var MsgContent = require("./msgcontent.jsx"); var MsgTool = require("./msgtool.jsx"); var MsgForm = require("./msgform.jsx"); var ChatApp = React.createClass({ getInitialState: function () { return {messages: [], system: [], scrollSwitch: true} }, componentDidMount: function () { socket.on("join", this.handleJoin); socket.on("msg", this.handleMsgRce) }, handleJoin: function (msg) { console.log(msg); var self = this; var {system}=this.state; system.push(msg); this.setState({msg}); setTimeout(function () { system.pop(); self.setState({system}); }, 5000) }, handleMsgRce: function (msg) { console.log(this.state); var {messages}=this.state; messages.push(msg) this.setState({messages}); }, socketEmitMsg: function (msg) { socket.emit("msg", msg) }, switchCallback: function (v) { this.setState({scrollSwitch: v}) }, render: function () { return ( <div className="col-md-12 panel chat"> <div className="panel-header"> <MsgTool switchCallback={this.switchCallback}/> </div> <div className="panel-body"> <MsgContent messages={this.state.messages} system={this.state.system} scrollSwitch={this.state.scrollSwitch}/> </div> <div className="panel-footer"> <MsgForm user={this.props.user} socketEmitMsg={this.socketEmitMsg}/> </div> </div> ) } }); ReactDOM.render(<ChatApp user={user}/>, document.getElementById("content"))
初始化的时候,我定义了3个状态
{messages: [], system: [], scrollS 4000 witch: true}messages即是接收到的消息的对象集合,system是系统消息的集合,而scrollSwitch是滚屏插件的对象(传递到MsgTool)的。
这里还要讲一下的是,
user={user}里面的user是一个全局变量,通过express+jade直接渲染给前端的。这里有些人可能不会,我想做的就是后端通过JSON.stringify(user),将后端保存的用户信息转为string类型,前端的jade通过非转义的方式
user=!{user}就可以直接调用用户的信息
关于MsgForm模块,
var React = require("react"); var EmojiList = require("./emojilist.jsx") module.exports = React.createClass({ getInitialState: function () { return ({text: "", disabled: false, count: 3,hide:true}) }, //把信息传递到父组件 handleSubmit: function (e) { e.preventDefault(); if (this.state.text) { var msg = {text: this.state.text, user: this.props.user}; this.props.socketEmitMsg(msg) this.setState({text: "", disabled: true,hide:true}) } }, handleInputMsg: function (e) { this.setState({text: e.target.value}) }, componentDidMount: function () { //发送间隔 this.interval = setInterval(this.tick, 1000); var self = this //把表情的string值传递到输入框中 $(document).ready(function(){ $(".theEmoji").click(function(){ var v = $(this).attr("value") self.setState({text:self.state.text+v}) }) }) }, tick: function () { if (this.state.count > 0 && this.state.disabled == true) { this.setState({count: this.state.count - 1}) } else { this.setState({disabled: false, count: 3}) } }, //显示表情列表 handleClick:function(){ this.setState({hide:!this.state.hide}) }, submitEmoji:function(v){ this.state.text +=v }, render: function () { return ( <form style={{"position":"relative"}}> <EmojiList hide={this.state.hide} submitEmoji={this.submitEmoji} /> <div className="input-group sendMsgForm"> <span className="input-group-addon"> <span className="fa fa-smile-o feedback" onClick={this.handleClick}></span> </span> <input className="form-control" onChange={this.handleInputMsg} value={this.state.text} maxLength="50"/> <span className="input-group-addon"> <button className="btn btn-danger" onClick={this.handleSubmit} disabled={this.state.disabled}>{this.state.disabled?this.state.count:"发送"} </button> </span> </div> </form> ) } });
从代码中可以看到,最外层用了bootstrap的input-group类,里面包裹了3个div,表情列表呼出按钮,发送文字表单和发送文字按钮.。
利用componentDidMount函数,我设置了一个定时器,检查this.state.count是否大于0并且为禁用状态,如果是的话,计数减1
不是的话,设置为非禁用,初始话计数为3。这样,每次发送一条消息后会有4秒的禁言时间,防止刷屏。
这里的socketEmitMsg属性是从父组件app.jsx传递过来的一个方法,就是一个简单的socket.emit方法
socketEmitMsg: function (msg) { socket.emit("msg", msg) },
关于表情emojilist.jsx
var React = require("react"); var emojione = require("emojione"); var EmojiList = React.createClass({ getInitialState:function(){ return ({ emoji:[":grinning:",":grimacing:",":grin:",":joy:",":smiley:",":sweat_smile:", ":innocent:",":wink:",":blush:",":slight_smile:",":yum:",":heart_eyes:", ":kissing_heart:",":stuck_out_tongue_closed_eyes:",":money_mouth:",":nerd:", ":sunglasses:",":hugging:",":thinking:",":flushed:",":disappointed:",":rage:", ":confused:",":persevere:",":tired_face:",":triumph:",":open_mouth:",":scream:", ":cold_sweat:",":cry::disappointed_relieved:",":sweat::sob:",":head_bandage:",":poop:", ":spy::tongue:",":pray::muscle:",":clap::v:",":ok_hand:",":point_up:",":middle_finger:", ":metal::vulcan:"] }) }, render:function(){ var emojiList = this.state.emoji.map(function(v,n){ var createMarkup = function(){ return {__html:emojione.shortnameToImage(v).toString()} } return <li key={n} dangerouslySetInnerHTML={createMarkup()} className="theEmoji" value={v}></li> }) return (<ul className={this.props.hide?"hide":"show"+" emoji "}> {emojiList} </ul>) } }); module.exports=EmojiList
这里表情库是从github上找来的一个免费的,有兴趣的可以上他们官网http://emojione.com/ 看看。
这里要注意的是,我们转换过来的html代码加入以{emojione.shortnameToImage(v)}这样的形式显示的话,react会直接将他显示为文本,先要转换为string类型后,通过dangerouslySetInnerHTML来显示。
未完待续。。。。
相关文章推荐
- [原创]java局域网聊天系统
- webpack bable-loader升级无法编译jsx es6
- 如何安装SQL Server 2008 Management Studio Express
- sql server 2008 r2 express 精简版与企业版的区别
- c#实现多线程局域网聊天系统
- SQL Sever 2005 Express 安装失败解决办法
- 超级给力的JavaScript的React框架入门教程
- 由ReactJS的Hello world说开来
- Nodejs初级阶段之express
- 深入探讨前端框架react
- win7下安装配置node.js+express开发环境
- Express实现前端后端通信上传图片之存储数据库(mysql)傻瓜式教程(一)
- nw.js实现类似微信的聊天软件
- Nodejs的express使用教程
- javascript Discuz代码中的msn聊天小功能
- 用用outlook Express 由于服务器拒绝接受发件人的电子邮件地址,这封邮件无法发送
- 深入浅析react native es6语法
- 浅析node连接数据库(express+mysql)
- Microsoft SQL Server 2005 Express 远程访问设置详述,100%成功篇
- 零基础搭建Node.js、Express、Ejs、Mongodb服务器及应用开发入门