Nodejs + Express + MongoDBの実際の戦闘

プロジェクトのインストール
  1. エクスプレス足場をインストールします。npm install express-generator -g
  2. プロジェクトを作成します。express -e project-eはejsテンプレートの使用を表し、projectはプロジェクトの名前です。
  3. プロジェクトを入力してください:npm install依存関係パッケージをダウンロードしてください
  4. nodemonをインストールします。npm install nodemon -g開始するノードではなく、nodemonを使用してプロジェクトを開始します。
    ここに画像の説明を挿入
  5. スタートアッププロジェクト:npm start、ポート番号はwwwスタートアップファイルで確認できます。
プロジェクトはMongoDBデータベースに接続します
  1. nodejsと統合されたmongodbをインストールします。npm install mongodb -S

  2. プロジェクトにモデルファイルを作成し、以下にindex.jsを作成すると、データベースに接続されているすべてのコードがこのファイルにカプセル化されます。

     const MongoClient = require('mongodb').MongoClient;  // 创建Mongo的客户端对象
     const url = 'mongodb://localhost:27017';  // 连接数据库url
     const dbName = 'project';   // 连接的数据库名字
     // 数据库的连接方法封装
     function connect(callback){
         // 使用connect方法连接到服务器
         // err:错误对象。client:客户端连接成功的对象
         MongoClient.connect(url, function(err, client) {
             if(err){ // 如果连接错误,打印错误信息
                 console.log('数据库连接错误!',err);
             }else{  // 否则
                 const db = client.db(dbName);  // 数据库连接成功的对象
                 callback && callback(db);  // 利用回调函数处理
                 client.close();  // 每次调用成功,还要再关闭数据库
             }
         });
     }
     
     module.exports = {connect}
    
  3. 呼び出し:ルーティングを介してデータベースにデータを書き込むために使用されます

     var express = require('express');
     var router = express.Router();
     var model = require('../model');  // 引入连接数据库方法
     /* GET users listing. */
     router.get('/', function(req, res, next) {
       res.send('respond with a resource');
     });
     
     // 注册接口
     router.post('/regist',function(req, res, next){
       var data = {
         username:req.body.username,
         password:req.body.password,
         password2:req.body.password2
       }
       model.connect(function(db){
         db.collection('users').insert(data,function(err,ret){
           if(err){
             console.log('注册失败!',err);
             res.redirect('/regist');
           }else{
             res.redirect('/login');
           }
         })
       })
     })
     
     module.exports = router;
    
プロジェクトがMongoDBを導入した後のデータベース構文の操作
  1. 登録時に、ユーザー登録データをデータベースに書き込みます

     model.connect(function(db){ // 这里的data是form表单提交过来的数据
         db.collection('users').insert(data,function(err,ret){
           if(err){
             console.log('注册失败!',err);
             res.redirect('/regist');
           }else{
             res.redirect('/login');
           }
         })
       })
    
  2. ログインするときは、データベース内の対応するデータを検索して、データベースと整合性があるかどうかを確認してください

     model.connect(function(db){  // 连接数据库
     // 进入users库,寻找data这个数据.toArray转换成数组
     db.collection('users').find(data).toArray(function(err,docs){
       // 如果报错,重新登陆
       if(err){
         res.redirect('/login');
       }else{  
         // 否则校验数据,如果是空数组,说明没找到这个用户,让他去重新登录.找到的话.登陆成功,进入主页面
         if(docs.length > 0){
           // 登陆成功,进行session会话存储(将用户的信息进行存储)
           // 这样的话,前端每次去请求的时候,先去session里面找username,如果有值,那么证明他是登陆状态的,那么直接跳转登陆页面就好
           req.session.username = data.username;
           res.redirect('/'); // 进入主页
         }else{
           res.redirect('/login');
         }
       }
     })
    

    })

