第一篇、搭建前(vue)后(node)端环境,开发一个简单的登录功能

一、环境准备

  • 操作系统:支持 macOS,Linux,Windows
  • 运行环境:建议选择 LTS 版本,最低要求 8.x。

二、快速初始化服务端eggjs项目

Egg.js 为企业级框架和应用而生,我们希望由 Egg.js 孕育出更多上层框架,帮助开发团队和开发人员降低开发和维护成本。

注:Egg.js 缩写为 Egg

设计原则

我们深知企业级应用在追求规范和共建的同时,还需要考虑如何平衡不同团队之间的差异,求同存异。所以我们没有选择社区常见框架的大集市模式(集成如数据库、模板引擎、前端框架等功能),而是专注于提供 Web 开发的核心功能和一套灵活可扩展的插件机制。我们不会做出技术选型,因为固定的技术选型会使框架的扩展性变差,无法满足各种定制需求。通过 Egg,团队的架构师和技术负责人可以非常容易地基于自身的技术架构在 Egg 基础上扩展出适合自身业务场景的框架。

Egg 的插件机制有很高的可扩展性,一个插件只做一件事(比如 Nunjucks 模板封装成了 egg-view-nunjucks、MySQL 数据库封装成了 egg-mysql)。Egg 通过框架聚合这些插件,并根据自己的业务场景定制配置,这样应用的开发成本就变得很低。

Egg 奉行『约定优于配置』,按照一套统一的约定进行应用开发,团队内部采用这种方式可以减少开发人员的学习成本,开发人员不再是『钉子』,可以流动起来。没有约定的团队,沟通成本是非常高的,比如有人会按目录分栈而其他人按目录分功能,开发者认知不一致很容易犯错。但约定不等于扩展性差,相反 Egg 有很高的扩展性,可以按照团队的约定定制框架。使用 Loader 可以让框架根据不同环境定义默认配置,还可以覆盖 Egg 的默认约定。

与社区框架的差异

Express 是 Node.js 社区广泛使用的框架,简单且扩展性强,非常适合做个人项目。但框架本身缺少约定,标准的 MVC 模型会有各种千奇百怪的写法。Egg 按照约定进行开发,奉行『约定优于配置』,团队协作成本低。

Sails 是和 Egg 一样奉行『约定优于配置』的框架,扩展性也非常好。但是相比 Egg,Sails 支持 Blueprint REST API、WaterLine 这样可扩展的 ORM、前端集成、WebSocket 等,但这些功能都是由 Sails 提供的。而 Egg 不直接提供功能,只是集成各种功能插件,比如实现 egg-blueprint,egg-waterline 等这样的插件,再使用 sails-egg 框架整合这些插件就可以替代 Sails 了。

特性

安装

推荐直接使用脚手架,只需几条简单指令,即可快速生成项目(npm >=6.1.0):

$ mkdir egg-example && cd egg-example
$ npm init egg --type=simple
$ npm i

得到目录结构如下:

egg-project
├── package.json
├── app.js (可选)
├── agent.js (可选)
├── app
|   ├── router.js
│   ├── controller
│   |   └── home.js
│   ├── service (可选)
│   |   └── user.js
│   ├── middleware (可选)
│   |   └── response_time.js
│   ├── schedule (可选)
│   |   └── my_task.js
│   ├── public (可选)
│   |   └── reset.css
│   ├── view (可选)
│   |   └── home.tpl
│   └── extend (可选)
│       ├── helper.js (可选)
│       ├── request.js (可选)
│       ├── response.js (可选)
│       ├── context.js (可选)
│       ├── application.js (可选)
│       └── agent.js (可选)
├── config
|   ├── plugin.js
|   ├── config.default.js
│   ├── config.prod.js
|   ├── config.test.js (可选)
|   ├── config.local.js (可选)
|   └── config.unittest.js (可选)
└── test
    ├── middleware
    |   └── response_time.test.js
    └── controller
        └── home.test.js

启动项目:

$ npm run dev
$ open http://localhost:7001

三、建立一个会员信息表,mysql>=5.7

建立一个会员信息表,有用户名密码等信息

四、使用egg-mysql插件访问数据库

egg框架提供了 egg-mysql 插件来访问 MySQL 数据库。这个插件既可以访问普通的 MySQL 数据库,也可以访问基于 MySQL 协议的在线数据库服务。

安装与配置

安装对应的插件 egg-mysql

$ npm i --save egg-mysql

开启插件:

// config/plugin.js
exports.mysql = {
  enable: true,
  package: 'egg-mysql',
};

config/config.${env}.js 配置各个环境的数据库连接信息。

单数据源

如果我们的应用只需要访问一个 MySQL 数据库实例,可以如下配置:

// config/config.${env}.js
exports.mysql = {
  // 单数据库信息配置
  client: {
    // host
    host: 'mysql.com',//本机127.0.0.1
    // 端口号
    port: '3306',
    // 用户名
    user: 'test_user',
    // 密码
    password: 'test_password',
    // 数据库名
    database: 'users',//users
  },
  // 是否加载到 app 上,默认开启
  app: true,
  // 是否加载到 agent 上,默认关闭
  agent: false,
};

使用方式:

await app.mysql.query(sql, values); // 单实例可以直接通过 app.mysql 访问

多数据源

如果我们的应用需要访问多个 MySQL 数据源,可以按照如下配置:

