主頁 >  其他 > 京東投票專案開發筆記

京東投票專案開發筆記

2020-09-15 00:58:11 其他

京東投票專案開發筆記

  1. 打開專案
    $yarn install / $ npm install: 跑環境(把專案依賴的插件進行安裝)
    $node admin.js: 啟服務(把自己的計算機作為服務器,創建一個指定埠的服務,來管理后臺程式->后臺程式會根據客戶端請求的需求,把對應的資料和業務邏輯實作)

  2. API.TXT: API介面檔案
    真實專案中,后臺開發人員會給前端開發人員提供一個技術檔案(介面檔案),檔案中描述了前端需要調取后臺的某些介面實作的某些功能,并且標注了請求的地址、請求方式、傳遞給服務器的內容、以及服務器回傳的結果等資訊

    這就是前后端分離: 前端開發者不需要考慮后臺是基于什么技術怎么實作的,我們只需要按照API檔案中提供的資訊,去發送請求傳遞內容即可,這樣就可以獲取我們需要的資料(API檔案就是約束前端和后臺的規范檔案)

面試題:有一萬條資料,想讓其系結到頁面中,怎么做好一些?

  1. 檔案碎片: 遍歷資料,把對應的資料和結構都添加到檔案碎片中,在把檔案碎片扎入到頁面中(優勢∶減少了DOM的回流=>基于字串拼接也可以)

  2. 虛擬DOM:類似于REACT框架,基于虛擬DOM以及DIFF演算法,也可以優化資料系結

  3. 其實本質來講怎么做都不是最好的,我們不應該出現1萬條這種大資料量的系結
    ->從服務器獲取1萬條消耗很多時間
    ->頁面渲染1萬條也會消耗很多時間

異步資料加載(分頁加載)

「需要服務器端做支持]

  1. 客戶端向服務器端發送一個GET請求,傳遞給服務器:每頁展示的條數,當前要展示的頁數等資訊,例如傳遞的是?limit=20&page=1(每頁展示20條,當前展示第一頁)
  2. 服務器端接受到請求后,在所有的資料中把第一頁的20條資料回傳給客戶端
  3. 當用戶下拉加載更多或者點擊第二頁等頁碼按鈕等時候,重復第一步,把對應要展示的頁碼傳遞給服務器,服務器回傳對應頁碼中的資料

最終實作效果圖

通過AJAX請求來獲取JSON檔案中的資料,只有在登錄情況下才能投票和參賽,并且每個人只能投一票,如果沒有資料會顯示當前沒有資料,登錄的密碼需要用MD5加密等等,

一、首頁后端

目錄結構

|-- node_modules       第三方包
|-- public             公共的靜態資源
|-- app.js        	   子應用檔案
|-- package.json       包描述檔案
|-- package-lock.json  第三方包版本鎖定檔案(npm 5 以后才有)
|-- router.js          路由介面檔案

路由設計

路徑方法get引數post引數是否需要登錄備注
/indexGET渲染首頁
/registerGET渲染注冊頁
/registerPOSTusername、phone、password、passwordtrue、slogan、sex處理注冊頁
/loginGET渲染登錄頁
/loginPOSTphone、password處理登錄頁
/aboutGET渲染個人主頁
/logoutGET退出登錄
/searchGETusername搜索功能
/voteGETusername投票功能
/matchGET渲染參賽頁

專案構建

