京东投票项目开发笔记
Posted 码小余の博客
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了京东投票项目开发笔记相关的知识,希望对你有一定的参考价值。
京东投票项目开发笔记
-
打开项目
$yarn install / $ npm install
: 跑环境(把项目依赖的插件进行安装)
$node admin.js
: 启服务(把自己的计算机作为服务器,创建一个指定端口的服务,来管理后台程序->后台程序会根据客户端请求的需求,把对应的数据和业务逻辑实现) -
API.TXT: API接口文档
真实项目中,后台开发人员会给前端开发人员提供一个技术文档(接口文档),文档中描述了前端需要调取后台的某些接口实现的某些功能,并且标注了请求的地址、请求方式、传递给服务器的内容、以及服务器返回的结果等信息这就是前后端分离: 前端开发者不需要考虑后台是基于什么技术怎么实现的,我们只需要按照API文档中提供的信息,去发送请求传递内容即可,这样就可以获取我们需要的数据(API文档就是约束前端和后台的规范文档)
面试题:有一万条数据,想让其绑定到页面中,怎么做好一些?
-
文档碎片: 遍历数据,把对应的数据和结构都添加到文档碎片中,在把文档碎片扎入到页面中(优势∶减少了DOM的回流=>基于字符串拼接也可以)
-
虚拟DOM:类似于REACT框架,基于虚拟DOM以及DIFF算法,也可以优化数据绑定
-
其实本质来讲怎么做都不是最好的,我们不应该出现1万条这种大数据量的绑定
->从服务器获取1万条消耗很多时间
->页面渲染1万条也会消耗很多时间
异步数据加载(分页加载)
「需要服务器端做支持]
- 客户端向服务器端发送一个GET请求,传递给服务器:每页展示的条数,当前要展示的页数等信息,例如传递的是?limit=20&page=1(每页展示20条,当前展示第一页)
- 服务器端接受到请求后,在所有的数据中把第一页的20条数据返回给客户端
- 当用户下拉加载更多或者点击第二页等页码按钮等时候,重复第一步,把对应要展示的页码传递给服务器,服务器返回对应页码中的数据
最终实现效果图
通过AJAX请求来获取JSON文件中的数据,只有在登录情况下才能投票和参赛,并且每个人只能投一票,如果没有数据会显示当前没有数据,登录的密码需要用MD5加密等等。
一、首页后端
目录结构
|-- node_modules 第三方包
|-- public 公共的静态资源
|-- app.js 子应用文件
|-- package.json 包描述文件
|-- package-lock.json 第三方包版本锁定文件(npm 5 以后才有)
|-- router.js 路由接口文件
路由设计
路径 | 方法 | get参数 | post参数 | 是否需要登录 | 备注 |
---|---|---|---|---|---|
/index | GET | 渲染首页 | |||
/register | GET | 渲染注册页 | |||
/register | POST | username、phone、password、passwordtrue、slogan、sex | 处理注册页 | ||
/login | GET | 渲染登录页 | |||
/login | POST | phone、password | 处理登录页 | ||
/about | GET | 渲染个人主页 | |||
/logout | GET | 退出登录 | |||
/search | GET | username | 搜索功能 | ||
/vote | GET | username | 投票功能 | ||
/match | GET | 渲染参赛页 |
项目构建
app.js 文件的基本配置
-
需要引入第三方模块
-
路由文件(router.js)
// 引入第三方服务器模块 const express = require("express"); // 路由对象 const router = express.Router(); router.get("/", (req, res) => res.send("Hello World"); ); module.exports = router;
-
app.js
// 引入写服务器的第三方模块 const express = require("express"); // 引入用来解析的插件 const bodyParser = require("body-parser"); // 引入mongoose插件 const mongoose = require("mongoose"); // 引入router.js const router = require("./router"); // 创建服务器 var app = express(); // 模板引擎的设置 app.set("view engine", "html"); app.set("views", `$__dirname/views`); app.engine("html", require("ejs").renderFile); // 用ejs模板渲染html // 加载到没有挂载路径的中间件 app.use(bodyParser.urlencoded( extended: false )); // 静态资源配置 app.use(express.static(__dirname + "/public")); // 使用router, router.js文件中的所有路由都可以使用 app.use(router); // 连接数据库和开启服务器 /* * localhost - 本地地址 * jdvotes - mongodb数据库 */ mongoose.connect( "mongodb://localhost/jdvotes", useNewUrlParser: true, useUnifiedTopology: true, , function (err) if (err) console.log("数据库连接失败"); else console.log("数据库连接成功"); app.listen(8888, function () console.log("服务器开启成功 -- 8888"); ); );
-
需要用到MondoDB,所以需要配置以下表结构文件
/* MongoDB数据库模型文件 */ // 引入mongoose插件 const mongogose = require("mongoose"); // 通过mongoose定义接口 Schema var Schema = mongogose.Schema; // 生成表结构 // 操作users表(集合) 定义一个Schema Schema里面的对象和数据库表里面的字段需要一一对应 var mySchema = new Schema( // name: type: String, default: "zhangsan" , name: String, ); // 把Schema导出 module.exports = mySchema;
-
然后再访问数据库模型
// 引入mongoose插件 const mongoose = require("mongoose"); // 引入 schema.js 文件(MongoDB数据库表结构文件) const mySchema = require("./schema"); // 定义数据库模型 /* model里面的第一个参数 要注意: 1.首字母大写 2.要和数据库表(集合)名称对应 这个模型会和模型名称相同的复数的数据库表建立连接 */ // 把这个数据库模型导出 module.exports = mongoose.model("User", mySchema);
-
最后在写路由,在对应路由上查询对应的数据返回给页面即可
/* 路由文件 */ // 引入第三方服务器模块 const express = require("express"); // 引入model.js文件(数据库模型文件) const USER = require("./model"); // 路由对象 const router = express.Router(); // 首页 router.get("/", (req, res) => USER.find(, (err, docs) => // docs.forEach // 如果查询成功 if (err === null) console.log(docs); ); res.send("Hello"); ); module.exports = router;
浏览器访问
127.0.0.1:8888
,得到结果[ _id: 5f5ad635994e3f8f4923d1cd, name: 'zhangsan' ]
-
创建数据
for(var i=1;i<=150;i++) db.users.insert("id":i,"name":"张"+i,"picture":"https://cdn.jsdelivr.net/gh/extheor/images/Ajax%E5%9B%BE%E7%89%87/man.png","phone":"10377771223","sex":0,"password":"123456","bio":"Live beautifully, dream passionately, love completely","time":1506090072369,"isMatch":1,"matchId":i<10?"00"+i:i<100?"0"+i:i,"slogan":"你是唯一的,你是非常独特的,你就是你生命中的第一名","voteNum":1) ;
二、首页前端
首先把首页写出来(views/index.html)
完全手撸的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>首页</title>
<link rel="stylesheet" href="css/index.css" />
</head>
<body>
<div class="app">
<header>
<a href="/index">首页</a>
<a href="/login" class="login">登录</a>
<a href="/register">注册</a>
</header>
<div class="header">
<img class="img" src="img/title.png" alt="" />
<div class="myToMacth">
<a href="/match">我要参赛</a>
</div>
<div class="search">
<input type="text" class="searchInput" placeholder="输入用户名查找" />
<input type="button" class="searchButton" value="搜索" />
</div>
</div>
<div class="content">
<ul class="userul">
<% datas.forEach(data => %>
<li class="<%= data.phone %>">
<div class="left">
<img src="<%= data.picture %> " alt="" />
</div>
<div class="center">
<div><%= data.username %> | 编号# <%= data.matchId %></div>
<div><%= data.slogan %></div>
</div>
<div class="right">
<div class="voteNum"><%= data.voteNum %></div>
<div><button>投他一票</button></div>
</div>
</li>
<% ) %>
</ul>
</div>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="js/index.js"></script>
</body>
</html>
CSS样式在这里
*
margin: 0;
padding: 0;
box-sizing: border-box;
body
background: yellowgreen;
.app
width: 450px;
height: 800px;
background: red;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
a
text-decoration: none;
/* 首页、登录、注册 */
header
position: fixed;
right: 10px;
top: 10px;
font-weight: 800;
header > a
color: #000;
margin-left: 20px;
.header
width: 100%;
height: 50%;
background: #31a5de;
/* 投起来 */
.header > .img
position: relative;
left: 50%;
top: 40%;
transform: translate(-50%, -50%);
/* 我要参赛 */
.myToMacth
position: absolute;
left: 50%;
top: 38%;
transform: translate(-50%, -50%);
padding: 10px 20px;
background: #eb713b;
box-shadow: 5px 2px 15px rgb(90, 38, 38);
border-radius: 20px;
.myToMacth > a
color: #fff;
/* 搜索 */
.search
position: absolute;
left: 52%;
top: 45%;
transform: translate(-50%, -50%);
width: 250px;
height: 30px;
/* border: 1px solid #000; */
/* border-radius: ; */
.searchInput,
.searchButton
height: 30px;
border-radius: 30px;
border: none;
outline: none;
.searchInput
border-top-right-radius: 0;
border-bottom-right-radius: 0;
padding-left: 15px;
.searchButton
width: 50px;
background: #007ec3;
color: #fff;
position: relative;
right: 5px;
top: 1px;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
/* 列表 */
.content
height: 50%;
background: #ccc;
.content > ul
list-style: none;
margin: 0;
padding: 0;
width: 450px;
.content > ul > li
height: 100px;
background: #fff;
.content > ul > li > .left
float: left;
width: 100px;
height: 100px;
.content > ul > li > .left > img
width: 80%;
border-radius: 50%;
margin-left: 10px;
margin-top: 10px;
.content > ul > li > .center
float: left;
height: 100px;
width: 250px;
margin-top: 20px;
.content > ul > li > .center > div:nth-child(1)
margin-bottom: 10px;
.content > ul > li > .right
float: right;
width: 100px;
height: 100px;
margin-top: 20px;
.content > ul > li > .right > div:nth-child(1)
margin-bottom: 10px;
text-align: center;
color: rgb(156, 92, 92);
.content > ul > li > .right > div:nth-child(2)
margin-left: 10px;
.content > ul > li > .right > div:nth-child(2) > button
/* width: 60px;
height: 30px; */
padding: 5px 10px;
border: none;
background: #0081cd;
color: #fff;
border-radius: 15px;
页面样式如下:
-
接下来需要把从数据库获取到的数据渲染到HTML页面当中去
-
从路由文件中获取到数据
/* 路由文件 */ // 引入第三方服务器模块 const express = require("express"); // 引入model.js文件(数据库模型文件) const USER = require("./model"); // 路由对象 const router = express.Router(); // 首页 router.get("/index", (req, res) => USER.find(, (err, datas) => // docs.forEach // 如果查询成功 if (err === null) // console.log(datas); res.render("index", // es6语法:对象解构赋值, // 相当于datas:datas datas, ); ); ); module.exports = router;
-
渲染到HTML页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>首页</title> <link rel="stylesheet" type="text/css" href="css/index.css" /> </head> <body> <div class="app"> <header> <a href="#RoR 投票系统。如何计算票数、反对票和总票数?
-