Node.js と Geddy を使用してタスク マネージャー アプリケーションを構築する

WBOY
リリース: 2023-08-28 09:37:05
オリジナル
889 人が閲覧しました

この 3 部構成のチュートリアルでは、Node.js と Geddy を使用して To Do リスト管理アプリケーションを作成する方法を詳しく説明します。シリーズの第 2 部では、シンプルな To Do リスト管理アプリケーションを作成します。


###レビュー###

簡単にまとめると、前回は Node と Geddy をインストールし、新しいアプリケーションを生成し、サーバーを起動する方法を学びました。このチュートリアルでは、前回行った内容を基に進めていきますので、続行する前に必ずこのチュートリアルを完了してください。

Todo リソースを生成する

Geddy にはリソース ジェネレーターが組み込まれており、これにより特定のリソースのモデル、コントローラー、ビュー、ルートを自動的に生成できます。この ToDo リスト アプリケーションには、

todo

というリソースが 1 つだけあります。これを生成するには、cd をアプリケーションのディレクトリ (cd path/to/your/todo_app) に入れて、次のコマンドを実行します。 リーリー これで、次のファイルがアプリに追加されるはずです:

app/models/todo.js

    app/controllers/todos.js
  • アプリケーション/ビュー/todos/
  • index.html.ejs
    • show.html.ejs
    • edit.html.ejs
    • add.html.ejs
    あなたの
  • config/router.js
には次の追加も必要です:

リーリー それが何をするか

MVC を初めて使用する場合、これはすべて少し気が遠くなるかもしれません。しかし、心配しないでください。一度理解すれば非常に簡単です。

models/todo.js

: このファイルは、

todo モデルを定義する場所です。すべての todo が持つ多数のプロパティを定義します。ここでデータ検証も書きます。 controllers/todos.js

: このファイルは、すべての

/todos/ ルートの最終的な場所です。このコントローラーの各アクションには、対応するルートがあります: リーリー views/todos/

: ここの各ファイルは、上で示した

GET ルートの 1 つに対応します。これらは、アプリケーションのフロントエンドを生成するために使用するテンプレートです。 Geddy は、テンプレート言語として EJS (Embedded JavaScript) を使用します。 PHP または ERB を使用したことがある場合は、これに見覚えがあるはずです。基本的に、テンプレートでは任意の JavaScript を使用できます。 ルートを感じる

大量のコードを生成したので、必要なルートがすべて揃っていることを確認してみましょう。アプリケーション (

geddy

) を再度起動し、ブラウザで http://localhost:4000/todos を指定します。次のようなものが表示されるはずです

使用 Node.js 和 Geddy 构建任务管理器应用程序引き続き他の 使用 Node.js 和 Geddy 构建任务管理器应用程序GET使用 Node.js 和 Geddy 构建任务管理器应用程序 ルートを試してください:

http://localhost:4000/todos/something

    http://localhost:4000/todos/add
  • http://localhost:4000/todos/something/edit
  • 大丈夫ですか?さて、続けましょう。

Todo モデルの作成


Geddy (および他のほとんどの MVC フレームワーク) では、モデルを使用してアプリケーションが使用するデータ型を定義します。

todo

のモデルを生成したので、それが何をもたらすかを見てみましょう:

リーリー Geddy のモデルは非常にシンプルです。 todo

s の新しいコンストラクターを作成し、それを geddy にモデルとして登録するだけです。

todo のプロパティをいくつか定義しましょう。コメントアウトされたコードをすべて削除し、コンストラクターに追加します: リーリー 私たちの todo

にはタイトル、ID、ステータスがあり、3 つすべてが必須です。次に、

todo の検証を設定しましょう。 リーリー ヘッダーが存在することを確認しています。ヘッダーの最小長は 5 文字で、関数を使用してステータスが open

または

done であることを確認しています。組み込みの検証関数が多数あります。詳細については、http://github.com/mde/geddy でプロジェクトをチェックしてください。 Todo モデル アダプターの作成


To Do モデルを設定したので、モデルを保存する場所を作成できます。このチュートリアルでは、データをメモリ内に保持するだけです。データを保持するために、グローバル

geddy

オブジェクトに todos 配列を掛けます。このシリーズの次のパートでは、このデータをデータベースに保存することを開始します。

init.js ファイルを編集します

config/init.js

ファイルを開きます。これで、グローバルなキャッチされない例外ハンドラーが存在するはずです:

// Add uncaught-exception handler in prod-like environments
if (geddy.config.environment != 'development') {
  process.addListener('uncaughtException', function (err) {
    geddy.log.error(JSON.stringify(err));
  });
}
ログイン後にコピー

