nodejs笔记【4项目完结】

目录

    • 1.项目流程
    • 2.项目搭建
      • 2.1 初始化项目
      • 2.2 项目速成(后端)
        • 1. controller目录下的`blog.js`文件
        • 2. db目录下的`mysql.js`文件
        • 3. model目录下的`resModel.js`文件
        • 4. routher目录下的`blog.js`文件
        • 5. 根目录下`app.js`文件
      • 2.3 项目速成(前端)
        • 1. `index.html`页面
    • 3. 最终效果

源代码链接:https://pan.baidu.com/s/1QBytlPhuPdCAFOoMd72WDA

提取码:a757

1.项目流程


后端文件目录

  • app.js项目的入口文件
  • src目录:存储项目开发中用到的文件,换言之就是存储我们开发者编写的文件
    • controller目录:控制器。业务逻辑代码放进来
      • blog.js文件:博客列表
    • db目录:存放数据库
      • mysql.js:数据库文件
    • model目录:模型
      • resModel.js文件
    • router目录:存储路由文件
      • blog.js文件:路由文件

前端文件目录:

  • layui包
  • index.html文件

2.项目搭建


2.1 初始化项目

创建package.json文件,敲下面命令

npm init -y

安装mysql模块,敲下面命名。并在mysql文件中调用

cnpm i mysql

2.2 项目速成(后端)

1. controller目录下的blog.js文件

const {
      exec } = require("../db/mysql");
const {
      SuccessModel } = require("../model/resModel");
const moment =require('moment')
// 博客列表
const getList = () => {
     
 /*let result= exec("select * from blogs");
 return result.then(data=>{
   data.forEach(item=>{
    item.createtime=moment(item.createtime).format('YYYY-MM-DD HH:mm:ss')
   })
   return data
 })*/
 return exec("select * from blogs");
};
// 博客详情
const getDetail = (id) => {
     
  return exec("select * from blogs where id=" + id);
};
// 新增数据
const newBlog = function (blogData) {
     
  console.log(blogData);
  let sql = `insert into blogs values(null,'${
       blogData.title}','${
       
    blogData.content
  }',${
       Date.now()},'${
       blogData.author}')`;
  console.log(sql);
  let result = exec(sql);
  return result.then((data) => {
     
    return data.insertId;
  });
};
/**
 * 更新博客
 * id:要更新的博客的id
 * postData:结构如下:{title:'更改后的title',content:'更改后的content'}
 */
const updateBlog = (id, postData) => {
     
  let sql = `update blogs set title='${
       postData.title}',content='${
       postData.content}' where id=${
       id}`;
  let result = exec(sql);
  return result.then((data) => {
     
    return data.affectedRows == 1 ? true : false;
  });
};
// 删除博客
const deleteBlog = (id) => {
     
  let sql = `delete from blogs where id=${
       id}`;
  let result = exec(sql);
  return result.then((data) => {
     
    return data.affectedRows == 1 ? true : false;
  });
};
module.exports = {
     
  getList,
  getDetail,
  newBlog,
  updateBlog,
  deleteBlog,
};

2. db目录下的mysql.js文件

const mysql = require("mysql");
// 创建链接
const con = mysql.createConnection({
     
  host: "localhost",
  user: "root",
  password: "root",
  port: 3306,
  database: "new",
});
// 打开链接
con.connect();
const exec = (sql) => {
     
  return new Promise((resolve, reject) => {
     
    con.query(sql, (err, result) => {
     
      if (err) {
     
        reject("执行sql语句失败");
        return;
      }
      resolve(result);
    });
  });
};
module.exports={
     
    exec
}

3. model目录下的resModel.js文件

class BaseModel {
     
  constructor(msg, data) {
     
    this.msg = msg;
    this.data = data;
  }
}
class SuccessModel extends BaseModel {
     
  constructor(msg, data) {
     
    super(msg, data);
    this.errno = 0;
  }
}
class ErrorModel extends BaseModel {
     
  constructor(msg, data) {
     
    super(msg, data);
    this.errno = -1;
  }
}
module.exports = {
     
  SuccessModel,
  ErrorModel,
};

4. routher目录下的blog.js文件

/**
 * 路由文件:接受用户的请求,并进行返回数据
 */
