NodeJS全栈开发一个功能完善的Express项目(附完整源码)

本文详细介绍了如何使用Node.js的Express框架和前端Vue.js,结合MySQL数据库,开发一个功能完整的Web应用。从项目初始化、前端Vue项目创建到后端Express接口实现,包括登录注册、数据库设计、服务端配置、自动化重启服务和PM2进程管理等,提供了详细的步骤和代码示例。此外,还分享了项目源码链接和运维部署的注意事项。
摘要由CSDN通过智能技术生成

一. 前言

Node.js对前端来说无疑具有里程碑意义,与其越来越流行的今天,掌握 Node.js 技术已经不仅仅是加分项,而是前端攻城师们必须要掌握的一项技能。而 Express 基于 Node.js 平台,快速、开放、极简的 Web 开发框架,成为 Node.js 最流行的框架,所以使用 Express 进行 web 服务端的开发是个不错且可信赖的选择。但是 Express 初始化后,并不马上就是一个开箱即用,各种功能完善的 web 服务端项目,例如:MySQL 连接、jwt-token 认证、md5 加密、中间件路由模块、异常错误处理、跨域配置、自动重启等一系列常见的功能,需要开发者自己手动配置安装插件和工具来完善功能,如果你对 web 服务端开发或者 Express 框架不熟悉,那将是一项耗费巨大资源的工作。

本文作者根据项目实战经验已将底层服务架构搭建完成,并且本项目已在 github 开源,供大家学习参考使用(如有不足,还请批评指正),希望能减轻大家的工作量,更高效的完成工作,有更多时间提升自己的能力。

后端 API 接口源码地址 👉:https://github.com/jackchen0120/todo-nodejs-api

前端界面源码地址 👉:https://github.com/jackchen0120/todo-vue-admin

如果觉得本文还不错,记得点个 👍 或者给个 ❤️,你们的赞和 star 是作者编写更多更精彩文章的动力!

分享之前我们先来认识一下Node.js、Express都是什么东东。

Node.js

简单的说 Node.js 就是运行在服务端的 JavaScript。

Node.js 是一个基于 Chrome JavaScript 运行时建立的一个平台。

Node.js 是一个事件驱动 I/O 服务端 JavaScript 环境,基于 Google 的 V8 引擎,V8 引擎执行 Javascript 的速度非常快,性能非常好。

Express

Express 是一个简洁而灵活的 Node.js Web 应用框架,提供了一系列强大特性帮助你创建各种 Web 应用,和丰富的 HTTP 工具。使用 Express 可以快速地搭建一个完整功能的网站。

Express 框架核心特性:

  • 可以设置中间件来响应 HTTP 请求。
  • 定义了路由表用于执行不同的 HTTP 请求动作。
  • 可以通过向模板传递参数来动态渲染 HTML 页面。

二. 前后端分离

前端项目采用的技术栈是基于Vue + iView,用 vue-cli 构建前端界面,后端项目采用的技术栈是基于Node.js + Express + MySQL,用 Express 搭建的后端服务器。