在该代码块之后,让我们将数组挂在 geddy 全局上:

geddy.todos = [];
ログイン後にコピー

现在我们有了一个地方来存储 todos。请记住,它位于您的应用程序内存中,因此当您重新启动服务器时它将消失。

创建模型适配器

模型适配器提供模型所需的基本 saveremoveloadall 方法。我们的数据源非常简单(只是一个数组!),因此编写模型适配器也应该非常简单。

lib 中创建一个名为 model_adapters 的目录,并在 lib/model_adapters 中创建一个名为 todo.js 的文件。让我们打开该文件并添加一些样板代码:

var Todo = new (function () {
})();
exports.Todo = Todo;
ログイン後にコピー

我们在这里所做的就是设置一个新的空白对象,将其导出到最终需要此文件的任何地方。如果您想更多地了解 Node 的 require 方法是如何工作的,这篇文章有一个很好的概述。在这种情况下,我们的 init.js 文件将满足要求。

需要 init.js 中的模型适配器

因此我们设置了一个新的 Todo 模型适配器对象。现在还很贫瘠,但我们很快就会做到这一点。现在,我们必须返回 init.js 并添加一些代码,以便在启动时将其加载到我们的应用程序中。在 config/init.js 中的 geddy.todos = []; 之后添加这两行:

geddy.model.adapter = {};
geddy.model.adapter.Todo = require(process.cwd() + '/lib/model_adapters/todo').Todo;
ログイン後にコピー

我们创建了一个空白的模型适配器对象,并向其添加了 Todo 模型适配器。


保存待办事项

现在我们已经有了模型和模型适配器,我们可以开始应用程序逻辑了。让我们首先将待办事项添加到我们的待办事项列表中。

编辑适配器上的保存方法以保存待办事项实例

处理数据时,首先应该去的地方是模型适配器。我们需要能够将 Todo 模型的实例保存到 geddy.todos 数组中。因此,打开 lib/model_adapters/todo.js 并添加保存方法:

var Todo = new (function () {
  this.save = function (todo, opts, callback) {

    if (typeof callback != 'function') {
      callback = function(){};
    }

    todo.saved = true;
    geddy.todos.push(todo);
    return callback(null, todo);

  }
})();
ログイン後にコピー

我们所要做的就是将实例的保存属性设置为 true 并将项目推送到 geddy.todos 数组中。在 Node 中,最好以非阻塞方式执行所有 I/O,因此养成使用回调传递数据的习惯是个好主意。对于本教程来说,这并不重要,但稍后当我们开始持久化事物时,它会派上用场。您会注意到我们确保回调是一个函数。如果我们不这样做并在没有回调的情况下使用 save,我们会收到错误。现在让我们继续控制器创建操作。

编辑创建操作以保存待办事项实例

继续看一下 app/controllers/todos.js 中的 create 操作:

this.create = function (req, resp, params) {
  // Save the resource, then display index page
  this.redirect({controller: this.name});
};
ログイン後にコピー

很简单,对吧?盖迪已经帮你把它记下来了。那么我们来稍微修改一下:

this.create = function (req, resp, params) {
  var self = this
    , todo = geddy.model.Todo.create({
        title: params.title
      , id: geddy.string.uuid(10)
      , status: 'open'
      });
  todo.save(function (err, data) {
    if (err) {
      params.errors = err;
      self.transfer('add');
    }
    else {
      self.redirect({controller: self.name});
    }
  });
};
ログイン後にコピー

首先,我们使用 geddy.model.Todo.create 创建一个 Todo 模型的新实例,传入表单将发布给我们的标题,并设置 id 和状态的默认值。< /p>

然后我们调用在模型适配器上创建的 save 方法并将用户重定向回 /todos 路由。如果它没有通过验证,或者我们收到错误,我们使用控制器的 transfer 方法将请求传输回 add 操作。

编辑add.html.js

现在是我们设置添加模板的时候了。看一下 app/views/todos/add.html.ejs,它应该看起来像这样:

<div class="hero-unit">
  <h3>Params</h3>
  <ul>
  <% for (var p in params) { %>
    <li><%= p + ': ' + params[p]; %></li>
  <% } %>
  </ul>
</div>
ログイン後にコピー
ログイン後にコピー

我们不需要 <ul></ul> 对于我们的用例来说,所以让我们暂时摆脱它。让你的 add.html.ejs 看起来像这样:

<div class="hero-unit">
  <%= partial('_form', {params: params}); %>
</div>
ログイン後にコピー

分音简介

Partials 为您提供了一种在模板之间共享代码的简单方法。

