Express脚手架项目2

前面《Express脚手架项目》篇基本实现了一个留言板登录注册和留言的一个功能,但是一旦留言很多就会破坏页面结构,这里需要一个分页的效果。在说分页之前,先让留言能够查看在detail.ejs页面展示一下。

//detail.ejs
<!DOCTYPE html>
<html>
  <head>
    <title>详情</title>
    <link rel='stylesheet' href='/stylesheets/bootstrap.min.css' />
    <script src="/javascripts/jquery-1.11.0.js" type="text/javascript" charset="utf-8"></script>
  </head>
  <body>
  	<%- include('head.ejs')%>
  	<h2>详情</h2>
    <h1>歌曲名字:<%- detail2%></h1>
    <h2>歌手:<%- detail1%></h2> 
 
</html>

这里面的数据通过点击留言具体信息的时候,提交一个id去后台数据库查找,之后让后台把数据给前端页面,也就是前端会得到detail1和detail2这两条代表留言标题、留言内容的数据,在前端页面展示。下面是在留言页面去传递id和跳转到详情页面的操作。

//liuyan.ejs
<table class="table table-striped">
	  	<tr><th>序号</th><th>标题</th><th>内容</th></tr>
	  	<% list.map(function(item,i){%>
	  			<tr>
	  				<td><%- i+1%></td>
                     //点击跳转,通过query传参,search的方式,知道点击的是哪一条留言
	  				<td onclick="location.href='/detail?id=<%- item._id%>'"><%- item.title%></td>
	  				<td><%- item.con%></td>
	  			</tr>
	  	<% })%>
	  	
	  </table>

然后需要在前端路由渲染detail页面,还有通过req.query来接收前端传参数据。

//index.js
var mongodb = require("mongodb").MongoClient;
//这里引入mongodb模块里面的ObjectId是为了在查找的时候能通过id查找,因为前端传来的id是字符串格式,
//{ id: '5b6bb56282685418c87bf5ce' },而数据库里面的是处理过的
//{"_id": ObjectId('5b6bb56282685418c87bf5ce') }这样格式,不处理肯定找不到
var ObjectId = require("mongodb").ObjectId;
var db_str = "mongodb://localhost:27017/html5";

//详情
router.get("/detail",(req,res)=>{
	//console.log(req.query)
	var id = ObjectId(req.query.id)
	mongodb.connect(db_str,(err,database)=>{
		database.collection("liuyan",(err,coll)=>{
			coll.find({_id:id}).toArray((err,data)=>{
                //找到的留言信息传给前端页面
				res.render("detail",{detail1:data[0].con,detail2:data[0].title})
                               database.close()
			})
		})
	})
})

以上就实现了留言详情的一个展示,下面来实现分页。

在liuyan.ejs的发布留言按钮结构下面写入分页模块,拿了bootstrap的组件里面的分页结构,主要代码如下

//liuyan.ejs
<!--分页-->
	  <nav aria-label="Page navigation">
		  <ul class="pagination">
		    <li>
		      <a href="/liuyan?pageNum=<%-pageNum<1?1:parseInt(pageNum)-1%>" aria-label="Previous">
		        <span aria-hidden="true">&laquo;</span>
		      </a>
		    </li>
		    <!--<li><a href="#">1</a></li>
		    <li><a href="#">2</a></li>
		    <li><a href="#">3</a></li>
		    <li><a href="#">4</a></li>
		    <li><a href="#">5</a></li>-->
		    
		    <% if(page>4){%>
		    	<li><a href="/liuyan?pageNum=1">1</a></li>
			    <li><a href="/liuyan?pageNum=2">2</a></li>
			    <li><a href="#">...</a></li>
			    <li><a href="/liuyan?pageNum=<%-page-1%>"><%-page-1%></a></li>
			    <li><a href="/liuyan?pageNum=<%-page%>"><%-page%></a></li>
		    <%}else{%>
		    	
		    	<%for(let i=0; i<page;i++){%>
		    		<li><a href="/liuyan?pageNum=<%-i+1%>"><%-i+1%></a></li>
		    	<%}%>
		    
		    <%}%>
		    
		    <li>
		      <a href="/liuyan?pageNum=<%-pageNum>page?page:parseInt(pageNum)+1%>" aria-label="Next">
		        <span aria-hidden="true">&raquo;</span>
		      </a>
		    </li>
		  </ul>
		</nav>

前端路由对接收到的由前端页面用户点击的第几页即pageNum做的处理,如下

//index.js
//要安装async依赖模块(npm i async -D),然后引入
var async = require("async");