ログインインターセプト(ログインが成功すると、ユーザーの情報が保存されます。指定された時間内に、ユーザーは再度ログインするときにアカウントとパスワードを入力する必要はありません)
  1. ここではツールモジュールが使用されています-express-sessionサーバーはセッションを通じて保存します

  2. インストール:npm install express-session -S

  3. セッションを構成する最初のステップ:app.jsで紹介するvar session = require('express-session');

  4. セッションの構成2番目のステップ:app.jsでセッションミドルウェアを構成します

     // session配置
     app.use(session({
       secret: 'wangrenke project', // 可以随便改的
       resave: false,
       saveUninitialized: true,
       cookie: { maxAge: 1000 * 60 * 5 }  // 在服务端使用session时,会向客户端写入cookie,所以这里要指定一个cookie的有效期(即用户登陆多久是有效的)这里是五分钟
     }))
    
  5. 使用法:ユーザーが正常にログインしたら、セッションを保存してユーザーをセッションに保存する必要があります。これにより、フロントエンドから再度リクエストするときに、最初にseesionに移動してユーザー名を取得します。値がある場合、それはログインステータスを意味します。直接ランディングページをスキップします。それ以外の場合は、ランディングページにジャンプして再度ログインします。

     model.connect(function(db){  // 连接数据库
         // 进入users库,寻找data这个数据.toArray转换成数组
         db.collection('users').find(data).toArray(function(err,docs){
           // 如果报错,重新登陆
           if(err){
             res.redirect('/login');
           }else{  
             // 否则校验数据,如果是空数组,说明没找到这个用户,让他去重新注册.找到的话.登陆成功,进入主页面
             if(docs.length > 0){
               // 登陆成功,进行session会话存储(将用户的信息进行存储)
               // 这样的话,前端每次去请求的时候,先去session里面找username,如果有值,那么证明他是登陆状态的,那么直接跳转登陆页面就好
               req.session.username = data.username;
               res.redirect('/'); // 进入主页
             }else{
               res.redirect('/login');
             }
           }
         })
       })
    
  6. ログインブロックを設定する

     // 登录拦截(当进入系统的时候)
     app.get('*',function(req,res,next){
       var user = req.session.username;
       var path = req.path;
       console.log("session----user",user);
       // 如果是进的登录页或注册页,我们不拦截
       if(path != '/login' && path != '/regist'){
         if(!user){
           res.redirect('/login');
         }
       }
       next();
     })
    
サインアウト
  1. セッションで人事情報をクリアする

  2. ランディングページにジャンプします

     // 退出登录
     router.get('/loginout',function(req,res,next){
       req.session.username = null;
       res.redirect('/login');
     })
    
追加、削除、変更、チェック(記事公開機能の書き込み)----追加
  1. 記事を書くときは、リッチテキストボックスプラグインxhEditorを使用する必要があります。http://xheditor.com/download

  2. xhEditorをダウンロードした後、プロジェクトのpuliceの下にxheditorフォルダーを配置します。
    ここに画像の説明を挿入

  3. 使用:対応するhtmlファイルに依存ファイルを導入し、xheditorを初期化します

     <script type="text/javascript" src="/xheditor/jquery/jquery-1.4.4.min.js"></script>
     <script type="text/javascript" src="/xheditor/xheditor-1.2.2.min.js"></script>
     <script type="text/javascript" src="/xheditor/xheditor_lang/zh-cn.js"></script>
     <script>
     // 其实在本项目中基本上用前两个就行了
     $('#elm1').xheditor({
         tools: 'full',
         skin: 'default',
         showBlocktag: true,
         internalScript: false,
         internalStyle: false,
         width: 300,
         height: 200,
         loadCSS: 'http://xheditor.com/test.css',
         fullscreen: true,
         sourceMode: true,
         forcePtag: true,
         upImgUrl: "upload.php",
         upImgExt: "jpg,jpeg,gif,png"
     });
    
  4. textarea要素に1つ追加してclass='xheditor'、ページを更新したときに効果を確認できるようにします
    ここに画像の説明を挿入

  5. 記事の作成専用の新しいルートarticle.jsを作成します。次に、app.jsで記事を構成します。var articleRouter = require('./routes/article');app.use('/article', articleRouter);

  6. 保存する記事を書くときは、mongodbデータベースに記事を保存するためのデータを追加する必要があります。提出すると、データベースに保存できます。