您会注意到我们在此模板中使用了部分内容。部分为您提供了一种在模板之间共享代码的简单方法。我们的添加和编辑模板都将使用相同的表单,所以现在让我们创建这个表单部分。在 views/todos/ 目录中创建一个名为 _form.html.ejs 的新文件。我们使用下划线来轻松判断该模板是否是部分模板。打开它并添加以下代码:

<%
  var isUpdate = params.action == 'edit'
    , formTitle = isUpdate ? 'Update this To Do Item' : 'Create a new To Do Item'
    , action = isUpdate ? '/todos/' + todo.id + '?_method=PUT' : '/todos'
    , deleteAction = isUpdate ? '/todos/' + todo.id + '?_method=DELETE' : ''
    , btnText = isUpdate ? 'Update' : 'Add'
    , doneStatus = isUpdate ? 'checked' : ''
    , titleValue = isUpdate ? todo.title : ''
    , errors = params.errors;
%>
<form id="todo-form" class="form-horizontal" action="<%= action %>" method="POST">
  <fieldset>
    <legend><%= formTitle %></legend>
    <div class="control-group">
      <label for="title" class="control-label">Title</label>
      <div class="controls">
        <input type="text" class="span6" placeholder="enter title" name="title" value='<%= titleValue %>'/>
        <%  if (errors) { %>
          <p>
          <% for (var p in errors) { %>
            <div><%=  errors[p];  %></div>
          <% } %>
          </p>
        <% } %>
      </div>
    </div>
    <% if (isUpdate) { %>
      <div class="control-group">
        <label for="status">Status</label>
        <div class="controls">
          <select name="status">
            <option>open</option>
            <option>done</option>
          </select>
        </div>
      </div>
    <% } %>
    <div class="form-actions">
      <input type="submit" class="btn btn-primary" value="<%= btnText %>"/>
      <% if (isUpdate) { %>
        <button type="submit" formaction="<%= deleteAction %>" formmethod="POST" class="btn btn-danger">Remove</button>
      <% } %>
    </div>
  </fieldset>
</form>
ログイン後にコピー

哇,那里有很多代码!让我们看看是否可以通过它。由于两个不同的模板将使用此部分,因此我们必须确保表单在两个模板中看起来都正确。大部分代码实际上是来自 Twitter Bootstrap 的样板。这就是让这个应用程序立即看起来如此出色的原因(在移动设备上也是如此!)。

为了使此应用程序看起来更好,您可以使用演示应用程序下载中提供的 CSS 文件。

我们做的第一件事是设置一些变量供我们使用。在 add 操作中,我们将 params 对象传递给 respond 方法调用中的模板。这给了我们一些信息——它告诉我们这个请求被路由到哪个控制器和操作,并给我们提供了在 url 中传递的任何查询参数。我们设置 isUpdate 变量来查看当前是否正在进行更新操作,然后我们设置更多变量来帮助清理视图代码。

从那里,我们所做的就是制作一个表格。如果我们执行添加操作,我们只需按原样渲染表单即可。如果我们正在进行编辑操作,我们会填写表单以让用户更新字段。

请注意,该表单将使用 _method=PUT 参数向 /todos/ 发送 POST 请求。 Geddy 使用标准方法覆盖参数,允许您从浏览器发送 PUTDELETE 请求,而无需使用 JavaScript。 (至少在前端!)

我们需要看的最后一个小细节是“删除”按钮。我们使用 html5 的 formaction 属性来更改此表单的操作。您会注意到此按钮的 formactionPOST 请求发送到 /todos/:id 路由,并带有 _method=DELETE 参数。这将在控制器上执行 remove 操作,我们稍后会介绍。

重新启动服务器 (geddy) 并访问 http://localhost:4000/todos/add 以查看正在运行的模板。创建一个待办事项。


列出所有待办事项

现在我们已经将用户输入的待办事项添加到了 geddy.todos 数组中,我们可能应该将它们列出在某个地方。让我们从模型适配器中的 all 方法开始。

编辑适配器上的 all 方法以列出所有待办事项