Web3研习社 👉:[https://54web3.cc/)

部分效果截图

三. 前端部分

3.1 基础环境

开发前准备工作,相关运行环境配置如下:

工具名称 版本号
node.js 10.16.2
npm 6.9.0

运行项目

1> 下载安装依赖

git clone https://github.com/jackchen0120/todo-vue-admin.git

cd todo-vue-admin

npm install 或 yarn

2> 开发模式

npm run serve

运行之后,访问地址:http://localhost:8082

3> 生产环境打包

npm run build


3.2 目录结构

│  package.json                      // npm包管理所需模块及配置信息
│  vue.config.js                     // webpack配置
├─public
│      favicon.ico                   // 图标
│      index.html                    // 入口html文件
└─src
    │  App.vue                       // 根组件
    │  main.js                       // 程序入口文件
    ├─assets                         // 存放公共图片文件夹
    ├─components
    │      Footer.vue                // 页面底部公用组件
    │      Header.vue                // 页面头部公用组件
    ├─router
    │      index.js                  // 单页面路由注册组件
    ├─store
    │  │  index.js                   // 状态管理仓库入口文件
    │  └─modules
    │          userInfo.js           // 用户模块状态管理文件
    ├─styles
    │      base.scss                 // 基础样式文件
    ├─utils
    │      api.js                    // 统一封装API接口调用方法
    │      network.js                // axios封装与拦截器配置
    │      url.js                    // 自动部署服务器环境
    │      valid.js                  // 统一封装公用模块方法
    └─views
            Home.vue                 // 首页界面
            Login.vue                // 登录界面

3.3 技术栈

  • vue2.6
  • vue-router
  • vuex
  • axios
  • webpack
  • ES6/7
  • flex
  • iViewUI

3.4 功能模块

  • 登录(登出)
  • 注册
  • 记住密码
  • 忘记密码(修改密码)
  • todoList 增删改查
  • 点亮红星标记
  • 查询条件筛选

3.5 代码实现

3.5.1 全局安装 vue-cli4

npm install -g @vue/cli
#安装指定版本

npm install -g @vue/cli@4.4.0

#OR

yarn global add @vue/cli

3.5.2 vue-cli4 创建项目及运行

vue create todo-vue-admin

cd todo-vue-admin

npm run serve

3.5.3 开发配置

在项目根目录新增vue.config.js文件,配置信息如图所示:

3.5.4 其他事项

按照上面的步骤完成脚手架搭建后,把需要的 axios、vue-router、view-design、sass-loader、node-sass 等依赖库安装配置好,准备开始上膛。

3.5.5 实现前端登录注册功能

首先在 views 文件夹下面新建login.vue组件,编写一个静态的登录注册页面。登录成功后将登录返回的 token 保存到浏览器端并跳转到主页。views 文件夹下面新建home.vue组件,显示登录成功后的页面,并获取用户基本信息,主页右上角显示用户头像、修改密码、退出登录等功能。代码如下:

<template>
  <div class="login-container">
      <div class="pageHeader">
        <img src="../assets/logo.png" alt="logo">
        <span>TODOList区块链管理平台</span>
      </div>
      <div class="login-box">
        <div class="login-text" v-if="typeView != 2">
          <a href="javascript:;" :class="typeView == 0 ? 'active' : ''" @click="handleTab(0)">登录</a>
          <b>·</b>
          <a href="javascript:;" :class="typeView == 1 ? 'active' : ''" @click="handleTab(1)">注册</a>
        </div>
        <!-- 登录模块 -->
        <div class="right-content" v-show="typeView == 0">
          <div class="input-box">

            <input
              autocomplete="off"
              type="text"
              class="input"
              v-model="formLogin.userName"
              placeholder="请输入登录邮箱/手机号"
            />
            <input
              autocomplete="off"
              type="password"
              class="input"
              v-model="formLogin.userPwd"
              maxlength="20"
              @keyup.enter="login"
              placeholder="请输入登录密码"
            />
          </div>
          <Button
            class="loginBtn"
            type="primary"
            :disabled="isDisabled"
            :loading="isLoading"
            @click.stop="login">
            立即登录
          </Button>

          <div class="option">
            <Checkbox class="remember" v-model="checked" @on-change="checkChange">
              <span class="checked">记住我</span>
            </Checkbox>
            <span class="forget-pwd" @click.stop="forgetPwd">忘记密码?</span>
          </div>
        </div>

        <!-- 注册模块 -->
        <div class="right_content" v-show="typeView == 1">
          <div class="input-box">
            <input
              autocomplete="off"
              type="text"
              class="input"
              v-model="formRegister.userName"
              placeholder="请输入注册邮箱/手机号"
            />
            <input
              autocomplete="off"
              type="password"
              class="input"
              v-model="formRegister.userPwd"
              maxlength="20"
              @keyup.enter="register"
              placeholder="请输入密码"
            />
            <input
              autocomplete="off"
              type="password"
              class="input"
              v-model="formRegister.userPwd2"
              maxlength="20"
              @keyup.enter="register"
              placeholder="请再次确认密码"
            />
          </div>
          <Button
            class="loginBtn"
            type="primary"
            :disabled="isRegAble"
            :loading="isLoading"
            @click.stop="register">
            立即注册
          </Button>
        </div>
      </div>
  </div>
</template>
<style lang="scss" scoped>
.login-container {
   
  background-image: url('../assets/bg.png');
  background-position: center;
  background-size: cover;
  position: relative;
  width: 100%;
  height: 100%;

  .pageHeader {
   
    padding-top: 30px;
    padding-left: 40px;

    img {
   
      vertical-align: middle;
      display: inline-block;
      margin-right: 15px;
    }

    span {
   
      font-size: 18px;
      display: inline-block;
      vertical-align: -4px;
      color: rgba(255, 255, 255, 1);
    }
  }

  .login-box {
   
    position: absolute;
    left: 64vw;
    top: 50%;
    -webkit-transform: translateY(-50%);
    transform: translateY(-50%);
    box-sizing: border-box;
    text-align: center;
    box-shadow: 0 1px 11px rgba(0, 0, 0, 0.3);
    border-radius: 2px;
    width: 420px;
    background: #fff;
    padding: 45px 35px;
    .option {
   
      text-align: left;
      margin-top: 18px;
      .checked {
   
        padding-left: 5px;
      }
      .forget-pwd, .goback {
   
        float: right;
        font-size: 14px;
        font-weight: 400;
        color: #4981f2;
        line-height: 20px;
        cursor: pointer;
      }
      .protocol {
   
        color: #4981f2;
        cursor: pointer;
      }
    }

    .login-text {
   
      width: 100%;
      text-align: center;
      padding: 0 0 30px;
      font-size: 24px;
      letter-spacing: 1px;
      a {
   
        padding: 10px;
        color: #969696;
        &.active {
   
          font-weight: 600;
          color: rgba(73, 129, 242, 1);
          border-bottom: 2px solid rgba(73, 129, 242, 1);
        }
        &:hover {
   
          border-bottom: 2px solid rgba(73, 129, 242, 1);
        }
      }
      b {
   
        padding: 10px;
      }
    }
    .title {
   
      font-weight: 600;
      padding: 0 0 30px;
      font-size: 24px;
      letter-spacing: 1px;
      color: rgba(73, 129, 242, 1);
    }

    .input-box {
   
      .input {
   
        &:nth-child(1) {
   
          /*margin-top: 10px;*/
        }
        &:nth-child(2),
        &:nth-child(3) {
   
          margin-top: 20px;
        }
      }
    }

    .loginBtn {
   
      width: 100%;
      height: 45px;
      margin-top: 40px;
      font-size: 15px;
    }

    .input {
   
      padding: 10px 0px;
      font-size: 15px;
      width: 350px;
      color: #2c2e33;
      outline: none; // 去除选中状态边框
      border: 1px solid #fff;
      border-bottom-color: #e7e7e7;
      background-color: rgba(0, 0, 0, 0); // 透明背景
    }

    input:focus {
   
      border-bottom-color: #0f52e0;
      outline: none;
    }
    .button {
   
      line-height: 45px;
      cursor: pointer;
      margin-top: 50px;
      border: none;
      outline: none;
      height: 45px;
      width: 350px;
      background: rgba(216, 216, 216, 1);
      border-radius: 2px;
      color: white;
      font-size: 15px;
    
  • 96
    点赞
  • 261
    收藏
    觉得还不错? 一键收藏
  • 34
    评论
评论 34
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值