記事リストの実装
  1. 新しい記事-記事を書いた後、mongodbのデータベースに保存されます。保存後、ホームページにジャンプする必要があるため、ホームページには記事のリストが含まれている必要があります。したがって、ホームページのルートをレンダリングするとき。mongodbを操作し、対応するリストデータからフェッチします。ページに表示

     router.get('/', function(req, res, next) {
       var username = req.session.username;
       model.connect(function(db){
         // 从库中,将articles文章张列表的数据。取出来转换成数组
         db.collection('articles').find().toArray(function(err,docs){
           console.log('文章列表------',docs);
           var list = docs; // 文章列表,用来传到index.ejs中
           res.render('index', { msg: '首页',username:username,list:list });
         });
       })
     });
    
  2. ライブラリに保存する時間はミリ秒です。それも取り出して、プラグインを使用して時間を変換します。npm install moment -S

  3. 使用moment:必要なファイルで紹介するvar moment = require("moment");

     model.connect(function(db){
         // 从库中,将articles文章张列表的数据。取出来转换成数组
         db.collection('articles').find().toArray(function(err,docs){
           console.log('文章列表------',docs);
           var list = docs; // 文章列表,用来传到index.ejs中
           list.map(function(item){
             item.time = moment(item.id).format("YYYY-MM-DD hh:mm:ss");
             return item;
           })
           res.render('index', { msg: '首页',username:username,list:list });
         });
       })
    
ページングクエリ
  1. jsパート

     router.get('/', function(req, res, next) {
       var username = req.session.username || '';
       // 当前页
       var pageIndex = req.query.pageIndex || 1;
       // 分页
       var data = {
         total: 0,  // 文章总共的页数
         curPage: pageIndex,  // 当前页
         list: [],   // 当前页的文章列表
       }
       var pageSize = 10;  // 每次请求10条数据
       model.connect(function(db){
         // 第一步:查询所有文章(从库中,将articles文章张列表的数据。取出来转换成数组)
         db.collection('articles').find().toArray(function(err,docs){
           // 文章列表总条数/每页显示的条数,向上取整。得到一共有多少页。
           data.total = Math.ceil(docs.length / pageSize);
           // 第二步:查询当前页的文章列表(分页查询)
           model.connect(function(db){
             // 重点:sort({_id:-1})表示倒序查询;limit(pageSize)表示限制多少条;skip((pageIndex - 1)*pageSize)从多少条开始查
             db.collection('articles').find().sort({_id:-1}).limit(pageSize).skip((pageIndex - 1)*pageSize).toArray(function(err,doc2){
             // 这里考虑到如果删除的时候,当前页只剩一条数据,那么删完之后,需要把对应的页签也删掉。
               if(doc2.length == 0){
                 res.redirect('/?pageIndex='+((pageIndex-1) || 1));
                 return;
               }
               doc2.map(function(item){
                 item.time = moment(item.id).format("YYYY-MM-DD hh:mm:ss");
                 return item;
               })
               data.list = doc2;
             res.render('index', { msg: '首页',username:username,data:data });
             })
           })
         });
       })
     });
    
  2. ejsパート

     <!-- 分页 -->
       <div class="page">
         <span>共<%= data.list.length %>条</span>
         <a class="top">上一页</a>
         <% for(var i = 1; i<=data.total; i++){ %>
           <a href="/?pageIndex=<% i %>" class="pages"><%= i %></a>
         <% } %>
         <a class="next">下一页</a>
       </div>
    