// 引入blog 控制器
const {
     
  getList,
  getDetail,
  newBlog,
  updateBlog,
  deleteBlog,
} = require("../controller/blog");
const {
      SuccessModel, ErrorModel } = require("../model/resModel");
const handlerBlog = (req) => {
     
  // 使用 URL 模块对 req.url 进行封装
  let myUrl = new URL(req.url, "http://127.0.0.1:3000/");
  let method = req.method;
  let pathname = myUrl.pathname;

  // console.log(pathname);
  let msgResult = null;
  if (pathname == "/api/blog/list" && method == "GET") {
     
    msgResult = getList();
    // then 方法的返回值也是一个 promise
    return msgResult.then((data) => {
     
      return new SuccessModel("", data);
    });
  } else if (pathname == "/api/blog/detail" && method == "GET") {
     
    let id = myUrl.searchParams.get("id");
    msgResult = getDetail(id);
    return msgResult.then((data) => {
     
      return new SuccessModel("", data);
    });
  } else if (pathname == "/api/blog/new" && method == "POST") {
     
    msgResult = newBlog(req.body);
    return msgResult.then((data) => {
     
      return new SuccessModel("", data);
    });
  } else if (pathname == "/api/blog/update" && method == "POST") {
     
    let id = myUrl.searchParams.get("id");
    let postData = req.body;
    msgResult = updateBlog(id, postData);
    return msgResult.then((data) => {
     
      return new SuccessModel("", data);
    });
  } else if (pathname == "/api/blog/del" && method == "GET") {
     
    let id = myUrl.searchParams.get("id");
    msgResult = deleteBlog(id);
    return msgResult.then((data) => {
     
      return new SuccessModel("", data);
    });
  }
  return msgResult;
};
// 暴漏 handlerBlog 方法
module.exports = {
     
  handlerBlog,
};

5. 根目录下app.js文件

// 项目入口文件
const url = require("url");
const http = require("http");
// 引入 blog.js 模块
const blog_module = require("./src/router/blog");
const fs = require("fs");
// 创建 http 服务
const app = http.createServer((req, res) => {
     
  // 设置返回格式:JSON
  res.setHeader("content-type", "application/json");
  
  // 设置允许跨域请求
  res.setHeader("Access-Control-Allow-Origin", "http://127.0.0.1:8080"); // 允许所有路径跨域
  res.setHeader("Access-Control-Allow-Credentials", true); //允许带 cookie
  res.setHeader("Access-Control-Allow-Headers", "Content-Type,Content-Length, Authorization, Accept,X-Requested-With,xToken");
  res.setHeader("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
  res.setHeader("X-Powered-By",' 3.2.1');

  // 向客户端写入 cookie  因为跨域问题,下面代码不能实现。
  res.setHeader("Set-cookie", "username=onlifes;path=/");
  // 演示cookie 默认不能跨域写入
  // if (req.url == "/index.html") {
     
  //    let result=fs.readFileSync("./index.html")
  //    res.end(result)
  //    return
  // }
  getPostData(req).then((data) => {
     
    req.body = data; // 至此,已经能够完全获取到以post 方式提交的数据了
    let msgResult = blog_module.handlerBlog(req);
    if (msgResult) {
     
      msgResult.then((data) => {
     
        res.end(JSON.stringify(data));
        // return return 不能放在这里
      });
      return; // 中断当前函数
    }
    msgResult = {
     
      msg: "请求的接口不存在",
    };
    res.end(JSON.stringify(msgResult));
  });
});
// 处理所有网络请求
// app.on('reques',(req, res) => {});
// 启动服务
app.listen(3000, () => {
     
  console.log("Server is running at http://127.0.0.1:3000");
});
const getPostData = (req) => {
     
  /**
   * 处理以 post 方式提交的数据
   */
  // 获取以 post 方式提交的数据

  return new Promise((resolve, reject) => {
     
    if (req.method == "POST") {
     
      let postData = "";
      req.on("data", (params) => {
     
        postData += params;
      });
      req.on("end", () => {
     
        resolve(JSON.parse(postData));
      });
    } else {
     
      resolve({
     });
    }
  });
};

2.3 项目速成(前端)

下载layui包

只需要把里面的layui文件夹提出来就行

nodejs笔记【4项目完结】_第1张图片

1. index.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="/layui/css/layui.css" />
  <style>
    .form-hidden {
      
      display: none;
    }

    .form-show {
      
      display: block;
    }

    #form-add {
      
      padding-top: 20px;
    }
  style>