让我们再次打开 lib/model_adapters/todo.js 并在 save` 方法上方添加一个 all 方法:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:javascript;toolbal:false;">this.all = function (callback) { callback(null, geddy.todos); } </pre><div class="contentsignin">ログイン後にコピー</div></div> <p>这可能是我们今天要创建的最简单的模型适配器方法,它所做的就是接受回调并调用它并返回错误(目前始终为 null,我们将在下一个版本中升级此方法)教程)和 <code>geddy.todos

编辑索引操作以显示所有待办事项

再次打开 /app/controllers/todos.js 并查看 index 操作。它应该看起来像这样:

this.index = function (req, resp, params) {
  this.respond({params: params});
};
ログイン後にコピー

这部分非常简单,我们只需使用我们刚刚在模型适配器上定义的 all 方法来获取所有 todo 并渲染它们:

this.index = function (req, resp, params) {
  var self = this;
  geddy.model.adapter.Todo.all(function(err, todos){
    self.respond({params: params, todos: todos});
  });
};
ログイン後にコピー

这就是控制器的内容,现在进入视图。

编辑index.html.ejs

看一下 /app/views/todos/index.html.ejs,它应该如下所示:

<div class="hero-unit">
  <h3>Params</h3>
  <ul>
  <% for (var p in params) { %>
    <li><%= p + ': ' + params[p]; %></li>
  <% } %>
  </ul>
</div>
ログイン後にコピー
ログイン後にコピー

看起来很像 add.html.ejs 模板,不是吗?同样,我们在这里不需要 params 样板,因此将其取出,并使您的 index.html.ejs 模板如下所示:

<div class="hero-unit">
  <h2>To Do List</h2>
  <a href="/todos/add" class="btn pull-right">Create a new To Do</a></p>
</div>
<% if (todos &amp;&amp; todos.length) { %>
  <% for (var i in todos) { %>
  <div class="row todo-item">
    <div class="span8"><h3><a href="/todos/<%= todos[i].id; %>/edit"><%= todos[i].title; %></a></h3></div>
    <div class="span4"><h3><i class="icon-list-alt"></i><%= todos[i].status; %></h3></div>
  </div>
  <% } %>
<% } %>
ログイン後にコピー

这个也非常简单,但是这次我们的模板中有一个循环。在标题中,我们添加了一个按钮来添加新的待办事项。在循环内,我们为每个 todo 生成一行,显示其标题(作为指向 edit 页面的链接)及其状态。

要查看它,请访问 http://localhost:4000/todos。


编辑全部

现在我们有了 edit 页面的链接,我们应该可以让它工作了!

在模型适配器中创建加载方法

再次打开模型适配器 (/lib/model_adapters/todo.js)。我们将添加 load 方法,以便我们可以加载特定的 todo 并在我们的编辑页面中使用它。添加到哪里并不重要,但现在让我们将其放在 all 方法和 save 方法之间:

this.load = function (id, callback) {
  for (var i in geddy.todos) {
    if (geddy.todos[i].id == id) {
      return callback(null, geddy.todos[i]);
    }
  }
  callback({message: "To Do not found"}, null);
};
ログイン後にコピー

此加载方法需要一个 id 和一个回调。它循环遍历 geddy.todos 中的项目,并检查当前项目的 id 是否与传入的 id 匹配。如果是,则调用回调,并将 todo 项传回。如果找不到匹配项,则会调用回调并返回错误。现在我们需要在 todos 控制器的 show 操作中使用此方法。

编辑编辑操作以查找待办事项

再次打开 todos 控制器并查看它的 edit 操作。它应该看起来像这样:

this.edit = function (req, resp, params) {
  this.respond({params: params});
};
ログイン後にコピー

让我们使用刚刚创建的加载方法:

this.edit = function (req, resp, params) {
  var self = this;
  geddy.model.Todo.load(params.id, function(err, todo){
    self.respond({params: params, todo: todo});
  });
};
ログイン後にコピー

我们在这里所做的就是加载待办事项并将其发送到要渲染的模板。那么让我们看一下模板。

编辑edit.html.ejs

打开/app/views/todos/edit.html.ejs。我们再次不需要 params 样板,所以让我们删除它。让你的 edit.html.ejs 看起来像这样:

<div class="hero-unit">
  <%= partial('_form', {params: params, todo: todo}); %>
</div>
ログイン後にコピー

这应该与我们刚刚编辑的 add.html.ejs 文件非常相似。您会注意到,这次我们将 todo 对象发送到部分以及参数。很酷的是,由于我们已经编写了部分内容,因此这就是我们所要做的以使编辑页面正确显示。

重新启动服务器,创建一个新的 todo 并单击链接以查看其工作原理。现在让我们让更新按钮起作用!

编辑模型适配器中的保存方法

再次打开模型适配器并找到 save 方法。我们将添加一些内容,以便我们可以保存现有的 todos。让它看起来像这样:

this.save = function (todo, opts, callback) {
  if (typeof callback != 'function') {
    callback = function(){};
  }
  var todoErrors = null;
  for (var i in geddy.todos) {
    // if it's already there, save it
    if (geddy.todos[i].id == todo.id) {
      geddy.todos[i] = todo;
      todoErrors = geddy.model.Todo.create(todo).errors;
      return callback(todoErrors, todo);
    }
  }
  todo.saved = true;
  geddy.todos.push(todo);
  return callback(null, todo);
}
ログイン後にコピー

这会循环 geddy.todos 中的所有待办事项,如果 id 已经存在,它将用新的 todo 实例替换 todo 。我们在这里做了一些事情,以确保我们的验证在更新和创建时都有效 - 为了做到这一点,我们必须从新模型实例中提取 errors 属性,并将其传递回回调中。如果它通过了验证,它只是未定义的,我们的代码将忽略它。如果没有通过,todoErrors 将是一个验证错误数组。

现在我们已经完成了,让我们来处理控制器的 update 操作。


编辑更新操作以查找待办事项、更改状态并保存

继续再次打开控制器并找到“更新”操作,它应该如下所示:

this.update = function (req, resp, params) {
  // Save the resource, then display the item page
  this.redirect({controller: this.name, id: params.id});
};
ログイン後にコピー

您需要对其进行编辑,使其看起来像这样:

this.update = function (req, resp, params) {
  var self = this;
  geddy.model.adapter.Todo.load(params.id, function (err, todo) {
    todo.status = params.status;
    todo.title = params.title;
    todo.save(function (err, data) {
      if (err) {
        params.errors = err;
        self.transfer('edit');
      }
      else {
        self.redirect({controller: self.name});
      }
    });
  });
};
ログイン後にコピー

我们在这里所做的是加载请求的 todo,编辑它的一些属性,然后再次保存 todo。我们刚刚在模型适配器中编写的代码应该处理其余的事情。如果我们收到错误,则意味着新属性未通过验证,因此我们会将请求传输回 edit 操作。如果我们没有收到错误,我们将把请求重定向回 index 操作。

来吧,尝试一下。重新启动服务器,创建一个新的todo,点击它的编辑链接,将状态更改为done,并在index中看到它已更新。如果您想验证验证是否有效,请尝试将 title 更改为少于 5 个字符的内容。

现在让“删除”按钮发挥作用。


删除待办事项

现在我们已经有了一个待办事项列表应用程序,但是如果您开始使用它一段时间,那么在该索引页面上找到您要查找的 todo 项目将会变得很困难。让我们让“删除”按钮起作用,这样我们就可以保持列表简洁明了。

在模型适配器中创建删除方法

让我们再次打开模型适配器,这次我们要在其中添加 remove 方法。在 save 方法之后添加此内容:

this.remove = function(id, callback) {
  if (typeof callback != 'function') {
    callback = function(){};
  }
  for (var i in geddy.todos) {
    if (geddy.todos[i].id == id) {
      geddy.todos.splice(i, 1);
      return callback(null);
    }
  }
  return callback({message: "To Do not found"});
}
ログイン後にコピー

这个非常简单,它应该看起来很像 load 方法。它循环遍历 geddy.todos 中的所有 todo 以找到我们要查找的 id。然后,它将该项目从数组中拼接出来并调用回调。如果在数组中找不到它,则会调用回调并返回错误。

现在让我们在控制器中使用它。

编辑删除操作

再次打开控制器并执行 remove 操作。它应该看起来像这样:

this.remove = function (req, resp, params) {
  this.respond({params: params});
};
ログイン後にコピー

编辑它,使其看起来像这样:

this.remove = function (req, resp, params) {
  var self = this;
  geddy.model.adapter.Todo.remove(params.id, function(err){
    if (err) {
      params.errors = err;
      self.transfer('edit');
    }
    else {
      self.redirect({controller: self.name});
    }
  });
}
ログイン後にコピー

我们将从表单 post 中的参数中获取的 id 传递到我们刚刚创建的 remove 方法中。如果返回错误,我们将重定向回 edit 操作(我们假设表单发布了错误的信息)。如果我们没有收到错误,只需将请求发送到 index 操作。

就是这样!我们完成了。

您可以通过重新启动服务器,创建一个新的 todo 项目,单击它的链接,然后单击“删除”按钮来测试删除功能。如果您做得正确,您应该会返回索引页并删除该项目。


后续步骤

在下一个教程中,我们将使用 http://i.tv 很棒的 mongodb-wrapper 模块将 todo 持久保存到 MongoDB 中。有了 Geddy,这一切就会很容易;我们需要改变的只是模型适配器。

ご質問がある場合は、ここにコメントするか、github で問題を提起してください。

以上がNode.js と Geddy を使用してタスク マネージャー アプリケーションを構築するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート