プロジェクトのインストール
- エクスプレス足場をインストールします。
npm install express-generator -g
- プロジェクトを作成します。
express -e project
-eはejsテンプレートの使用を表し、projectはプロジェクトの名前です。 - プロジェクトを入力してください:
npm install
依存関係パッケージをダウンロードしてください - nodemonをインストールします。
npm install nodemon -g
開始するノードではなく、nodemonを使用してプロジェクトを開始します。
- スタートアッププロジェクト:
npm start
、ポート番号はwwwスタートアップファイルで確認できます。
プロジェクトはMongoDBデータベースに接続します
-
nodejsと統合されたmongodbをインストールします。
npm install mongodb -S
-
プロジェクトにモデルファイルを作成し、以下に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}
-
呼び出し:ルーティングを介してデータベースにデータを書き込むために使用されます
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を導入した後のデータベース構文の操作
-
登録時に、ユーザー登録データをデータベースに書き込みます
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'); } }) })
-
ログインするときは、データベース内の対応するデータを検索して、データベースと整合性があるかどうかを確認してください
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'); } } })
})
ログインインターセプト(ログインが成功すると、ユーザーの情報が保存されます。指定された時間内に、ユーザーは再度ログインするときにアカウントとパスワードを入力する必要はありません)
-
ここではツールモジュールが使用されています-
express-session
サーバーはセッションを通じて保存します -
インストール:
npm install express-session -S
-
セッションを構成する最初のステップ:app.jsで紹介する
var session = require('express-session');
-
セッションの構成2番目のステップ:app.jsでセッションミドルウェアを構成します
// session配置 app.use(session({ secret: 'wangrenke project', // 可以随便改的 resave: false, saveUninitialized: true, cookie: { maxAge: 1000 * 60 * 5 } // 在服务端使用session时,会向客户端写入cookie,所以这里要指定一个cookie的有效期(即用户登陆多久是有效的)这里是五分钟 }))
-
使用法:ユーザーが正常にログインしたら、セッションを保存してユーザーをセッションに保存する必要があります。これにより、フロントエンドから再度リクエストするときに、最初に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'); } } }) })
-
ログインブロックを設定する
// 登录拦截(当进入系统的时候) 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(); })
サインアウト
-
セッションで人事情報をクリアする
-
ランディングページにジャンプします
// 退出登录 router.get('/loginout',function(req,res,next){ req.session.username = null; res.redirect('/login'); })
追加、削除、変更、チェック(記事公開機能の書き込み)----追加
-
記事を書くときは、リッチテキストボックスプラグインxhEditorを使用する必要があります。
http://xheditor.com/download
-
xhEditorをダウンロードした後、プロジェクトのpuliceの下にxheditorフォルダーを配置します。
-
使用:対応する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" });
-
textarea要素に1つ追加して
class='xheditor'
、ページを更新したときに効果を確認できるようにします
-
記事の作成専用の新しいルートarticle.jsを作成します。次に、app.jsで記事を構成します。
var articleRouter = require('./routes/article');app.use('/article', articleRouter);
-
保存する記事を書くときは、mongodbデータベースに記事を保存するためのデータを追加する必要があります。提出すると、データベースに保存できます。
記事リストの実装
-
新しい記事-記事を書いた後、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 }); }); }) });
-
ライブラリに保存する時間はミリ秒です。それも取り出して、プラグインを使用して時間を変換します。
npm install moment -S
-
使用
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 }); }); })
ページングクエリ
-
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 }); }) }) }); }) });
-
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);
})
})
})
記事を変更する
-
[編集]をクリックすると、ページと新しいページが同じページを共有します
-
変更時:新しいインターフェースと同じインターフェース、および同じデータパスコレクションを共有する
// 渲染写文章页面 || 编辑文章页面 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('/'); } }) }) } });
記事詳細ページ(タイトルをクリックすると詳細が表示されます)
-
基本的なロジックは編集と同じです
-
新しい詳細ページを作成する
<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経由でも)
-
構成パラメーター
-
サーバーで定義
/upload路由
-
ファイルのアップロードを処理するには、サードパーティのプラグインが必要です。アップロード
multiparty
の固定形式は次のとおりです。multiparty/form-data
-
ダウンロード:
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の追加、削除、変更、チェックのコレクション