idea 创建todo_创建具有节点和角度的单页Todo应用

idea 创建todo

Today we will be creating a very simple Todo application using the MEAN (Mongo, Express, Angular, Node) stack. We will be creating:

今天,我们将使用MEAN(Mongo,Express,Angular,Node)堆栈创建一个非常简单的Todo应用程序。 我们将创建:

  • Single page application to create and finish todos

    单页应用程序来创建和完成待办事项
  • Storing todos in a MongoDB using Mongoose

    使用Mongoose将待办事项存储在MongoDB中
  • Using the Express framework

    使用Express框架
  • Creating a RESTful Node API

    创建一个RESTful Node API
  • Using Angular for the frontend and to access the API

    使用Angular作为前端并访问API
This article has been updated for 本文已针对 ExpressJS 4.0. ExpressJS 4.0更新。

While the application is simple and beginner to intermediate level in its own right, the concepts here can apply to much more advanced apps. The biggest things we should focus on is using Node as an API and Angular as the frontend. Making them work together can be a bit confusing so this tutorial should help alleviate some confusion. Buckle those seatbelts; this could be a long one.

尽管该应用程序简单易行,并且具有初学者到中级的水平,但是此处的概念可以应用于更高级的应用程序。 我们应该重点关注的最大事情是使用Node作为API,使用Angular作为前端。 使它们协同工作可能会有些混乱,因此本教程应有助于减轻一些混乱。 扣紧那些安全带; 这可能会很长。