exports.mysql = {
  clients: {
    // clientId, 获取client实例,需要通过 app.mysql.get('clientId') 获取
    db1: {
      // host
      host: 'mysql.com',
      // 端口号
      port: '3306',
      // 用户名
      user: 'test_user',
      // 密码
      password: 'test_password',
      // 数据库名
      database: 'test',
    },
    db2: {
      // host
      host: 'mysql2.com',
      // 端口号
      port: '3307',
      // 用户名
      user: 'test_user',
      // 密码
      password: 'test_password',
      // 数据库名
      database: 'test',
    },
    // ...
  },
  // 所有数据库配置的默认值
  default: {

  },

  // 是否加载到 app 上,默认开启
  app: true,
  // 是否加载到 agent 上,默认关闭
  agent: false,
};

使用方式:

const client1 = app.mysql.get('db1');
await client1.query(sql, values);

const client2 = app.mysql.get('db2');
await client2.query(sql, values);

在数据库里建一个users表

service层

  • 在app目录下新建service目录,用来放置service层的代码

  • 新建一个users.js文件

  'use strict';
  
  const Service = require('egg').Service;
  
  class UsersService extends Service {
  
      async account(name, pwd) {
          const result = await this.app.mysql.select('users', { // 搜索 users 表
              where: { name: name, password: pwd }, // WHERE 条件
          });
          return result;
      }
  }
  
  module.exports = UsersService;

controller层

  • 在controller目录下新建account.js
'use strict';

const Controller = require('../core/base_controller');

class AccontController extends Controller {
  async account() {
    const { ctx } = this;
    //解析post请求的参数
    const name = ctx.request.body.loginname;
    const pwd = ctx.request.body.password;
    let res = await ctx.service.users.account(name,pwd);//调用service层的方法
    this.success(res);
    
  }
}

module.exports = AccontController;
  • 这里base_controller是自己创建的一个基类controller,在app目录下新建“/core/base_controller.js”。
const { Controller } = require('egg');
class BaseController extends Controller {
  success(data) {
    this.ctx.body = {
      success: true,
      data,
    };
  }

  notFound(msg) {
    msg = msg || 'not found';
    this.ctx.throw(404, msg);
  }
}
module.exports = BaseController;
  • 配置服务端路由
'use strict';

/**
 * @param {Egg.Application} app - egg application
 */
module.exports = app => {
  const { router, controller } = app;
  router.get('/', controller.home.index);
  router.post('/account', controller.accont.account);//我们的简单登录验证接受post请求
    // controller.accont.account 是accountController里的account方法,,,accont拼写错了
};

这样我们简单的一个服务端就写好了。

五、初始化一个前端vue项目

  • 安装一下vue的clivue-cli,初始化一个vue工程
npm install -g @vue/cli-service-global
vue ui //用图形化界面创建vue工程

六、引用element-ui 插件

自己配一个喜欢的主题色,我自己瞎配了个绿色。

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import './plugins/element.js'

Vue.config.productionTip = false

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

七、封装请求模块

安装axios

在src目录下新建“http/http.js”,在这里我们先初步简单封装一下我们前端的请求模块:

import axios from "axios";

axios.defaults.timeout = 5000;
axios.defaults.baseURL = 'http://127.0.0.1:7001';
// axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
axios.defaults.headers.post['Content-Type'] = 'application/json';



function get(url, data = {}) {
    return new Promise((resolve, reject) => {
        axios.get(url, {
            params: data
        }).then(response => {
            resolve(response.data);
        }).catch(err => {
            reject(err)
        })
    })
}

function post(url, data = {}) {
    return new Promise((resolve, reject) => {
        axios.post(url, data).then(response => {
            resolve(response.data);
        }).catch(err => {
            reject(err)
        });
    })
}

function patch(url, data = {}) {
    return new Promise((resolve, reject) => {
        axios.patch(url, data)
            .then(response => {
                resolve(response.data);
            }, err => {
                reject(err)
            })
    })
}

function put(url, data = {}) {
    return new Promise((resolve, reject) => {
        axios.put(url, data)
            .then(response => {
                resolve(response.data);
            }, err => {
                reject(err)
            })
    })
}

export default { get,post,patch,put }

在新建一个api.js文件用来管理一下我们前端的请求接口:

import http from "./http";

/**
 * login 页面
 */
export const login = (data) => http.post("/account",data);//用户登录

八、创建登录页面,实现简单登录

在views里新建“login/login.vue”

<template>
    <div>
        <div style="height: 300px;margin-top: 100px">
            <p style="text-align: center;"><img src="../../assets/logo.png"></p>
        </div>
        <div style="width: 350px;margin: 0 auto">

            <el-form ref="form" :model="form">
                <el-form-item label="">
                    <el-input v-model.trim="form.loginname" placeholder="用户名"></el-input>
                </el-form-item>
                <el-form-item label="">
                    <el-input v-model.trim="form.password" placeholder="密码"></el-input>
                </el-form-item>
                <el-form-item label="">
                    <el-button type="primary" style="width: 100%" @click="login">登录</el-button>
                </el-form-item>
            </el-form>
        </div>
    </div>
</template>

<script>
    import {login} from "../../http/api";

    export default {
        name: "loign",
        data() {
            return {
                form: {
                    loginname: "",
                    password: ""
                }
            }
        },
        methods: {
            login() {
                login(this.form).then(res => {
                    if (res.success) {
                        if(res.data.length > 0){
                            this.$message.success("成功!页面跳转中");
                            this.$router.push("/conent");
                        }else {
                            this.$message.error("失败");
                        }

                    }else {
                        this.$message.error("失败")
                    }
                }).catch(e => {
                    console.log(e)
                })
            }
        }
    }
</script>

<style scoped>

</style>

配置一下前端路由

    {
        path: '/',
        name: 'Login',
        component: Login
    },
      npm run serve

好啦,一个简单的登录完成了!
快来打赏我吧!

posted @ 2020-06-22 20:49  球球不吃虾  阅读(528)  评论(0编辑  收藏  举报