第9章-WebSocket、Socket.IO和DerbyJS的实时应用程序-9.3.用DerbyJS,Express.js和MongoDB搭建一个在线协作的代码编辑器

xiaoxiao2021-02-28  92

Derby是一个新的,成熟的MVC框架,作为Express的中间件使用。 Express.js是使用中间件概念增强应用程序功能的一个流行的node框架。 Racer也支持Derby,他是一个数据同步引擎,类似Handlebars的模板引擎,拥有很多其他特性。 Meteor和Sails.js是另一个实时全栈Node.js的MVC框架,可与DerbyJS相媲美。 不过Meteor更保守些,他往往需要依赖于其他专有的解决方案和软件包。

本示例将使用Express.js、DerbyJS、MongoDB和Redis构建一个实时的应用程序。 项目结构: 1.项目依赖和package.json 2.服务器端代码 3.DerbyJS应用程序 4.DerbyJS视图 5.编辑器Tryout

一、项目依赖和package.json

创建项目文件夹editor和文件package.json

{ "name": "editor", "version": "0.0.1", "private": true, "description": "在线实时编辑器", "main": "index.js", "scripts": { "test": "mocha test" }, "git repository": "https://github.com/client-zy/aml", "keywords": "editor node derby real-time", "author": "lijian", "license": "BSD", "dependencies": { "derby": "~0.5.12", "express": "~3.4.8", "livedb-mongo": "~0.3.0", "racer-browserchannel": "~0.1.1", "redis": "~0.10.0" } }

模块说明: derby(DerbyJS)和Express.js是为了路由 redis,racer-browserchannel和livedb-mongo是为了使DerbyJS用Redis和MongoDB数据库

二、服务器端代码

require('derby').run(__dirname + '/server.js');

这行代码用来启动Derby服务器

创建editor/server.js作为应用的入口文件 //1.引入依赖

var path = require('path'), express = require('express'), derby = require('derby'), racerBrowserChannel = require('racer-browserChannel'), liveDbMongo = require('livedb-mongo'),

//2.定义Derby应用程序的文件

app = require(path.join(__dirname, 'app.js')),

//3.实例化Express.js应用程序

expressApp = module.exports = express(),

//4.Redis客户端

redis = require('redis').createClient(),

//5.本地MongoDB连接URI

mongoUrl = 'mongodb://localhost:27017/editor';

//6.使用连接URI和redis客户端对象创建一个liveDbMongo对象

var store = derby.createStore({ db: liveDbMongo(mongoUrl + '?auto_reconnect', { safe: true }), redis: redis });

//7.定义一个公共文件夹

var publicDir = path.join(__dirname, 'public');

//8.用链式调用声明使用Express.js中间件

expressApp .use(express.favicon()) .use(express.compress())

//9.中间件DerbyJS-specific提供了Derby路由和模型对象

.use(app.scripts(store)) .use(racerBrowserChannel(store)) .use(store.modelMiddleware()) .use(app.router())

//10.常规的Express.js路由中间件

.use(expressApp.router);

//11.在一个服务器端混合使用Express.js和DerbyJS是可以的 //用404涵盖所有路由

expressApp.all('*', function(req, res, next){ return next('404: ' + req.url); });

三、DerbyJS应用程序

DerbyJS应用程序(app.js)巧妙地在浏览器和服务器间共享代码, 所以可以在一个地方(Node.js文件)写函数和方法。 然而,依赖DerbyJS规则可以把app.js中的部分代码变成浏览器JavaScript代码 这种行为可以更好地复用和组织代码,因为不需要复制路由、helper函数和实体方法。 把DerbyJS应用程序文件中的代码变成浏览器代码的一种方法是用app.ready(),

editor/app.js文件