我们将要建设的 (What We'll Be Building)

todoaholic

基本设置 (Base Setup)

档案结构 (File Structure)

We are going to keep the file structure very simple and put most of the code for our Node application into the server.js file. In larger applications, this should be broken down further to separate duties. Mean.io is a good boilerplate to see best practices and how to separate file structure. Let's go ahead and create our simpler file structure and edit the files as we go along.

我们将使文件结构非常简单,并将Node应用程序的大部分代码放入server.js文件中。 在较大的应用程序中,应将其进一步分解为单独的职责。 Mean.io是查看最佳实践以及如何分隔文件结构的好样板。 让我们继续创建更简单的文件结构,并在进行过程中编辑文件。

- public            <!-- holds all our files for our frontend angular application -->
    ----- core.js       <!-- all angular code for our app -->
    ----- index.html    <!-- main view -->
    - package.json      <!-- npm configuration to install dependencies/modules -->
    - server.js         <!-- Node configuration -->

安装模块 (Installing Modules)

In Node, the package.json file holds the configuration for our app. Node's package manager (npm) will use this to install any dependencies or modules that we are going to use. In our case, we will be using Express (popular Node framework) and Mongoose (object modeling for MongoDB).

在Node中, package.json文件保存了我们应用程序的配置。 Node的程序包管理器(npm)将使用它来安装我们将要使用的所有依赖项或模块。 在我们的案例中,我们将使用Express (流行的Node框架)和Mongoose (用于MongoDB的对象建模)。

{
  "name"         : "node-todo",
  "version"      : "0.0.0",
  "description"  : "Simple todo application.",
  "main"         : "server.js",
  "author"       : "Scotch",
  "dependencies" : {
    "express"    : "~4.7.2",
    "mongoose"   : "~3.6.2",
    "morgan"     : "~1.2.2",
    "body-parser": "~1.5.2",
    "method-override": "~2.1.2"
    }
}

Now if we run npm install, npm will look at this file and install Express and Mongoose.

现在,如果我们运行npm install ,npm将查看该文件并安装Express和Mongoose。

npm-install

节点配置 (Node Configuration)

In our package.json file, we told it that our main file would be server.js. This is the main file for our Node app and where we will configure the entire application.

package.json文件中,我们告诉我们主文件将是server.js 。 这是Node应用程序的主文件,我们将在其中配置整个应用程序。

This is the file where we will:

这是我们将要执行的文件:

  • Configure our application

    配置我们的应用程序
  • Connect to our database

    连接到我们的数据库
  • Create our Mongoose models

    创建我们的猫鼬模型
  • Define routes for our RESTful API

    为我们的RESTful API定义路由
  • Define routes for our frontend Angular application

    为我们的前端Angular应用程序定义路由
  • Set the app to listen on a port so we can view it in our browser

    将应用程序设置为侦听端口,以便我们可以在浏览器中查看它

For now, we will just configure the app for Express, our MongoDB database, and listening on a port.

现在,我们仅将应用程序配置为Express,我们的MongoDB数据库并在端口上侦听。

// server.js

    // set up ========================
    var express  = require('express');
    var app      = express();                               // create our app w/ express
    var mongoose = require('mongoose');                     // mongoose for mongodb
    var morgan = require('morgan');             // log requests to the console (express4)
    var bodyParser = require('body-parser');    // pull information from HTML POST (express4)
    var methodOverride = require('method-override'); // simulate DELETE and PUT (express4)

    // configuration =================

    mongoose.connect('mongodb://node:nodeuser@mongo.onmodulus.net:27017/uwO3mypu');     // connect to mongoDB database on modulus.io

    app.use(express.static(__dirname + '/public'));                 // set the static files location /public/img will be /img for users
    app.use(morgan('dev'));                                         // log every request to the console
    app.use(bodyParser.urlencoded({'extended':'true'}));            // parse application/x-www-form-urlencoded
    app.use(bodyParser.json());                                     // parse application/json
    app.use(bodyParser.json({ type: 'application/vnd.api+json' })); // parse application/vnd.api+json as json
    app.use(methodOverride());

    // listen (start app with node server.js) ======================================
    app.listen(8080);
    console.log("App listening on port 8080");

Just with that bit of code, we now have an HTTP server courtesy of Node. We have also created an app with Express and now have access to many benefits of it. In our app.configure section, we are using express modules to add more functionality to our application.

仅需少量的代码,我们现在就拥有一个由Node提供的HTTP服务器。 我们还使用Express创建了一个应用程序,现在可以使用它的许多好处。 在我们的app.configure部分中,我们使用快速模块向我们的应用程序添加更多功能。

数据库设置 (Database Setup)

We will be using a remote database hosted on Modulus.io. They provide a great service and give you $15 upfront to use as you see fit. This is great for doing testing and creating databases on the fly.

我们将使用Modulus.io上托管的远程数据库。 他们提供优质的服务,并给您15美元的预付款,以供您酌情使用。 这非常适合即时进行测试和创建数据库。

Modulus will provide the database URL you need and you can use mongoose.connect to connect to it. That's it.

Modulus将提供您所需的数据库URL,您可以使用mongoose.connect进行连接。 而已。

启动您的应用程序! (Start Your App!)

Now that we have our package.json and server.js started up, we can start up our server and see what's going on. Just go into your console and use the following command:

现在我们已经启动了package.jsonserver.js ,我们可以启动服务器,看看发生了什么。 只需进入控制台并使用以下命令:

node server.js Now you have a server listening on port 8080. You can't see anything in your browser at http://localhost:8080 yet since we didn't configure our application to output anything. But it's a start!

node server.js现在,您有一个服务器正在侦听端口8080。由于我们没有将应用程序配置为输出任何内容,因此您无法在浏览器中的http:// localhost:8080看到任何内容。 但这是一个开始!

Automatically restart server when files change: By default, node will not monitor for file changes after your server has been started. This means you'd have to shut down and start the server every time you made a file change. This can be fixed with nodemon. To use: install nodemon globally npm install -g nodemon. Start your server with nodemon server.js now. Smooth sailing from there.
文件更改时自动重新启动服务器:默认情况下, 启动服务器后 ,节点将不监视文件更改。 这意味着每次更改文件时都必须关闭并启动服务器。 这可以用 nodemon修复 。 要使用:全局安装nodemon npm install -g nodemon 。 立即使用 nodemon server.js启动服务器。 从那里航行顺畅。

申请流程 (Application Flow)

Now a brief overview of how all our moving parts will work together. There are a lot of different ideas and technologies involved in this application that it is easy to get mixed up with them all. In our diagram below, we explain a bit of the separation of tasks and how the parts tie in together.

现在简要概述一下我们所有的运动部件将如何协同工作。 此应用程序涉及许多不同的思想和技术,很容易将它们混淆在一起。 在下面的图表中,我们解释了一些任务分离以及各部分如何结合在一起。

mean

Angular is on its own in the frontend. It accesses all the data it needs through the Node API. Node hits the database and returns JSON information to Angular based on the RESTful routing.

Angular在前端是独立的。 它通过Node API访问所需的所有数据。 节点访问数据库,并基于RESTful路由将JSON信息返回到Angular。

This way, you can separate the frontend application from the actual API. If you want to extend the API, you can always build more routes and functions into it without affecting the frontend Angular application. This way you can eventually build different apps on different platforms since you just have to hit the API.

这样,您可以将前端应用程序与实际的API分开。 如果要扩展API,则始终可以在其中构建更多路由和功能,而不会影响前端Angular应用程序。 这样,您最终可以在不同的平台上构建不同的应用程序,因为您只需要点击API。

创建我们的节点API (Creating Our Node API)

Before we get to the frontend application, we need to create our RESTful API. This will allow us to have an api that will get all todos, create a todo, and complete and delete a todo. It will return all this information in JSON format.

在进入前端应用程序之前,我们需要创建我们的RESTful API。 这将使我们拥有一个将获取所有 待办事项创建待办事项以及完成并删除待办事项的api。 它将以JSON格式返回所有这些信息。

待办事项模型 (Todo Model)

We must define our model for our Todos. We'll keep this simple. After the configuration section and before the listen section, we'll add our model.

我们必须为Todos定义模型。 我们将保持简单。 在配置部分之后侦听部分之前,我们将添加模型。

// define model =================
    var Todo = mongoose.model('Todo', {
        text : String
    });

That is all we want. Just the text for the todo. MongoDB will automatically generate an _id for each todo that we create also.

那就是我们想要的。 只是待办事项的文字。 MongoDB将为我们创建的每个待办事项自动生成一个_id

RESTful API路由 (RESTful API Routes)

Let's generate our Express routes to handle our API calls.

让我们生成Express路由来处理API调用。

// server.js
...

// routes ======================================================================

    // api ---------------------------------------------------------------------
    // get all todos
    app.get('/api/todos', function(req, res) {

        // use mongoose to get all todos in the database
        Todo.find(function(err, todos) {

            // if there is an error retrieving, send the error. nothing after res.send(err) will execute
            if (err)
                res.send(err)

            res.json(todos); // return all todos in JSON format
        });
    });

    // create todo and send back all todos after creation
    app.post('/api/todos', function(req, res) {

        // create a todo, information comes from AJAX request from Angular
        Todo.create({
            text : req.body.text,
            done : false
        }, function(err, todo) {
            if (err)
                res.send(err);

            // get and return all the todos after you create another
            Todo.find(function(err, todos) {
                if (err)
                    res.send(err)
                res.json(todos);
            });
        });

    });

    // delete a todo
    app.delete('/api/todos/:todo_id', function(req, res) {
        Todo.remove({
            _id : req.params.todo_id
        }, function(err, todo) {
            if (err)
                res.send(err);

            // get and return all the todos after you create another
            Todo.find(function(err, todos) {
                if (err)
                    res.send(err)
                res.json(todos);
            });
        });
    });

...

Based on these routes, we've built a table to explain how a frontend application should request data from the API.

基于这些路由,我们构建了一个表来解释前端应用程序应如何从API请求数据。

HTTP Verb URL Description
GET /api/todos Get all of the todos
POST /api/todos Create a single todo
DELETE /api/todos/:todo_id Delete a single todo
HTTP动词 网址 描述
得到 / api / todos 获取所有待办事项
开机自检 / api / todos 创建一个待办事项
删除 / api / todos /:todo_id 删除一个待办事项

Inside of each of our API routes, we use the Mongoose actions to help us interact with our database. We created our Model earlier with var Todo = mongoose.model and now we can use that to find, create, and remove. There are many more things you can do and I would suggest looking at the official docs to learn more.

在我们的每个API路由中,我们使用Mongoose操作来帮助我们与数据库进行交互。 我们之前使用var Todo = mongoose.model创建了模型,现在可以使用它来查找创建删除 。 您还可以做更多的事情,我建议您看一下官方文档以了解更多信息。

Our API is done! Rejoice! If you start up your application, you can interact with it at localhost:8080/api/todos to get all the todos. There won't be anything currently since you haven't added any.

我们的API已完成! 麾! 如果启动应用程序,则可以在localhost:8080/api/todos与之交互以获取所有待办事项。 由于您尚未添加任何内容,因此目前没有任何内容。

Angular的前端应用程序 (Frontend Application with Angular)

We have created a Node application, configured our database, generated our API routes, and started a server. So much already done and still a little bit longer to go!

我们已经创建了Node应用程序配置了数据库生成了API路由 ,并启动了服务器 。 已经完成了很多工作,还有很长的路要走!

The work that we've done so far can stand on its own as an application. It can be an API we use let applications and users connect with our content.

到目前为止,我们所做的工作可以作为应用程序独立存在。 它可以是我们用来让应用程序和用户与我们的内容连接的API。

We want to be the first to use our brand new API that we've just created. This is one of my favorite terms that I learned about last month: We will be dogfooding. We could treat this as we are our very first client to use our new API. We are going to keep this simple so we'll have just our index.html and core.js to define our frontend.

我们希望成为第一个使用我们刚刚创建的全新API的人。 这是我上个月了解到的我最喜欢的术语之一:我们将成为狗粮 。 我们可以将其视为第一位使用新API的客户端。 我们将使其保持简单,以便仅使用index.htmlcore.js定义前端。

定义前端路由 (Defining Frontend Route)

We have already defined our API routes. Our application's API is accessible from /api/todos, but what about our frontend? How do we display the index.html file at our home page?

我们已经定义了API路由。 我们的应用程序的API可从/api/todos访问,但是我们的前端呢? 我们如何在主页上显示index.html文件?

We will add one route to our server.js file for the frontend application. This is all we need to do since Angular will be making a single page application and handle the routing.

我们将为前端应用程序向我们的server.js文件添加一条路由。 这是我们需要做的所有事情,因为Angular将制作一个单页应用程序并处理路由。

After our API routes, and before the app.listen, add this route:

在我们的API路由之后,在app.listen之前,添加以下路由:

// server.js
...
    // application -------------------------------------------------------------
    app.get('*', function(req, res) {
        res.sendfile('./public/index.html'); // load the single view file (angular will handle the page changes on the front-end)
    });
...

This will load our single index.html file when we hit localhost:8080.

当我们点击localhost:8080时,这将加载我们的单个index.html文件。

设置Angular core.js (Setting Up Angular core.js)

Let's go through our Angular setup first. We have to create a module, create a controller, and define functions to handle todos. Then we can apply to view.

让我们首先进行Angular设置。 我们必须创建一个模块创建一个控制器 ,并定义函数来处理待办事项 。 然后我们可以申请查看

// public/core.js
var scotchTodo = angular.module('scotchTodo', []);

function mainController($scope, $http) {
    $scope.formData = {};

    // when landing on the page, get all todos and show them
    $http.get('/api/todos')
        .success(function(data) {
            $scope.todos = data;
            console.log(data);
        })
        .error(function(data) {
            console.log('Error: ' + data);
        });

    // when submitting the add form, send the text to the node API
    $scope.createTodo = function() {
        $http.post('/api/todos', $scope.formData)
            .success(function(data) {
                $scope.formData = {}; // clear the form so our user is ready to enter another
                $scope.todos = data;
                console.log(data);
            })
            .error(function(data) {
                console.log('Error: ' + data);
            });
    };

    // delete a todo after checking it
    $scope.deleteTodo = function(id) {
        $http.delete('/api/todos/' + id)
            .success(function(data) {
                $scope.todos = data;
                console.log(data);
            })
            .error(function(data) {
                console.log('Error: ' + data);
            });
    };

}

We create our Angular module (scotchApp) and controller (mainController).

我们创建了Angular模块( scotchApp )和控制器( mainController )。

We also create our functions to get all todos, create a todo, and delete a todo. All these will be hitting the API we just created. On page load, we will GET /api/todos and bind the JSON we receive from the API to $scope.todos. We will then loop over these in our view to make our todos.

我们还创建函数以获取所有 待办事项创建待办事项删除待办事项 。 所有这些都会影响我们刚刚创建的API。 在页面加载时,我们将GET /api/todos并将从API收到的JSON绑定到$scope.todos 。 然后,我们将循环查看这些内容以完成待办事项。

We'll follow a similar pattern for creating and deleting. Run our action, remake our todos list.

我们将遵循类似的创建和删除模式。 运行我们的动作,重新制作待办事项列表。

前端视图index.html (Frontend View index.html)

Here we will keep it simple. This is the HTML needed to interact with Angular. We will:

在这里,我们将使其保持简单。 这是与Angular交互所需HTML。 我们会:

  • Assign Angular module and controller

    分配Angular模块和控制器
  • Initialize the page by getting all todos

    通过获取所有待办事项来初始化页面
  • Loop over the todos

    循环待办事项
  • Have a form to create todos

    有创建待办事项的表格
  • Delete todos when they are checked

    检查待办事项时删除待办事项
<!-- index.html -->
<!doctype html>

<!-- ASSIGN OUR ANGULAR MODULE -->
<html ng-app="scotchTodo">
<head>
    <!-- META -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1"><!-- Optimize mobile viewport -->

    <title>Node/Angular Todo App</title>

    <!-- SCROLLS -->
    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css"><!-- load bootstrap -->
    <style>
        html                    { overflow-y:scroll; }
        body                    { padding-top:50px; }
        #todo-list              { margin-bottom:30px; }
    </style>

    <!-- SPELLS -->
    <script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script><!-- load jquery -->
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js"></script><!-- load angular -->
    <script src="core.js"></script>

</head>
<!-- SET THE CONTROLLER AND GET ALL TODOS -->
<body ng-controller="mainController">
    <div class="container">

        <!-- HEADER AND TODO COUNT -->
        <div class="jumbotron text-center">
            <h1>I'm a Todo-aholic <span class="label label-info">{{ todos.length }}</span></h1>
        </div>

        <!-- TODO LIST -->
        <div id="todo-list" class="row">
            <div class="col-sm-4 col-sm-offset-4">

                <!-- LOOP OVER THE TODOS IN $scope.todos -->
                <div class="checkbox" ng-repeat="todo in todos">
                    <label>
                        <input type="checkbox" ng-click="deleteTodo(todo._id)"> {{ todo.text }}
                    </label>
                </div>

            </div>
        </div>

        <!-- FORM TO CREATE TODOS -->
        <div id="todo-form" class="row">
            <div class="col-sm-8 col-sm-offset-2 text-center">
                <form>
                    <div class="form-group">

                        <!-- BIND THIS VALUE TO formData.text IN ANGULAR -->
                        <input type="text" class="form-control input-lg text-center" placeholder="I want to buy a puppy that will love me forever" ng-model="formData.text">
                    </div>

                    <!-- createToDo() WILL CREATE NEW TODOS -->
                    <button type="submit" class="btn btn-primary btn-lg" ng-click="createTodo()">Add</button>
                </form>
            </div>
        </div>

    </div>

</body>
</html>

Take a look at what we have.

看看我们有什么。

todoaholic

结论 (Conclusion)

Now we have a fully working application that will show, create, and delete todos all via API (that we built!). That was quite a day. We've done so much. Just an overview of what we've accomplished:

现在,我们有了一个可以正常运行的应用程序,它将通过API(我们自己构建的)显示,创建和删除待办事项。 那真是一天。 我们做了很多。 只是我们已完成的工作的概述:

  • RESTful Node API using Express

    使用Express的RESTful Node API
  • MongoDB interaction using mongoose

    使用猫鼬的MongoDB交互
  • Angular AJAX $http calls

    Angular AJAX $ http调用
  • Single page application w/ no refreshes

    单页应用程序,无刷新
  • Dogfooding (sorry, I really like that word)

    狗食(对不起,我真的很喜欢这个词)

测试应用 (Test the Application)

Go ahead and download the code on Github and tweak it or test it. To get it all up and running:

继续并在Github上下载代码并对其进行调整或测试。 要使其全部正常运行:

  1. Make sure you have Node and npm installed

    确保已安装Node和npm
  2. Clone the repo: git clone git@github.com:scotch-io/node-todo

    克隆仓库: git clone git@github.com:scotch-io/node-todo
  3. Install the application: npm install

    安装应用程序: npm install
  4. Start the server: node server.js

    启动服务器: node server.js
  5. View in your browser at http://localhost:8080

    在浏览器中查看位于http://localhost:8080

I hope this was insightful on how to have lots of moving parts work together. In the future, we will look at separating our server.js file since that got a little crazy.

我希望这对如何使许多活动部件协同工作很有见地。 将来,我们将着眼于分离server.js文件,因为这样做有点疯狂。

进一步阅读如果您对更多MEAN堆栈应用程序感兴趣,我们编写了指南,以帮助您开始构建自己的MEAN堆栈基础。 (Further Reading If you are interested in more MEAN stack applications, we've written up a guide to get you started in building your own MEAN stack foundation.)

Setting Up a MEAN Stack Single Page Application

设置MEAN Stack单页应用程序

Edit #1: Removing ng-init 编辑#1:删除ng-init
Node and Angular To-Do App series. Node and Angular To-Do App系列的一部分。
  1. Creating a Single Page To-do App with Node and Angular

    使用节点和角度创建单页待办事项应用程序
  2. Node Application Organization and Structure

    节点应用程序的组织和结构
  3. Angular Modules: Controllers and Services

    角模块:控制器和服务

翻译自: https://scotch.io/tutorials/creating-a-single-page-todo-app-with-node-and-angular

idea 创建todo

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值