記事を削除する
// ejs页面
<a href="/article/delete?id=<%= item.id %>&pageIndex=<%= data.curPage %>">删除</a>
// /delete路由代码
// 删除
router.get('/delete',function(req,res,next){
  var id = parseInt(req.query.id); // 页面传过来的需要删除的id
  var pageIndex = req.query.pageIndex; // 页面传过来的当前页
  model.connect(function(db){
  	// 删除对应id的数据deleteOne()
    db.collection('articles').deleteOne({id: id},function(err,ret){
      if(err){
        console.log('删除失败!!');
      }else{
        console.log('删除成功!!');
      }
      // 删除完成后接着跳转对应的页面路由,这里有一个问题,就是如果删除时只剩一条数据,那么删掉之后需要把那一页的分页也删掉。这个限制在主体路由上。
      res.redirect('/?pageIndex='+pageIndex);
    })
  })
})
記事を変更する
  1. [編集]をクリックすると、ページと新しいページが同じページを共有します

  2. 変更時:新しいインターフェースと同じインターフェース、および同じデータパスコレクションを共有する

     // 渲染写文章页面 || 编辑文章页面
     router.get('/write',function(req,res,next){
       var username = req.session.username;
       var id = parseInt(req.query.id);
       var pageIndex = req.query.pageIndex;
       var item = {
         title:'',  // 标题
         content:''  // 内容
       }
       if(id){  // 如果有id,那么就是编辑
         model.connect(function(db){
           db.collection('articles').findOne({id:id},function(err,docs){
             if(err){
               console.log('查询失败!!!!');
             }else{
               item = docs
               item.pageIndex = pageIndex;
               console.log('aaaaaaa-------',item);
               res.render('write',{msg:'编辑文章',username:username,item:item});
             }
           })
         })
       }else{  // 否则就是新增
         res.render('write',{msg:'写文章',username:username,item:item});
       }
     })
     /* 新增 || 编辑 */
     router.post('/add', function(req, res, next) {
       var id = parseInt(req.body.id);
       if(id){  // 编辑
         var pageIndex = req.body.pageIndex;
         var title = req.body.title;
         var content = req.body.content;
         model.connect(function(db){
           db.collection('articles').updateOne({id:id},{$set:{title:title,content:content}},function(err,ret){
               if(err){
                   console.log('文章修改失败!',err);
               }else{
                 console.log('文章修改成功!');
                   res.redirect('/?pageIndex='+pageIndex);
               }
           })
         })
       }else{   // 新增
         var data = {
           title: req.body.title,  // 标题
           content: req.body.content,  // 内容
           id: Date.now(),   // 时间戳(什么时候提交的)
           username: req.session.username  // 提交的用户(是谁写的)
         }
         model.connect(function(db){
           db.collection('articles').insert(data,function(err,ret){
               if(err){
                   console.log('文章发布失败!',err);
                   res.redirect('/write');
               }else{
                   res.redirect('/');
               }
           })
         })
       }
     });
    
記事詳細ページ(タイトルをクリックすると詳細が表示されます)
  1. 基本的なロジックは編集と同じです

  2. 新しい詳細ページを作成する

     <td><a href="/detail?id=<%= item.id %>"><%= item.title %></a></td>
     ---------------------------------------------------
     // 查看文章详情页面
     router.get('/detail',function(req,res,next){
       var username = req.session.username;
       var id = parseInt(req.query.id);
       var item = {
         title:'',  // 标题
         username:'',  // 作者
         id:'',   // 时间&&id
         content:'',  // 内容
       }
       model.connect(function(db){
         db.collection('articles').findOne({id:id},function(err,docs){
           if(err){
             console.log('查询失败!!!!');
             res.redirect('/');
           }else{
             item = docs;
             item.time = moment(item.id).format('YYYY-MM-DD hh:mm:ss');
             res.render('detail',{msg:'详情页',username:username,item:item});
           }
         })
       })
     })
    
ファイルのアップロード(リッチテキストプラグインxheditor経由でも)
  1. 構成パラメーター
    ここに画像の説明を挿入

  2. サーバーで定義/upload路由

  3. ファイルのアップロードを処理するには、サードパーティのプラグインが必要です。アップロードmultipartyの固定形式は次のとおりです。multiparty/form-data

  4. ダウンロード:npm install multiparty -S、はじめに:var multiparty = require('multiparty');、インスタンスvar form = new multiparty.Form()インスタンス化後、リクエスト本文はフォームオブジェクトを介して解析でき、リクエスト本文内のファイルは解析および処理できます。必要な結果を取得します。

     // 文件上传
     router.post('/upload',function(req,res,next){
       var form = new multiparty.Form();
       form.parse(req,function(err,fields,files){
         if(err){
           console.log('上传失败呗!!!');
         }else{
           console.log('文件列表----',files);
           // 这个就是拿到的上传的文件数据,我们需要使用fs管道流的方式,写入到硬盘
           var file = files.filedata[0];
           var newPath = '/uploads/'+file.originalFilename;  // 写入的路径加文件名字
           var rs = fs.createReadStream(file.path);  // 第一个流(读取的)--读的时候,就读带的路径就行
           var ws = fs.createWriteStream("./public"+newPath);  // 第二个流(写入的)--写的时候要写在服务端-这里放在pulice下的uploads中
           rs.pipe(ws);
           // 当写入完成的时候,监听一个on('close')事件
           ws.on('close',function(){
             console.log('文件上传成功!!!');
             res.send({err:'',msg:newPath});
           })
         }
       })
     })
    
プロジェクトの概要

登録、ログイン、ログインインターセプト、セッションストレージ、ページング、mongodbの追加、削除、変更、チェックのコレクション

おすすめ

転載: blog.csdn.net/weixin_43996999/article/details/103832849