//留言
router.get("/liuyan",(req,res)=>{
	//页码
	var  pageNum = req.query.pageNum;
    //没点击时候,展示第一页,点击时候,点哪一页展示哪一页的数据
	pageNum = pageNum?pageNum:1;
	//总页数
	var page = 0;
	//每页数量
	var size =5;
	//总条数
	var count = 0;
	
	mongodb.connect(db_str,(err,database)=>{
		database.collection("liuyan",(err,coll)=>{
			
			async.series([
				function(callback){
					coll.find({}).toArray((err,data)=>{
						count = data.length;
						page = Math.ceil(count/size)
						
						
//						上一页/下一页
						pageNum=pageNum<1?1:pageNum;
						pageNum= pageNum.page?page:pageNum;
						
						callback(null,"")
						
					})
				},
				function(callback){
					coll.find({}).sort({_id:-1}).limit(size).skip((pageNum-1)*size).toArray((err,data)=>{
						callback(null,data)
					})
				}
			],function(err,data){
				 res.render("liuyan",{list:data[1],pageNum:pageNum,page:page,count:count,size:size})
				 database.close()
			})

			
//			coll.find({}).sort({_id:-1}).toArray((err,data)=>{
//					res.render("liuyan",{list:data})
//          database.close()
//			})
		})
	})
})

这里用到异步流程模块,主要是因为两个事件需要同时进行,没有先后顺序。

为了完善留言板功能,添加了一个富文本编辑器,这里需要引入几个文件,可以参考富文本编辑器入门的用法。主要是在javascripts中引入xheditor文件夹和fwb.js(可以从我上传的资源里面下,也可以在官网即入门里面下),然后再路由界面引入upload.js文件。

//liuyan.ejs
<script src="/javascripts/jquery-1.11.0.js" type="text/javascript" charset="utf-8"></script>
  	<script src="/javascripts/xheditor/xheditor-1.2.2.min.js" type="text/javascript" charset="utf-8"></script>
 		<script src="/javascripts/xheditor/xheditor_lang/zh-cn.js" type="text/javascript" charset="utf-8"></script>


//修改一下input框为多行文本输入框,加上xheditor类名
<label for="con">内容</label>
<textarea type="text" class="form-control xheditor" id="con" placeholder="内容"></textarea>

到这里可以实现富文本的表情、加粗、倾斜、字变色等功能,但是图片不能上传。下面配置一下,实现图片上传。

//liuyan.ejs

//在ajax事件的script上面调用一下,这里面配有上传图片路径upImgUrl: '/users/uploadImg',
<script src="/javascripts/fwb.js" type="text/javascript" charset="utf-8"></script>

然后看一下upload.js,它里面引入了一个multiparty模块,实现上传图片的。安装一下依赖(npm i multiparty -D),然后能看到这个upload.js文件封装了一个函数实现了文件的上传时候相关配置,最后作为upload模块暴露出去了,说明要在其他地方引用。下面是upload.js的代码。

//upload.js
var multiparty=require('multiparty')
var fs=require('fs')
function upload(req,res){
//	创建表单
	var form =new multiparty.Form()
//	编码格式
	form.encoding='utf-8';
//	文件大小
	form.maxFilesSize=2*1024*1024;
//	文件上传目录
	form.uploadDir='./uploadtem';
	
	
	form.parse(req,function(err,fields,files){
		var uploadurl='/images/upload';
//		获取文件
		file=files['filedata'];
//		文件的原始名字
		originalFilename=file[0].originalFilename;
//		文件路径
		tempath=file[0].path;
		
		var timestap=new Date().getTime()
		uploadurl+=timestap+originalFilename;
		newPath='./public/'+uploadurl;
		
		var fsread=fs.createReadStream(tempath)
		var fswrite=fs.createWriteStream(newPath)
		
		fsread.pipe(fswrite)
		fswrite.on('close',()=>{
			fs.unlinkSync(tempath)
			res.send('{"err":"","msg":"'+uploadurl+'"}')	
		})	
	})
}

module.exports=upload;

 上面文件上传目录是根路径下的uploadtem,需要去在项目根路径创建一下这个目录,还有上传的路径是'/images/upload',所以要在images里面去建一下upload文件目录。再去看一下富文本fwb.js这个文件

//fwb.js
pageInit()
    function pageInit() {
      $.extend(XHEDITOR.settings, {shortcuts:{'ctrl+enter': submitForm}})
      $('#con').xheditor({
        html5Upload: false,
        upMultiple: '1',
		width:'100%',
        upLinkUrl: 'upload.html',
        upLinkExt: 'zip, rar, txt',

        upImgUrl: '/users/uploadImg',
        upImgExt: 'jpg,jpeg,gif,png',

        upFlashUrl: 'upload.html',
        upFlashExt: 'swf',
        upMediaUrl: 'upload.html',
        upMediaExt: 'wmv,avi,wma,mp3,mid'
      })
    }
//  富文本自动调用
	function insertUpload(arrmsg){
		var i ,msg;
		for (i=0;i<arrmsg.length;i++) {
			msg=arrmsg[i];
			$('#uploadList').append('<option value="'+msg.id+'">'+msg.localname+'</option>')
		}
	}
    function submitForm() {
      $('#frmDemo').submit()
    }

可以看到upImgUrl: '/users/uploadImg'----当我们上传图片时候,是在请求users路由里面的/uploadImg,所以去uses路由里面配置一下。

//user.js
//接收一下这个图片处理模块
var upload = require("./upload");


//图片
router.post("/uploadImg",(req,res)=>{
	upload(req,res);
})

以上就将相关配置工作做好了,启动项目就可以实现登录、注册、富文本留言、查看详情这些操作了。

猜你喜欢

转载自blog.csdn.net/keep789/article/details/81539168