app.js 檔案的基本配置

  • 需要引入第三方模塊

    npm i express

    npm i ejs

    npm i cookie-parser

    npm i body-parser

    npm i mongoose

    npm i multer

  • 路由檔案(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="#">首頁</a>
              <a href="/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>
                <% datas.forEach(data => { %>
                <li class="<%= data.id %>">
                  <div class="left">
                    <img src="<%= data.picture %> " alt="" />
                  </div>
                  <div class="center">
                    <div>張三 | 編號# <%= 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>
        </body>
      </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" />
    <link rel="stylesheet" href="css/register.css" />
  </head>
  <body>
    <div class="app">
      <header>
        <a href="#">首頁</a>
        <a href="/login">登錄</a>
        <a href="/register">注冊</a>
        <a href="/logout">退出</a>
      </header>

      <div class="header">
        <img class="img" src="img/title.png" alt="" />
      </div>
      <form action="#">
        用戶名:<input
          type="text"
          name="username"
          id="username"
          placeholder="請輸入您的真實姓名"
          required
        />
        手機號碼:<input
          type="text"
          name="phone"
          id="phone"
          placeholder="請填寫您常用的手機號"
          required
        />
        密碼:<input
          type="password"
          name="password"
          id="password"
          placeholder="由6~12位數字和字母組成"
          required
        />
        確認密碼:
        <input type="password" name="passwordtrue" id="password" required />
        <div class="introduce">自我描述:</div>
        <textarea
          cols="54"
          rows="6"
          placeholder="限制在10~100字之間"
          minlength="10"
          maxlength="100"
          id="descript"
          name="descript"
        ></textarea>
        上傳頭像:
        <input type="file" id="avatar" name="avatar" />
        <div class="sex">性別:</div>
        <input type="radio" name="sex" id="man" required /><span></span>
        <input type="radio" name="sex" id="woman" required /><span></span>
        <input type="submit" value="提交注冊資訊" class="submit" />
      </form>
    </div>

    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
    <script src="js/register.js"></script>
  </body>
</html>
.app {
  background: #fff;
}
.header {
  height: 40%;
}
/* 投起來 */
.header > .img {
  position: relative;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}

form {
  color: #656e73;
  background: #fff;
  padding: 20px;
}

form > input {
  display: block;

  margin-top: 5px;
  margin-bottom: 20px;
  width: 396px;
  height: 30px;
  padding: 10px;
}
form > textarea {
  padding: 10px;
  outline: none;
  resize: none;
}

form > #man,
form > #woman {
  float: left;
  position: absolute;
  bottom: -135px;
  width: 30px;
}
.sex {
  margin-bottom: 10px;
}
form > #man ~ span {
  margin-right: 20px;
  margin-left: 30px;
}

form > #man {
  left: 17px;
}
form > #woman {
  left: 89px;
}

form > .submit {
  margin-top: 20px;
  background: #54abe8;
  color: #fff;
  font-size: 20px;
  height: 60px;
  border: none;
  outline: none;
  cursor: pointer;
  border-radius: 3px;
}

前端需要把注冊資訊發送給后端,所以需要用到AJAX

// 當提交表單時觸發
$("form").on("submit", (event) => {
  // 阻止默認行為
  event.preventDefault();
  //   console.log($("form")[0]);
  /*
    serialize()  FormData  serializeArray()都是序列化表單,實作表單的異步提交
    但是serialize()和serializeArray()都是只能序列化表單中的資料,比如input  select等的資料,
    但是對于檔案上傳就只能用 FormData,
  */
  var data = new FormData($("form")[0]);
  $.ajax("/register", {
    type: "post",
    data,
    dataType: "json",
    // (默認: "application/x-www-form-urlencoded") 發送資訊至服務器時內容編碼型別,默認值適合大多數情況,如果你明確地傳遞了一個content-type給 $.ajax() 那么他必定會發送給服務器(即使沒有資料要發送)
    contentType: false,
    // processData 默認為true,當設定為true的時候,jquery ajax 提交的時候不會序列化 data,而是直接使用data
    processData: false,
    success: function (response) {
      if (response.code == "200") {
        window.location = "/";
      }
    },
  });
});

四、注冊頁后端

// 注冊
router.get("/register", (req, res) => {
  res.render("register");
});
// 必須寫上傳檔案
router.post("/register", upload.single("picture"), (req, res) => {
  // 獲取前端發送過來的注冊資訊
  var { username, phone, password, passwordtrue, slogan, sex } = req.body;
  // console.log(username);
  var picture;
  try {
    picture = req.file.filename;
  } catch (e) {
    picture = undefined;
  }
  // console.log(picture);
  if (password !== passwordtrue) {
    res.send({
      code: "304",
      message: "兩次密碼不一致",
    });
    return;
  }
  USER.findOne({ username })
    .then((result) => {
      // 如果查詢到username存在,則說明該用戶已注冊過
      if (result) {
        // console.log(result); // 查詢結果
        res.send({
          code: 304,
          message: "該用戶已存在",
        });
      }
      // 否則該用戶不存在,則添加到表(集合)中去
      else {
        console.log("用戶注冊~~~");
        // 如果用戶上傳了圖片
        // 創建一個資料集合(物件)
        var myUser = new USER({
          username,
          phone,
          password,
          picture,
          slogan,
          // sex,
        });
        // console.log(myUser);
        // 把這個資料集合插入到表(集合)中
        USER.insertMany(myUser)
          .then((result) => {
            // console.log(result);
            // 插入成功
            res.send({
              code: 200,
              message: "注冊成功",
            });
          })
          .catch((err) => {
            // console.log(err);
            res.send({
              code: 304,
              message: "注冊失敗",
            });
          });
      }
    })
    .catch((err) => {
      res.send({
        code: 500,
        message: "資料庫內部錯誤",
      });
    });
});

頁面效果如下

注冊即可,其中用戶名為必填項,手機號碼為必填項,密碼為必填項,確認密碼為必填項,性別為必填項

點擊“提交注冊資訊”即可注冊成功,我們會發現在資料庫里就多了一條資料,相對而言,首頁也就會多出這條資料,如下:

五、登錄頁前端

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <link rel="stylesheet" href="css/index.css" />
    <link rel="stylesheet" href="css/register.css" />
  </head>
  <body>
    <div class="app">
      <header>
        <a href="/index">首頁</a>
        <a href="/register">注冊</a>
      </header>

      <div class="header">
        <img class="img" src="img/title.png" alt="" />
      </div>

      <form action="#">
        手機號碼:<input
          type="text"
          name="phone"
          id="phone"
          placeholder="請填寫您常用的手機號"
          required
        />
        密碼:<input
          type="password"
          name="password"
          id="password"
          placeholder="由6~12位數字和字母組成"
          required
        />
        <input type="submit" value="提交登錄資訊" class="submit" />
      </form>
    </div>

    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
    <script src="js/login.js"></script>
  </body>
</html>

六、登錄頁后端

// 登錄
router.get("/login", (req, res) => {
  res.render("login");
});
router.post("/login", (req, res) => {
  var { username, phone, password } = req.body;

  // 去資料庫查找phone和password
  USER.findOne({ phone, password })
    .then((result) => {
      if (phone === result.phone && password === result.password) {
        // 如果手機號和密碼都正確,則登錄成功
        var id = result._id;
        // console.log(id);

        res.cookie("phone", phone);
        res.cookie("id", id);

        res.send({
          code: 200,
          message: "登錄成功",
          data: {
            phone,
            id,
          },
        });
      } else {
        res.send({
          code: 304,
          message: "手機號或密碼錯誤",
        });
      }
    })
    .catch((err) => {
      res.send({
        code: 500,
        message: "資料庫內部錯誤",
      });
    });
});

登錄用到了cookie,可以通過用后端發送cookie給客戶端,并在客戶端存盤,然后前端可以通過判斷cookie中的phone是否存在,來判斷用戶是否登錄

  • 登錄頁ajax請求部分

    // 獲取后臺傳送的cookie
    if (document.cookie.indexOf("phone") >= 0) {
      // 如果cookie里的phone存在,則把index頁面中的登錄換成用戶名
      // 想要獲取當前手機號,可以使用cookie中的phone
      // console.log(document.cookie); // phone=17692414892; id=j%3A%225f5c9c1f203b5c3b2ca5c27c%22
      // 通過 ; 切割字串
      // console.log(document.cookie.split(";")); // ["phone=17692414892", " id=j%3A%225f5c9c1f203b5c3b2ca5c27c%22"]
      // 取第零個 -- 手機號
      // console.log(document.cookie.split(";")[0]); // phone=17692414892
      // 利用 = 切割字串
      // console.log(document.cookie.split(";")[0].split("=")); // ["phone", "17692414892"]
      // 然后再取第一個就可以了
      var phone = document.cookie.split(";")[0].split("=")[1];
      // console.log(phone);
      // 對登錄a標簽進行文本替換,herf地址也換一下,可以換成個人主頁
      $(".login").text(phone);
      $(".login").attr("href", "/about");
    
    
      // about頁邏輯
      $(".about").text(phone + "~ 歡迎你");
    }
    

順便就把個人主頁寫出來了

七、個人主頁前端

<!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" />
    <link rel="stylesheet" href="css/about.css" />
  </head>
  <body>
    <div class="app">
      <header>
        <a href="/index">首頁</a>
        <a href="/login" class="login">登錄</a>
        <a href="/logout">退出</a>
      </header>
      <div class="about"></div>
      <img
        class="seekfocus"
        src="https://cdn.jsdelivr.net/gh/extheor/images/%E6%B1%82%E5%85%B3%E6%B3%A8.jpg"
        alt=""
      />
    </div>
  </body>

  <script src="https://cdn.bootcdn.net/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
  <script src="js/index.js"></script>
</html>

CSS樣式:

body {
  background: #31a5de;
}
.app {
  background: #edf1f8;
}
.about {
  background: #edf1f8;
  width: 80%;
  height: 20%;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  border-radius: 8px;
  box-shadow: 0 4px 8px 6px rgba(7, 17, 27, 0.06);

  text-align: center;
  line-height: 100px;
  font-size: 18px;
}

八、個人主頁后端

// 個人主頁
router.get("/about", (req, res) => {
  // 在資料庫中查找到所有的資料進行回傳
  USER.find({}, (err, datas) => {
    if (err === null) {
      res.render("about", {
        datas,
      });
    } else {
      res.send({
        code: 500,
        message: "資料庫內部錯誤",
      });
    }
  });
});

點擊 手機號

即可出現以下頁面

九、退出后端(沒有前端頁面)

