目录
什么是Express?
了解Express中的中间件
源代码
步骤2。配置
步骤3。创建一个测试框架
4。设置一个带有Express的MVC模式
步骤1。模型
5。创建FastDelivery网站
步骤1。控制面板
保护管理面板
步骤3。前端
结论
首页 web前端 js教程 使用Express建立一个完整的MVC网站

使用Express建立一个完整的MVC网站

Mar 14, 2025 am 09:33 AM


什么是Express?

Express是Node.js的最佳框架之一。它具有大力的支持和许多有用的功能。那里有很多很棒的文章,涵盖了所有基础知识。但是,这次我想深入研究,并分享我的工作流程以创建一个完整的网站。通常,本文不仅用于Express,而且还将其与其他一些可用于节点开发人员使用的优质工具结合使用。

要遵循本教程,我假设您对节点有些熟悉,并且已将其安装在系统上。

了解Express中的中间件

Express的核心是连接。这是一个中间件框架,配备了许多有用的东西。如果您想知道什么是中间件,这是一个快速示例:

 const connect = require('connect'),<br> http = require('http');<br><br> const app = connect()<br> .use(function(req,res,ext)<br> console.log(“那是我的第一个中间件”);<br> 下一个();<br> }))<br> .use(function(req,res,ext)<br> console.log(“那是我的第二个中间件”);<br> 下一个();<br> }))<br> .use(function(req,res,ext)<br> console.log(“ end”);<br> res.end(“ Hello World”);<br> });<br><br> http.Createserver(App).Listen(3000);<br>
登录后复制

中间件基本上是一个函数,该函数接受响应对象和响应对象,或通过在第二个中间件中调用Next()方法来调用下一个函数,Body Parser解析请求主体并支持应用程序/JSON,Application/X-WWW-Form-urlCormeded,以及Multipart/form-data。并用cookie名称键入的对象进行req.cookies。

Express Craps实际上连接并添加了一些新功能,例如路由逻辑,这使得该过程更加顺畅。这是处理Express中的GET请求的示例:

 app.get('/hello.txt',function(req,res){<br> var body ='Hello world';<br> res.setheader('content-type','text/plain');<br> res.setheader(“内容长度”,body.mength);<br> res.end(身体);<br> });<br>
登录后复制

源代码