//1.声明变量,创建一个应用程序 var app; app = require('derby').createApp(module); //2.声明根路由,当用户访问他时会创建一个新snippet并重定向到路径/:snippetId: app.get('/', function(page, model, _arg, next){ snippetId = model.add('snippets', { snippetName: _arg.snippetName, code: 'var' }); return page.redirect('/', + snippetId); }); //3.DerbyJS使用和Express.js相似的路由模型,DerbyJS响应页面,Express.js响应报文(res) //路由/:snippetId是编辑器显示的地方,调用subscribe以支持DOM的实时更新 app.get('/:snippetId', function(page, model, param, next){ //4.model.at方法在collection_name.ID模式中的参数类似于调用findById(),即我们从存储/数据库中得到对象 var snippet = model.at('snippets. '+param.snippetId); snippet.subscribe(function(err){ console.log(snippet.get()); //5.model.ref()允许把对象绑定到视图展现层。通常在视图层可以写{{_page.snippet}},他会实时地自我更新。 //我们可以使用Ace编辑器让代码看起来漂亮点,Ace被绑到全局的编辑器对象上。 model.ref('_page.snippet', snippet); page.render(); }); }); //6.DerbyJS的前端JavaScript代码是写在app.ready的回调里的,我们需要在应用程序启动时从Derby模型设置Ace的内容 app.ready(function(model){ editor.setValue(model.get('_page.snippet.code')); //7.监听模型的改变(来自其他用户)并用新文本更新Ace编辑器 model.on('change', '_page.snippet.code', function(){ if (editor.getValue() !== model.get('_page.snippet.code')){ //8.process.nextTick是一个函数,该函数声明了在下一个事件循环迭代的回调(作为参数传递给他) //这可以避免无限循环,即当用户的更新模型在Ace编辑器里触发改变事件时,会触发远程模型的不必要的更新 process.nextTick(function(){ editor.setValue(model.get('_page.snippet.code'), 1); }); } }); //9.监听Ace改变,并更新DerbyJS模型 editor.getSession().on('change', function(e){ if (editor.getValue() !== model.get('_page.snippet.code')){ process.nextTick(function(){ //10._page是DerbyJS专有的名字,用来渲染/绑定视图 model.set('_page.snippet.code', editor.getValue()); }); } }); });

四、DerbyJS视图

DerbyJS视图包含内置标签,如,大部分内容都是在页面加载完之后由Ace编辑器动态生成的。 views/app.html

<Title:> 在线实时编辑器 <Head:> <meta charset="utf-8"> <meta http-equiv="x-ua-compatible" content="IE=edge, chrome=1"> <title>Editor</title> <style type="text/css" media="screen"> body{ overflow: hidden; } #editor{ margin:0; position: absolute; top: 0; bottom:0; left:0; right:0; } </style> //1.从内容分发网络(CDN)加载jQuery和Ace <script src="//cdnjs.cloudflare.com/ajax/libs/ace/1.1.01/ace.js"></script> <script src="//code.jquery.com/jquery-2.1.0.min.js"></script> //2.在body标签里用一个隐藏的input标签和editor元素 <Body:> <input type="hidden" value="{_page.snippet.code}" class="code" /> <pre id="editor" value="{_page.snippet.code}"></pre> //3.初始化Ace编辑器对象,作为一个全局变量(编辑器的变量) <script> var editor = ace.edit("editor"); editor.setTheme("ace/theme/twilight");//设置主题 editor.getSession().setMode("ace/mode/javascript");//设置语言 </script>

注意:视图名称(app.html)要和DerbyJS应用程序文件的名称(app.js)保持一致,不然框架就关联不上

五、编辑器Tryout

项目所有文件app.js,index.js,server.js,views/app.html和package.json

用$npm install安装模块, 用$mongod和$redis-server启动数据库 用$node .或者$node index启动应用程序

在浏览器中打开http://localhost:3000/, 他会重定向到一个新的snippet(用URL中的ID) 在第二个浏览器窗口中打开同样的url,并开始打字, 这时第一个窗口中的代码同步更新了。

转载请注明原文地址: https://www.6miu.com/read-30528.html

最新回复(0)