head>

<body>
  <div class="layui-container" style="padding-top: 50px">
    <button type="button" class="layui-btn" id="btn-add">发表文章button>
    <div class="layui-row">
      <div class="layui-col-md12">
        <table class="layui-table">
          <colgroup>
            <col width="150" />
            <col width="200" />
            <col />
            <col />
            <col />
            <col />
          colgroup>
          <thead>
            <tr>
              <th>编号th>
              <th>标题th>
              <th>内容th>
              <th>创建时间th>
              <th>作者th>
              <th>操作th>
            tr>
          thead>
          <tbody>
			
          tbody>
        table>
      div>
    div>
  div>

  
  <form class="layui-form form-hidden" action="" id="form-add">
    <div class="layui-form-item">
      <label class="layui-form-label">博客标题label>
      <div class="layui-input-block">
        <input type="text" name="title" id="title" required lay-verify="required" placeholder="请输入标题" autocomplete="off"
          class="layui-input" />
      div>
    div>

    <div class="layui-form-item layui-form-text">
      <label class="layui-form-label">博客内容label>
      <div class="layui-input-block">
        <textarea name="content" id="content" placeholder="请输入内容" class="layui-textarea">textarea>
      div>
    div>

    <div class="layui-form-item">
      <label class="layui-form-label">作者label>
      <div class="layui-input-block">
        <input type="text" name="author" id="author" required lay-verify="required" placeholder="请输入姓名" autocomplete="off"
          class="layui-input" />
      div>
    div>
    <div class="layui-form-item">
      <div class="layui-input-block">
        <button class="layui-btn" lay-submit lay-filter="formDemo">
          立即发表
        button>
        <button type="reset" class="layui-btn layui-btn-primary">重置button>
      div>
    div>
  form>
  
  <form class="layui-form form-hidden" action="" id="form-edite">
    <input type="hidden" name="" id="blog_id" />
    <div class="layui-form-item">
      <label class="layui-form-label">博客标题label>
      <div class="layui-input-block">
        <input type="text" name="title" id="edite_title" required lay-verify="required" placeholder="请输入标题"
          autocomplete="off" class="layui-input" />
      div>
    div>

    <div class="layui-form-item layui-form-text">
      <label class="layui-form-label">博客内容label>
      <div class="layui-input-block">
        <textarea name="content" id="edite_content" placeholder="请输入内容" class="layui-textarea">textarea>
      div>
    div>

    <div class="layui-form-item">
      <label class="layui-form-label">作者label>
      <div class="layui-input-block">
        <input type="text" name="author" id="edite_author" required lay-verify="required" placeholder="请输入姓名"
          autocomplete="off" class="layui-input" />
      div>
    div>
    <div class="layui-form-item">
      <div class="layui-input-block">
        <button class="layui-btn" lay-submit lay-filter="formEdite">
          立即发表
        button>
        <button type="reset" class="layui-btn layui-btn-primary">重置button>
      div>
    div>
  form>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js">script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js">script>
  <script src="/layui/layui.js">script>
  <script>



    // 声明变量,存储ajax请求的基准地址
    let baseUrl = 'http://127.0.0.1:3000/'
    

    // 展示博客数据
    var loadBlog = () => {
      
      fetch(baseUrl + "api/blog/list", {
      
          credentials: "omit",
        })
        .then((response) => {
      
          return response.json();
        })
        .then((data) => {
      
          document.querySelector('tbody').innerHTML=''
          console.log();
          data.data.forEach((item) => {
      
            let tr = `
              
                ${
        item.id}
                ${
        item.title}
                ${
        item.content}
                ${
        moment(item.createtime).format("YYYY年M月D号 H时m分s秒")}
                ${
        item.author}
                
                  
                  
                
              
              `;
            document
              .querySelector("tbody")
              .insertAdjacentHTML("afterbegin", tr);
          });
        });
    };
    
    loadBlog();

    // 声明全局变量, 存储layer.open方法的返回值,用于将来关闭此弹出层
    var index = -1;
    // 点击发表文章按钮弹出用于添加文章的层
    document.querySelector("#btn-add").addEventListener("click", () => {
      
      layui.use("layer", function () {
      
        var layer = layui.layer;

        index = layer.open({
      
          content: $("#form-add"),
          title: "添加博客",
          type: 1,
          area: ["800px", "400px"],
        });
        $("#form-add").css("display", "form-show");
      });
    });

    layui.use("form", function () {
      
      var form = layui.form;

      //监听添加
      form.on("submit(formDemo)", function (data) {
      
        // 发送 ajax 请求,新增数据
        var url = baseUrl + "api/blog/new";
        var data = {
      
          title: $("#title").val(),
          content: $("#content").val(),
          author: $("#author").val()
        };

        fetch(url, {
      
            method: "POST", // or 'PUT'
            body: JSON.stringify(data), // data can be `string` or {object}!
            headers: new Headers({
      
              "Content-Type": "application/json",
            }),
          })
          .then((res) => res.json())
          .then((response) => {
      
            if (response.errno == 0) {
      
              layer.close(index);
              layer.msg("博客发表成功");
              // 重新加载数据
              loadBlog();
              // location.reload();
            } else {
      
              layer.msg(response.msg);
            }
          });
        return false;
      });
      // 监听编辑
      form.on("submit(formEdite)", function (data) {
      
        let id = document.querySelector("#blog_id").value;
        var data = {
      
          title: $("#edite_title").val(),
          content: $("#edite_content").val(),
          content: $("#edite_content").val(),
          author: $("#edite_author").val(),
        };
        fetch(baseUrl + "api/blog/update?id=" + id, {
      
            method: "post",
            body: JSON.stringify(data),
            headers: new Headers({
      
              "Content-Type": "application/json",
            }),
          })
          .then((response) => {
      
            return response.json();
          })
          .then((data) => {
      
            if (data.data == true) {
      
              layer.close(index);
              layer.msg("博客发表成功");
              // 重新加载数据
              loadBlog();
              // location.reload();
            }
          });
        return false;
      });
    });

    // 鼠标悬浮到编辑按钮上,显示提示文字
    // document
    //   .querySelector("tbody")
    //   .addEventListener("mouseover", function (e) {
      
    //     let reg1 = /edite/;
    //     let reg2 = /delete/;
    //     if (reg1.test(e.target.className)) {
      
    //       layer.tips("编辑文章", e.target, {
      
    //         tips: 1,
    //       }); //在元素的事件回调体中,follow直接赋予this即可
    //     } else if (reg2.test(e.target.className)) {
      
    //       layer.tips("删除文章", e.target, {
      
    //         tips: 1,
    //       }); //在元素的事件回调体中,follow直接赋予this即可
    //     }
    //   });

    // 点击编辑按钮,弹出用于编辑文章的层
    document.querySelector("tbody").addEventListener("click", function (e) {
      
      let reg1 = /edite/;
      let reg2 = /delete/;

      if (reg1.test(e.target.className)) {
      
        // 获取待编辑的博客的id
        let id = e.target.dataset.id;
        // 发送ajax请求
        fetch(baseUrl + "api/blog/detail?id=" + id)
          .then((response) => {
      
            return response.json();
          })
          .then((res) => {
      
            if (res.errno == 0) {
      
              document.querySelector("#blog_id").value = res.data[0].id;
              document.querySelector("#edite_title").value =
                res.data[0].title;
              document.querySelector("#edite_content").value =
                res.data[0].content;
              document.querySelector("#edite_author").value =
                res.data[0].author;
            }
          });
        layui.use("layer", function () {
      
          var layer = layui.layer;

          index = layer.open({
      
            content: $("#form-edite"),
            title: "编辑博客",
            type: 1,
            area: ["800px", "400px"],
          });
          $("#form-edite").css("display", "form-show");
        });
      } else if (reg2.test(e.target.className)) {
      
        // 获取待编删除的博客的id
        let id = e.target.dataset.id;
        fetch(baseUrl + "api/blog/del?id=" + id)
          .then((response) => {
      
            return response.json();
          })
          .then((data) => {
      
            if (data.data == true) {
      
              layer.msg('删除成功')
              loadBlog()
              // location.reload();
            }
          });
      }
    });

  script>
body>

html>

3. 最终效果


你可能感兴趣的:(nodejs,js)