我们构建的示例网站的源代码可在GitHub上使用。请随意分叉并与之一起玩。这是运行网站的步骤。

  • 下载源代码
  • 转到NPM安装
  • 运行MongoDB守护程序
  • 运行NPM安装。
     {<br> “名称”:“ mywebsite”,<br> “描述”:“我的网站”,<br> “版本”:“ 0.0.1”,<br> “依赖关系”:{<br> “ express”:“ 5.x”<br> }<br> }<br>
    登录后复制

    框架的代码将放置在node_modules中,您将能够创建一个实例。但是,我更喜欢使用命令行工具一个替代选项。通过使用NPX Express-Generator命令:

     用法:Express [选项] [DIR]<br><br> 选项:<br><br>  -  version输出版本号<br> -e,-ej添加EJS引擎支持<br>  -  Pug添加哈哈发动机支撑<br> -HBS添加车把引擎支持<br> -h, - 霍根添加hogan.js引擎支持<br> -v,-view <engine>添加视图<engine>支持(灰尘|<br>  - 不使用静态HTML代替视图引擎<br> -c,-css <egene>添加样式表<engine> support> support> sandlus | Compass | sass)(默认为普通CSS)<br>  -  git添加.gitignore<br> -F, - 非空目录的力量<br> -h, - 螺旋输出使用信息<br></engine></egene></engine></engine>
    登录后复制

    如您所见,只有一些可用的选择,但是对我来说,它们已经足够了。通常,我少用作为CSS预处理器和车把作为模板引擎。在此示例中,我们还需要会话支持,因此NPM安装和NODE_MODULES文件夹将弹出。

    我意识到上述方法并不总是合适的。您可能需要将路线处理程序放置在另一个目录或类似目录中。但是,正如您将在接下来的几节中看到的那样,我将对已经生成的结构进行更改,并且很容易做到。因此,您应该只是想到app.js来使用我们的新文件结构。我们需要删除这两行:

     const usersrouter = require(“ ./路由/用户”);<br> ...<br> app.use(“/用户”,usersrouter);<br>
    登录后复制

    步骤2。配置

    现在,我们需要设置配置。让我们想象我们的小网站应部署到三个不同的位置:本地服务器,登台服务器和生产服务器。当然,每个环境的设置都不同,我们应该实施一种足够灵活的机制。如您所知,每个节点脚本都是作为控制台程序运行的。因此,我们可以轻松地发送将定义当前环境的命令行参数。我将该部分包裹在单独的模块中,以便稍后为其编写测试。这是/config/index.js文件:

     const config = {<br> 当地的: {<br> 模式:“本地”,<br> 端口:3000<br> },,<br> 登台:{<br> 模式:“分期”,<br> 端口:4000<br> },,<br> 生产: {<br> 模式:“生产”,<br> 端口:5000<br> }<br> }<br> Module.exports = function(mode){<br> 返回配置[模式|| process.argv [2] || 'local'] || config.local;<br> }<br>
    登录后复制

    (现在)只有两个设置:端口。您可能已经猜到了,该应用程序为不同的服务器使用不同的端口。这就是为什么我们必须在app.js中更新站点的输入点的原因。

     const config = require('./ config')();<br> process.env.port = config.port;<br>
    登录后复制

    要在配置之间切换,只需在末尾添加环境即可。例如:

     NPM开始登台<br>
    登录后复制

    将在端口4000运行服务器。

    现在,我们将所有设置都放在一个地方,并且很容易管理。


    步骤3。创建一个测试框架

    我是测试驱动开发(TDD)的忠实拥护者。我将尝试介绍本文中使用的所有基础类。当然,对所有内容进行测试都会使这本书的写作太长,但是总的来说,这就是创建自己的应用程序时应该继续进行的方式。我最喜欢的测试框架之一是UVU,因为它非常易于使用和快速使用。当然,它可以在NPM注册表中使用:

     npm安装 -  save-dev uvu<br>
    登录后复制

    然后,在NPM测试中创建一个新脚本,您应该看到以下内容:

     config.js<br> •••(3/3)<br><br> 总计:3<br> 通过:3<br> 跳过:0<br> 持续时间:0.81ms<br>
    登录后复制

    这次,我首先编写了实施,第二个测试。这并不是TDD做事的方式,而是在接下来的几个部分中,我将相反。

    我强烈建议您花费大量时间写作测试。没有什么比全面测试的应用程序更好的了。

    几年前,我意识到一些非常重要的事情,这可能有助于您制作更好的程序。每次您开始编写新课程,新模块或仅仅是新逻辑时,请问自己:

    我该如何测试?

    这个问题的答案将有助于您更有效地编码,创建更好的API,并将所有内容放入良好的块中。您不能为意大利面代码编写测试。例如,在上面的配置文件( /config/index.js )中,我添加了发送生产配置的可能性,但是节点脚本是使用NPM安装MongoDB运行的。

    接下来,我们将编写一个测试,该测试检查是否运行了MongoDB服务器。这是/tests/mongodb.js文件:

     const {test} = require(“ uvu”);<br> const {mongoclient} = require(“ mongodb”);<br><br> test(“ mongodb服务器活动”,async函数(){<br> const client = new mongoclient(“ mongodb://127.0.0.1:27017/fastdelivery”);<br> 等待client.connect();<br> });<br><br> test.run();<br><br>
    登录后复制

    我们不需要添加MongoDB客户端的任何连接方法,每当我们必须向数据库提出请求时,都会接收一个mongoclient对象。因此,我们应该连接到初始服务器创建中的数据库。为此,由于中间件在每个请求之前自动运行,因此在Req.db属性中可用。


    4。设置一个带有Express的MVC模式

    我们都知道MVC模式。问题是如何适用表达。或多或少,这是解释的问题。在接下来的几个步骤中,我将创建模块,该模块充当模型,视图和控制器。

    步骤1。模型

    该模型将是处理我们应用程序中的数据的方法。它应该可以使用杂种。我们的模型还应该有一种扩展它的方法,因为我们可能需要创建不同类型的模型。例如,我们可能想要一个contactsmodel。因此,我们需要编写一个新规格, /tests /base.model.js ,以测试这两个模型功能。并记住,通过在开始编码实现之前定义这些功能,我们可以保证我们的模块只能完成我们想要的工作。

     const {test} = require(“ uvu”);<br> const sustert = require(“ uvu/servert”);<br> const ModelClass = require(“ ../ models/base”);<br> const dbmockup = {};<br> test(“模块创建”,异步函数(){<br> const Model =新的ModelClass(DBMOCKUP);<br> assert.ok(model.db);<br> assert.ok(model.setdb);<br> assert.ok(model.Collection);<br> });<br> test.run();<br>
    登录后复制

    而不是真实的DB对象和我们的数据库视图目录的Getter将更改为基本视图类。现在,这个小的更改需要另一个更改。我们应该通知明确说明我们的模板文件现在放置在另一个目录中:

     app.set(“ views”,path.join(__ dirname,“模板”));<br>
    登录后复制

    首先,我将定义我需要的内容,编写测试,然后编写实现。我们需要一个匹配以下规则的模块:

    • 它的构造函数应接收响应对象和模板名称。
    • 它应该有一个视图类。难道不仅以某种方式调用响应对象,例如,提供JSON数据:
       const data = {开发人员:“ krasimir tsonev”};<br> response.conttype(“ application/json”);<br>响应send(json.stringify(data));<br>
      登录后复制

      拥有JSONVIEW类,甚至是测试目录,而不是每次都这样做,如果您在路线之后运行'/'(在上面的示例中,实际上是控制器)是一个接受响应的函数,并且是一个接受响应的函数,并且Express(1)命令行工具将是一个名为“旧界限”功能,它是旧的Middledware函数,它是旧的Middledware函数,它是一个旧的Middledware函数,它是optres ofer

    • 应该有一种运行方法以及其自己的逻辑。

      5。创建FastDelivery网站

      好的,我们为MVC体系结构提供了一系列的课程,并且我们已经通过测试介绍了新创建的模块。现在,我们准备继续使用假公司FastDelivery的网站。

      让我们想象该站点有两个部分:前端和管理面板。前端将用于向我们的最终用户显示数据库中写的信息。管理面板将用于管理该数据。让我们从管理员(控制)面板开始。

      步骤1。控制面板

      让我们首先创建一个简单的控制器,该控制器将用作管理页面。这是/routes/admin.js文件:

       const basecontroller = require(“ ./ base”),<br> view = require(“ ../ view/base”);<br> Module.exports = new(class adminController扩展了basecontroller {<br> constructor(){<br> 超级(“ admin”);<br> }<br> 运行(req,res,next){<br> if(this.authorize(req)){<br> req.session.fastDelivery = true;<br> req.session.save(function(err){<br> var v =新视图(res,“ admin”);<br> v.render({<br> 标题:“管理”,<br> 内容:“欢迎来到控制面板”,<br> });<br> });<br> } 别的 {<br> const v =新视图(res,“ admin-login”);<br> v.render({<br> 标题:“请登录”,<br> });<br> }<br> }<br> 授权(req){<br> 返回 (<br> (Req.Session &&<br> req.session.fastDelivery &&<br> req.session.fastDelivery === true)||<br> (req.body &&<br> req.body.username === this.username && &&<br> req.body.password === this.password)<br> );<br> }<br> })();<br>
      登录后复制

      通过为控制器和视图使用预编写的基本类,我们可以轻松地为控制面板创建入口点。 admin.run方法直接作为中间件。那是因为我们想保留上下文。如果我们这样做:

       app.all('/admin*',admin.run);<br>
      登录后复制

      admin一词将指向其他内容。

      保护管理面板

      /管理为开头的每个页面都应受到保护。为了实现这一目标,我们将使用Express的中间件:Session。它只需将对象附加到称为admin Controller的请求即可做两个其他事情:

      • 它应该检查是否有可用的会话。如果没有,请显示登录表单。
      • 如果用户名和密码匹配,则应接受登录表格发送的数据并授权用户。

      这是我们可以用来实现这一目标的小辅助功能:

      授权(req){<br> 返回 (<br> (Req.Session &&<br> req.session.fastDelivery &&<br> req.session.fastDelivery === true)||<br> (req.body &&<br> req.body.username === this.username && &&<br> req.body.password === this.password)<br> );<br> }<br>
      登录后复制

      首先,我们有一个声明,试图通过会话对象识别用户。其次,我们检查是否已提交表格。如果是这样,则来自表单的数据在BodyParser中间件中可用。然后,我们只检查用户名和密码是否匹配。

      现在,这是标题,图片和类型属性将确定记录的所有者。例如,“联系人”页面只需要一个使用Admin Controller的记录。为了简化任务,我决定将添加记录列表和添加/编辑的表格组合起来。如您在下面的屏幕截图中看到的那样,该页面的左侧为列表保留,并保留该表单的右侧部分。

      使用Express建立一个完整的MVC网站

      在一个页面上拥有所有内容意味着我们必须集中精力在呈现页面的部分,或更具体地说,是我们发送到模板的数据。这就是为什么我创建了几个合并的助手功能,例如:

       this.del(req,function(){<br> this.form(req,res,function(formmarkup){<br> this.list(function(listmarkup){<br> v.render({<br> 标题:“管理”,<br> 内容:“欢迎来到控制面板”,<br> 列表:Listmarkup,<br> 表格:formmarkup,<br> });<br> });<br> });<br> });<br> const v =新视图(res,“ admin”);<br>
      登录后复制

      它看起来有些丑陋,但它可以按照我的意愿起作用。第一个助手是一个操作= delete&id = [记录的ID],它从集合中删除了数据。第二个功能称为列表方法获取信息并准备HTML表,后来将其发送到模板。可以在本教程的源代码中找到这三个帮助者的实现。

      在这里,我决定向您展示处理admin.js中的文件上传的功能:

       handerfileupload(req){<br> 如果(!<br> 返回req.body.currentPicture || “”<br> }<br> const data = fs.ReadFileSync(req.files.picture.path);<br> const filename = req.files.picture.name;<br> const uid = crypto.randombytes(10).tostring(“ hex”);<br> const dir = __dirname“ /../public/uploads/” uid;<br> fs.mkdirsync(dir,“ 0777”);<br> fs.WriteFileSync(dir“/”文件名,数据);<br> 返回“/uploads/“ uid”/“ fileName;<br> }<br>
      登录后复制

      如果提交文件,则节点脚本req.files.picture。在上面的代码段中,readfilesync,writefilesync。

      步骤3。前端

      艰苦的工作现在已经完成。管理面板正在工作,我们有一个家庭和四个记录,其中包含博客的DB对象,但请致电“不同 /blog /:id string”。该路线将匹配req.params.id等URL。换句话说,我们能够定义动态参数。在我们的情况下,这就是记录的ID。获得此信息后,我们可以为每篇文章创建一个唯一的页面。

      第二个有趣的部分是我如何构建服务,职业和联系人页面。显然,他们仅使用数据库中的一个记录。如果我们必须为每个页面创建一个不同的控制器,那么我们必须复制/粘贴相同的代码,只需在其NPM安装命令中更改类型即可运行以安装新的依赖项(如果有)。

    • 然后应再次运行主脚本。
    • 请记住,节点仍然还很年轻,因此并非所有内容都可以按照您的预期工作,但是一直都有改进。例如,永远保证您的node.js程序将连续运行。您可以通过发出以下命令来执行此操作:

    永远启动您的app.js<br>
    登录后复制

    这也是我在服务器上使用的内容。这是一个不错的小工具,但它解决了一个大问题。如果您使用永远的应用程序运行,请简单地重新启动应用程序。

    现在我不是系统管理员,但是我想分享我的经验将节点应用与Apache或Nginx集成,因为我认为这是开发工作流程的一部分。

    如您所知,Apache通常在端口80上运行,这意味着,如果您打开http:// localhost:80,您将看到Apache Server提供的页面,并且很可能您的节点脚本在其他端口上收听。因此,您需要添加一个接受请求并将其发送到正确端口的虚拟主机。例如,假设我想托管我们刚刚在主机文件下的本地Apache服务器上构建的网站。

     127.0.0.1 ExpressCompletewebsite.dev<br>
    登录后复制

    之后,我们必须在Apache Configuration目录下编辑HTTPD-VHOSTS.CONF文件,然后添加:

     #ExpressCompleteWebsite.dev<br> <virtualhost><br> Servername ExprexPleteWebsite.dev<br> Serveralias www.expresscompletewebsite.dev<br> proxyrequest off<br> <br> 订单拒绝,允许<br> 从所有人那里允许<br> <br> <br> proxypass http:// localhost:3000/<br> ProxypassReverse http:// localhost:3000/<br> <br> </virtualhost><br>
    登录后复制

    服务器仍然接受端口80上的请求,但将其转发到端口3000,该端口正在侦听。

    NGINX设置要容易得多,而且,老实说,它是托管基于node.js的应用程序的更好选择。您仍然必须在主机文件中添加域名。之后,只需在NGINX安装下的/启用 /站点的目录中创建一个新文件即可。文件的内容看起来像这样:

    服务器 {<br> 听80;<br> server_name ExpressCompletewebsite.dev<br> 地点 / {<br> Proxy_pass http://127.0.0.1:3000;<br> proxy_set_header主机$ http_host;<br> }<br> }<br>
    登录后复制

    请记住,您不能使用上述主机设置同时运行Apache和Nginx。那是因为它们都需要端口80。此外,如果您计划在生产环境中使用上述代码段,则可能需要对更好的服务器配置进行一些其他研究。正如我所说,我不是这个领域的专家。


    结论

    Express是一个很棒的框架,它为您提供了开始构建应用程序的良好起点。如您所见,这是您将如何扩展它以及与之构建的方法的选择。它通过使用一些出色的中间件来简化无聊的任务,并将有趣的零件留给开发人员。

    雅各布·杰克逊(Jacob Jackson)的贡献已更新。雅各布(Jacob)是网络开发人员,技术作家,自由职业者和开源贡献者。

以上是使用Express建立一个完整的MVC网站的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

前端热敏纸小票打印遇到乱码问题怎么办? 前端热敏纸小票打印遇到乱码问题怎么办? Apr 04, 2025 pm 02:42 PM

前端热敏纸小票打印的常见问题与解决方案在前端开发中,小票打印是一个常见的需求。然而,很多开发者在实...

神秘的JavaScript:它的作用以及为什么重要 神秘的JavaScript:它的作用以及为什么重要 Apr 09, 2025 am 12:07 AM

JavaScript是现代Web开发的基石,它的主要功能包括事件驱动编程、动态内容生成和异步编程。1)事件驱动编程允许网页根据用户操作动态变化。2)动态内容生成使得页面内容可以根据条件调整。3)异步编程确保用户界面不被阻塞。JavaScript广泛应用于网页交互、单页面应用和服务器端开发,极大地提升了用户体验和跨平台开发的灵活性。

谁得到更多的Python或JavaScript? 谁得到更多的Python或JavaScript? Apr 04, 2025 am 12:09 AM

Python和JavaScript开发者的薪资没有绝对的高低,具体取决于技能和行业需求。1.Python在数据科学和机器学习领域可能薪资更高。2.JavaScript在前端和全栈开发中需求大,薪资也可观。3.影响因素包括经验、地理位置、公司规模和特定技能。

如何实现视差滚动和元素动画效果,像资生堂官网那样?
或者:
怎样才能像资生堂官网一样,实现页面滚动伴随的动画效果? 如何实现视差滚动和元素动画效果,像资生堂官网那样? 或者: 怎样才能像资生堂官网一样,实现页面滚动伴随的动画效果? Apr 04, 2025 pm 05:36 PM

实现视差滚动和元素动画效果的探讨本文将探讨如何实现类似资生堂官网(https://www.shiseido.co.jp/sb/wonderland/)中�...

JavaScript的演变:当前的趋势和未来前景 JavaScript的演变:当前的趋势和未来前景 Apr 10, 2025 am 09:33 AM

JavaScript的最新趋势包括TypeScript的崛起、现代框架和库的流行以及WebAssembly的应用。未来前景涵盖更强大的类型系统、服务器端JavaScript的发展、人工智能和机器学习的扩展以及物联网和边缘计算的潜力。

JavaScript难以学习吗? JavaScript难以学习吗? Apr 03, 2025 am 12:20 AM

学习JavaScript不难,但有挑战。1)理解基础概念如变量、数据类型、函数等。2)掌握异步编程,通过事件循环实现。3)使用DOM操作和Promise处理异步请求。4)避免常见错误,使用调试技巧。5)优化性能,遵循最佳实践。

如何使用JavaScript将具有相同ID的数组元素合并到一个对象中? 如何使用JavaScript将具有相同ID的数组元素合并到一个对象中? Apr 04, 2025 pm 05:09 PM

如何在JavaScript中将具有相同ID的数组元素合并到一个对象中?在处理数据时,我们常常会遇到需要将具有相同ID�...

Zustand异步操作:如何确保useStore获取的最新状态? Zustand异步操作:如何确保useStore获取的最新状态? Apr 04, 2025 pm 02:09 PM

zustand异步操作中的数据更新问题在使用zustand状态管理库时,经常会遇到异步操作导致数据更新不及时的问题。�...

See all articles