// 退出
router.get("/logout", (req, res) => {
  // 清除cookie
  res.clearCookie("phone");
  res.clearCookie("id");

  // 重定向
  res.writeHead(302, {
    Location: "/index",
  });
  // 結束回應程序
  // 用于快速結束沒有任何資料的回應
  res.end("");
});

十、搜索后端

// 搜索
router.get("/search", (req, res) => {
  // 根據id搜索資訊
  var { username } = req.query;
  // 把前端傳遞過來的username在資料庫進行查找,然后回傳結果給前端
  if (username !== "") {
    // 如果用戶名不為空,則查詢對應的用戶
    USER.find({ username }, (err, datas) => {
      if (err === null) {
        res.send({
          datas,
        });
      } else {
        res.send({
          code: 500,
          message: "資料庫內部錯誤",
        });
      }
    });
  }
  // 如果用戶名不為空,則查詢所有的用戶
  else {
    USER.find({}, (err, datas) => {
      if (err === null) {
        res.send({
          datas,
        });
      } else {
        res.send({
          code: 500,
          message: "資料庫內部錯誤",
        });
      }
    });
  }
});
  • 然后前端發送資料給后端,讓后端在資料庫里查詢想要的結果,然后后端在把結果回傳給前端,前端只需渲染到頁面上即可

    // 搜索邏輯
    // 按用戶名 -- 搜索
    $(".searchButton").on("click", (event) => {
      if (document.cookie.indexOf("phone") >= 0) {
        // 如果進入到這里說明用戶已登錄
    
        // 獲取到用戶在搜索框輸入的用戶名
        var username = {
          username: $(".searchInput").val(),
        };
        // 發送ajax請求,后端會傳給前端資料,讓前端進行頁面處理
        $.ajax("/search", {
          type: "get",
          data: username,
          success: function (response) {
            // console.log(response.datas);
            var result = response.datas;
            // console.log(result[0].username);
    
            if (result[0]) {
              // 如果查詢到的結果不為空
              // 先把ul串列清空
              $(".userul").empty();
    
              // 回圈遍歷result
              $.each(result, (index, data) => {
                console.log(data);
                var html = `<li class="${data.username}">
                <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串列中
                $(".userul").append(html);
              });
            } else {
              // 如果查詢到的結果為空
              alert("當前沒有該用戶");
            }
        },
        });
      //   var username = datas
      } else {
      // 如果進入到這里說明用戶未登錄
        alert("請先登錄!!!");
      }
    });
    

    注意:該操作必須登錄

    效果如下:

十一、投票后端

// 投票
router.get("/vote", (req, res) => {
  // 當前端點擊投票按鈕時獲取到前端發送過來的投票數,然后自加
  var { username } = req.query;
  USER.findOne({ username }, (err, datas) => {
    if (err === null) {
      // 修改資料庫中vaotNum的值 -- update
      // console.log(datas); // 從資料庫查到的資料集合(物件)
      // 從資料庫中修改用戶點擊的用戶的投票數
      USER.updateOne(
        { username },
        { voteNum: ++datas.voteNum },
        (err, voteNum) => {
          if (err === null) {
            // console.log("點贊成功");
            res.send({
              code: 200,
              message: "點贊成功",
              datas,
            });
          } else {
            console.log("點贊失敗");
          }
        }
      );
    }
  });
});
  • 首先是前端點擊投票a標簽,然后通過Ajax發送給后端,后端接收到資料后,從資料庫進行查找,每點擊一次投票數(voteNum)加一,然后 后端會把這個結果回傳給前端,前端可以使用這個資料,來重新繪制HTML頁面

  • 前端ajax請求如下

    // 投票
    // 因為li標簽是動態創建的,所以需要通過事件委托來獲取投票按鈕
    $(".userul").delegate(".vote", "click", function () {
      if (document.cookie.indexOf("phone") >= 0) {
        var $this = $(this);
        var username = $this.parents("li").attr("class");
        var data = {
          username,
        };
        $.ajax("/vote", {
          type: "get",
          data,
          success: function (response) {
            // console.log(response.datas);
            if (response.code === 200) {
              // 先獲取到資料庫中該用戶的票數
              var voteNum = response.datas.voteNum;
              console.log(voteNum);
              // 通過 全域$this 找到voteNum元素
              var $voteNum = $this.parents(".right").children(".voteNum");
              // 然后把voteNum重新繪制到HTML頁面即可
              $voteNum.text(voteNum);
            }
          },
        });
      } else {
        alert("請先登錄!!!");
      }
    });
    

    到這里,基本的投票功能也已經能實作了,如下效果

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/40087.html

標籤:其他

上一篇:誰說程式員不會寫詩?人工智能詩詞大賽來啦!!

下一篇:求助:HTP ALM的相關問題

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more