用户模块封装数据模型层

news2024/11/25 15:38:58

数据模型层

数据模型层(Data Model Layer)是指在应用程序中用于表示和处理数据的模型层。这一层通常是应用程序的核心,因为它 负责从各种数据源获取数据并保证这些数据与应用程序的功能相匹配

在一个应用程序中,数据模型层通常包含以下几个组件:

1.数据模型:数据模型用于描述应用程序所使用的数据实体及其属性、关系以及操作。它决定了应用程序如何存储、访问和处理数据。

2.数据访问层:数据访问层负责从各种数据源(例如数据库、文件系统、Web服务等)中获取数据。它可以为应用程序提供统一的接口来访问和操作数据,以此提高应用程序的可维护性和扩展性。

3.业务逻辑层:业务逻辑层根据应用程序的需求,对数据进行处理和转换。它负责将数据转换成应用程序所需的格式,并执行各种计算、判断和决策逻辑,以此实现业务功能。

数据模型层是现代应用程序开发中非常重要的一部分,因为它可以帮助开发人员更好地管理和处理数据,提高应用程序的可靠性、性能和安全性。

封装数据模型层

数据模型层是应用程序中负责数据存储和管理的部分,其能够对应用程序中的业务逻辑进行数据的持久化。

为了实现良好的代码组织和可维护性,我们通常会采用封装的方式来对数据模型层进行设计和实现。

在封装数据模型层时,我们可以采用面向对象编程的思想,将数据模型抽象为一个类,并提供一系列的公共方法,让其他模块可以通过调用这些公共方法来完成对数据模型的操作。

同时,我们还可以对数据模型进行属性的私有化和封装,以防止外部直接访问和修改数据模型的内部状态,确保数据的安全性和完整性。

另外,在实现数据模型层时,我们可以考虑使用开源的 ORM(对象关系映射)框架,如 SQLAlchemy 等,以便于快速、高效地实现数据模型和数据库之间的映射,避免手动书写繁琐的 SQL 语句,从而提高开发效率和代码质量。

更多精彩内容,请微信搜索“前端爱好者戳我 查看

用户模块封装数据模型层

第一步,项目中创建controller文件夹,用于业务逻辑控制层

对于每一个模块,用单独的controller进行管理。

第二步,controller文件夹中新建user.js文件,用于处理用户模块控制操作。

此部分操作,需要把之前在 router/user.js 中的请求方法整合到 controller/user.js

// server/controller/user.js
const User = require('../models/users') // 引入users modal 

//添加系统用户
const userAdd = async (ctx) => {
    let {
        username = '', pwd = ''
    } = ctx.request.body
    await User.create({
        username,
        pwd
    }).then(rel => {
        if (rel) {
            ctx.body = {
                code: 200,
                msg: '添加成功',
                data: rel
            }
        } else {
            ctx.body = {
                code: 300,
                msg: '添加失败'
            }
        }

    }).catch(err => {
        ctx.body = {
            code: 400,
            msg: '添加时出现异常'
        }
        console.error(err)
    })
}

//修改用户
const userUpdate = async (ctx) => {
    let params = ctx.request.body
    await User.updateOne({
        _id: params._id
    }, {
        username: params.username,
        pwd: params.pwd
    }).then(rel => {
        ctx.body = {
            reslut: rel
        }
    }).catch(err => {
        ctx.body = {
            code: 400,
            msg: '修改时出现异常'
        }
        console.error(err)
    })
}

//删除用户
const userDel = async (ctx) => {
    let {
        _id
    } = ctx.request.body
    await User.findOneAndDelete({
        _id
    }).then(rel => {
        ctx.body = {
            reslut: rel
        }
    }).catch(err => {
        ctx.body = {
            code: 400,
            msg: '删除时出现异常'
        }
        console.error(err)
    })
}

//查询所有用户
const userFind = async (ctx) => {
    await User.find().then(rel => {
        ctx.body = {
            result: rel
        }
    }).catch(err => {
        ctx.body = {
            code: 400,
            msg: '查询时出现异常'
        }
        console.error(err)
    })
}

//查询单个用户
const userFindOne = async (ctx) => {
    await User.findOne({
        _id: ctx.params.id
    }).then(rel => {
        ctx.body = {
            result: rel
        }
    }).catch(err => {
        ctx.body = {
            code: 400,
            msg: '查询时出现异常'
        }
        console.error(err)
    })
}


module.exports = {
    userAdd,
    userUpdate,
    userDel,
    userFind,
    userFindOne
}

第三步,修改 router/user.js文件

const router = require('koa-router')()

const userControl = require('../controller/user')

router.prefix('/users') 

//添加系统用户
router.post('/add', userControl.userAdd)

//修改系统用户
router.post('/update', userControl.userUpdate)

//删除系统用户
router.post('/del', userControl.userDel)

//查询所有系统用户
router.get('/find', userControl.userFind)

//查询单个系统用户
router.get('/find/:id', userControl.userFindOne)

module.exports = router

每日一课: ES6 新增属性 第二部分

ES6 (ECMAScript 2015) 引入了许多新的语法和功能特性,其中一些新增的属性包括:

函数默认参数

函数默认参数是指在定义函数时,为某些参数设置了默认值,使得在函数调用时,如果没有为这些参数提供实参,则自动使用其默认值。

函数默认参数的语法格式为:在函数定义中,对需要设置默认值的参数,通过赋值的方式来设置默认值。

例如:

def my_func(a, b=10, c=20):
    print("a=", a)
    print("b=", b)
    print("c=", c)

在上述代码中,参数b和c都被设置为有默认值的参数,分别为10和20。这意味着在函数调用时,即使不为它们提供实参,它们也会自动使用其默认值。

当然,如果在函数调用时为这些参数提供了实参,则函数将使用提供的实参而不是默认值

例如:

my_func(5) # a=5, b=10, c=20
my_func(5, 30) # a=5, b=30, c=20
my_func(5, 30, 40) # a=5, b=30, c=40

在上述代码中,第一个函数调用只为参数a提供了实参,所以参数b和c使用了默认值。

第二个函数调用提供了a和b两个实参,所以只有参数c使用了默认值。

第三个函数调用为所有参数都提供了实参,所以所有参数都使用了实参而非默认值。

函数默认参数可以方便地为函数的使用者提供灵活性,使得函数调用更加简单和易用。

Rest 参数和展开运算符

Rest 参数(Rest Parameters)和展开运算符(Spread Operator)是一种新的参数语法,它们可以使函数接受任意数量的参数,并将它们转换为数组或对象。

Rest参数

是指把一个函数的多个参数收集成为一个数组。

在函数定义时,最后一个形参前添加三个点(...)即可创建一个 Rest 参数

例如:

function myFunc(...args) {
  console.log(args);
}
myFunc(1, 2, 3, 4); // 输出 [1, 2, 3, 4]

在上述代码中,函数myFunc使用了Rest参数args,可以看到函数被调用时,所有的实参都被收集到一个数组中,并赋值给了args。

展开运算符

是对一个数组或对象进行“打散”,把其中的元素或属性提取出来,逐个作为函数的实参传递。

在函数调用时,在数组或对象前添加三个点(…)即可使用展开运算符。

例如:

function myFunc(a, b, c) {
  console.log(a, b, c);
}

let arr = [1, 2, 3];
myFunc(...arr); // 输出 1 2 3

let obj = {x: 1, y: 2, z: 3};
myFunc(...Object.values(obj)); // 输出 1 2 3

在上述代码中,第一个例子中,arr数组通过展开运算符被“打散”,其中的元素分别作为函数myFunc的实参传递。

第二个例子中,obj对象的值被提取出来通过展开运算符作为函数myFunc的三个实参传入。

Rest参数和展开运算符使得函数的参数使用更加简单明了。

类和继承

ES6 引入了类(Class)语法,用于更方便地创建对象。类支持继承,可以实现更复杂的对象关系。

类和继承(Class and Inheritance),ES6 引入了 class 和 extends 关键字,可以通过面向对象的方式定义类和继承关系。

类和继承的概念,使得JavaScript代码可以更加符合面向对象编程的思想。

类(class) 是一种类似于构造函数的声明方式,它定义了一个对象的属性和方法。

类的声明语法如下:

class MyClass {
  constructor() {
    // 构造函数
  }
  method1() {
    // 方法1
  }
  method2() {
    // 方法2
  }
  // ...
}

在上述代码中,使用class关键字声明了一个名为MyClass的类,该类内部定义了一个构造函数和若干个方法。

其中:

  • 构造函数使用constructor()定义,用于创建对象实例;
  • 方法则直接在类中进行定义,不需要使用function关键字。

继承(inheritance) 则是指一个类可以从另一个类中继承属性和方法。

继承的语法如下:

class SubClass extends SuperClass {
  constructor() {
    super();
    // 子类的构造函数
  }
  method3() {
    // 新增的方法3
  }
  // ...
}

在上述代码中,使用extends关键字声明了一个名为SubClass的子类,该子类继承自SuperClass父类,并定义了一个构造函数和若干个方法。

其中,通过使用super()函数调用父类的构造函数,以便在创建子类对象时初始化父类的属性。

子类中还可以新增、重写和调用父类的方法。

例如,下面的代码定义了一个“形状”类和“矩形”子类

class Shape {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
  move(x, y) {
    this.x += x;
    this.y += y;
  }
}

class Rectangle extends Shape {
  constructor(x, y, width, height) {
    super(x, y);
    this.width = width;
    this.height = height;
  }
  getSize() {
    return {width: this.width, height: this.height};
  }
}

let rect = new Rectangle(10, 20, 100, 200);
console.log(rect.x, rect.y); // 输出 10 20
console.log(rect.getSize()); // 输出 {width: 100, height: 200}
rect.move(5, 10);
console.log(rect.x, rect.y); // 输出 15 30

在上述代码中,通过定义Shape类来表示一个二维图形,并实现了一个move()方法用于移动图形。

然后使用Rectangle子类继承自Shape父类,并添加了一个getSize()方法用于获取矩形的大小。

在主函数中创建了一个Rectangle对象,并可以通过调用父类的方法和子类新增的方法分别对其进行操作。

ES6中引入的类和继承机制为JavaScript代码提供了更加规范和易用的面向对象编程方式。

Promise 对象

ES6中引入了Promise对象,它可以用于处理异步操作,并通过 链式调用的方式 使代码更加简洁清晰。

Promise对象表示一个异步操作的最终完成或失败,并返回结果值或错误原因。

它主要包含三种状态:

  • pending(等待完成)
  • fulfilled(已完成)
  • rejected(已失败)。

当异步操作完成后,Promise对象可以通过调用 then() 方法来获取处理结果;在异步操作失败时,可以通过调用 catch() 方法来获取处理失败的原因。

Promise的语法如下:

let myPromise = new Promise((resolve, reject) => {
  // 异步操作
  if (异步操作成功) {
    resolve(异步操作成功返回值);
  } else {
    reject(异步操作失败原因);
  }
});

myPromise.then((result) => {
  // 处理成功结果
}).catch((reason) => {
  // 处理失败原因
});

在上述代码中,使用new关键字创建一个Promise对象,并在构造函数中传入一个函数作为参数,该函数接受两个参数(resolve和reject),这两个参数都是函数类型。

在异步操作完成后

  • 如果执行成功,就调用resolve()函数并传入返回值;
  • 否则就调用reject()函数并传入错误原因。

在调用then()方法时,

  • 如果异步操作执行成功,则接收到的参数是resolve()函数中的返回值;
  • 在调用catch()方法时,如果异步操作执行失败,则接收到的参数是reject()函数中的错误原因。

使用Promise对象可以使异步操作的处理更加清晰易懂,也可以方便地进行链式调用。

例如:

function getData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve({data: 'hello world'});
    }, 1000);
  });
}

getData().then((result) => {
  console.log(result.data); // 输出 hello world
}).catch((reason) => {
  console.error(reason);
});

在上述代码中,通过定义getData()函数返回一个Promise对象,在异步操作完成时调用resolve()函数并传入结果。

在调用then()方法时,可以获取到异步操作成功后的结果,并在回调函数中进行处理。

如果异步操作失败,则会被catch()方法捕获并处理。

ES6中引入的Promise对象为异步操作提供了便捷的处理方式,可以让 异步代码 更容易理解和维护。

模块化导入和导出

ES6 引入了模块化导入和导出语法,允许我们将代码拆分成多个文件,以便更好地组织代码。

这些新增属性使得 JavaScript 语言更加强大和灵活,方便开发人员编写更加高效、易读、易维护的代码。

在ES6中,可以使用模块化的方式对代码进行组织和管理,使得代码更加清晰易懂,也更容易复用和维护。

模块(module) 是一种独立的代码单元,可以包含变量、函数、类等,并可以从其他模块中导入和导出这些内容。

ES6中使用 exportimport 关键字来实现模块的导出和导入。

模块的导出语法如下:

// 导出单个值
export const myValue = 123;

// 导出多个值
export function myFunc() {
  // ...
}
export class MyClass {
  // ...
}

在上述代码中,使用export关键字将一个或多个值进行导出。

可以导出单个值,例如一个变量,也可以导出多个值,例如一个函数和一个类。

导出的值可以在其他模块中直接引用和使用。

模块的导入语法如下:

// 导入单个值
import { myValue } from './myModule.js';

// 导入多个值
import { myFunc, MyClass } from './myModule.js';

在上述代码中,使用import关键字从指定路径的模块中导入一个或多个值。

可以通过 花括号{}指定要导入的值的名称 ,也可以 使用星号*导入所有值

导入的值可以在当前模块中使用,并且不需要使用全局变量或命名空间等。

例如,下面的代码定义了一个myModule.js模块:

const myValue = 123;

function myFunc() {
  console.log('Hello, world');
}

class MyClass {
  constructor(x) {
    this.x = x;
  }
  printX() {
    console.log(`x=${this.x}`);
  }
}

export { myValue, myFunc, MyClass };

在主函数中可以使用import语句来导入该模块中的内容:

import { myValue, myFunc, MyClass } from './myModule.js';

console.log(myValue);   // 输出 123
myFunc();               // 输出 'Hello, world'
let obj = new MyClass(10);
obj.printX();           // 输出 'x=10'

在上述代码中,使用import关键字从myModule.js模块中分别导入了myValue变量、myFunc函数和MyClass类,并在主函数中分别进行了使用。

ES6中引入的模块化机制为JavaScript代码提供了更加清晰易懂的结构,也为代码的复用和维护提供了更多选择。

块级作用域

在ES6之前,JavaScript中只有 函数作用域全局作用域 ,而没有块级作用域。

块级作用域(block scope) 是指变量和函数的作用域限定在当前的代码块(花括号{})内部,而不是整个函数或全局范围内。

在ES6中,可以使用 letconst 关键字来声明块级作用域的变量和常量。

例如:

function test() {
  if (true) {
    let x = 123;
    console.log(x);   // 输出 123
  }
  console.log(x);     // 报错,x未定义
}

test();

在上述代码中,使用let关键字声明了一个名为x的变量,并将其限定在if代码块中

在该代码块内部可以正常使用x变量,而在该代码块外部则无法访问该变量,因为它的作用域受限于该代码块。

需要注意的是,使用var关键字声明的变量是函数作用域的,在函数内部定义的变量会被“提升”到函数顶部,并且变量的改变也会影响到函数内的其他代码块。

例如:

function test() {
  if (true) {
    var x = 123;
    console.log(x);   // 输出 123
  }
  console.log(x);     // 输出 123
}

test();

在上述代码中,使用var关键字声明了一个名为x的变量,并将其限定在if代码块中。

在该代码块内部可以正常使用x变量,但是在该代码块外部也可以访问该变量,并且在函数内部对该变量的赋值操作也会影响到该代码块之外的其他代码。

ES6中引入的块级作用域机制为JavaScript代码提供了更加灵活和严谨的变量管理方式,使得代码结构更加清晰易懂,也更容易排查错误。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/651840.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MidJourney使用教程:二 初识Prompts

最近AIGC这么火,除了chatGPT以外,这种图像类的产品也是非常有意思,其中就有MidJourney和Stable Diffusion这俩个比较出圈。这里我先选择MidJourney来体验并整理出一个教程。一方面MidJourney最简单,能当路Discord,注册…

正则替换的方式删除特定的内容

以前,公司网络限制,无法通过用户名密码登录某些网站,但是可以通过浏览器打开网站,而这些网站有个问题,非登录用户,不能复制博客中的代码,这个就有些麻烦了。 好在,这些代码是可以通过…

6.vue3医疗在线问诊项目 - _极速问诊-订单选择页面 ==> 问诊级别(普通/三甲)、科室选择(一级科室、二级科室)、病情描述、选择患者

6.vue3医疗在线问诊项目 - _极速问诊-订单选择页面 > 问诊级别(普通/三甲)、科室选择(一级科室、二级科室)、病情描述、选择患者 极速问诊-选择问诊级别-路由{#consult-change-type} 完成选择三甲还是普通问诊页面&#xff0c…

【Hadoop】大数据开发环境配置

【Hadoop】大数据开发环境配置 文章目录 【Hadoop】大数据开发环境配置1 设置静态ip2 设置主机名3 关闭防火墙4 ssh免密码登录5 JDK配置6 hadoop安装并配置6.1 集群节点之间时间同步6.2 SSH免密码登录完善6.3 hadoop配置 1 设置静态ip 进入ifcfg-ens33文件 vi /etc/sysconfig/n…

JAVA图形界面GUI

目录 一、窗口、窗格、按钮、标签 设置一个窗口JFrame 设置一个窗格JPanel和按钮JButton 设置一个标签JLabel 标准写法 二、监听器ActionListener 用内部类实现 用匿名内部类实现 用LAMADA表达式实现 三、文本域、复选框、下拉列表 JTextField单行文本域 JCheckBox复选…

智能算法终极大比拼,以CEC2017测试函数为例,十种智能算法直接打包带走,不含任何套路

包含人工蜂群(ABC)、灰狼(GWO)、差分进化(DE)、粒子群(PSO)、麻雀优化(SSA)、蜣螂优化(DBO)、白鲸优化(BWO)、遗传算法(GA)、粒子群算法(PSO),基于反向动态学习的差分进化算法,共十种算法,直接一文全部搞定! 其中基于反向动态学习…

Dalamud 插件开发白皮书 P1 - Getting started

文章目录 从哪里开始 How do I get started?Dalamud 插件例子Dalamud 底层探究XIVLauncher 启动器 在哪里寻找帮助 Where do I ask for help?如何热重载插件 How do I hot-reload my plugin?如何调试插件,甚至游戏?如何在编码过程中使用 How do I use…

国内几款强大的语言模型

写在前面 Hello大家好, 我是【麟-小白】,一位软件工程专业的学生,喜好计算机知识。希望大家能够一起学习进步呀!本人是一名在读大学生,专业水平有限,如发现错误或不足之处,请多多指正&#xff0…

STC15WProteus仿真红绿灯直行左右转紧急模式STC15W4K32S4-0041

STC15WProteus仿真红绿灯直行左右转紧急模式STC15W4K32S4-0041 Proteus仿真小实验: STC15WProteus仿真红绿灯直行左右转紧急模式STC15W4K32S4-0041 功能: 硬件组成:STC15W4K32S4单片机 2位数码管5个LED灯(红 黄 ←绿 ↑绿 →绿…

《网络基础之socket理解》

【一】socket是什么 从字面上的意思来理解,这玩意的中文含义叫插座,对你想的没错,就是你家用来插电器的插座,只不过你家的插座是用来导电的,而网络里面的socket是用来传导信息的。 【二】网络socket传送数据流程 我们…

基于阻尼绕组起动同步电动机matlab完整程序分享

主要包含输出转速,感应转矩,磁场变化,感应电压,感应电流等6个参数变化曲线图!! 完整程序如下: clc; clear; close all; warning off; addpath(genpath(pwd)); %電機參數設定 r_stat_in=15;%stator內圈半徑 r_stat_out=17;%stator外圈半徑 width_rot=2;%rotor細部寬度 leng…

【瑞萨RA_FSP】DAC —— 输出正弦波

文章目录 一、DAC简介二、DAC的结构框图1. 参考电压2. 触发源3. DAC数据寄存器4. 转换的过程5. 同步转换 三、生成正弦波数据表四、DAC程序设计1. 硬件设计2. 软件设计①文件结构②FSP配置③DAC初始化函数④设置DAC输出电压函数⑤DAC输出正弦波⑥ hal_entry入口函数 一、DAC简介…

多用户商城软件有哪些开发方式?-加速度jsudo

电商时代之下,企业商家纷纷开始了b2b2c商城系统的搭建,以此来抢占电商市场,但由于大多企业商家并没有专业化的开发团队,所以大多会选择将网站建设外包给专业的商城系统开发公司,但就目前而言,b2b2c商城系统…

改进YOLOv8 | 损失函数篇 | YOLOv8 更换损失函数之 SIoU / EIoU / WIoU / Focal_xIoU 最全汇总版

文章目录 更换方式CIoUDIoUEIoUGIoUSIoUWIoUFocal_CIoUFocal_DIoUFocal_EIoUFocal_GIoUFocal_SIoU提示更换方式 第一步:将ultralytics/yolo/utils/metrics.py文件中的bbox_iou替换为如下的代码:class

基于微信小程序的云音乐管理系统+第三稿+文档

博主介绍:✌在职Java研发工程师、专注于程序设计、源码分享、技术交流、专注于Java技术领域和毕业设计✌ 项目名称 基于微信小程序的云音乐管理系统第三稿文档 视频演示 基于微信小程序的云音乐管理系统第三稿问题解答任务书开题报告查重报告安装视频讲解视频&#…

【计算机网络】第三章传输层-电子科技大学2023期末考试

第三章 传输层 传输层服务与协议 传输层为两个不同主机上的应用程序之间提供逻辑通信机制 传输层协议运行在端系统 发送方: 将应用程序报文分成数据段传递给网络层,接受方: 将数据段重新组装成报文传递到应用层 网络层为两个主机之间提供逻辑通信 主要提供两种协议TCP和U…

RTC

文章目录 前言驱动应用程序运行 前言 RTC(Real Time Clock,实时时钟)是个常用的外设,通过 RTC 我们可以知道日期和时间信息,因此在需要记录时间的场合就需要实时时钟。 可以使用专用的实时时钟芯片来完成此功能&#…

PostgreSQL如何创建临时表?

分类 PostgreSQL支持两种临时表: 会话级临时表:数据可以一直保存在整个会话的生命周期中事务级临时表:数据只存在于这个事务的生命周期中 在PostgreSQL中,不管是事务级的临时表还是会话级的临时表,当会话结束时都会…

家庭版Windows10/Windows11不支持远程桌面的解决办法

家庭版Windows10或11是不支持远程桌面的。我们可以在电脑的“设置”-> “远程桌面设置”中查看系统是否支持远程桌面:我们可以通过RDPWrap这个项目让家庭版也支持远程桌面。 百度网盘下载 首先在下面网址下载该项目,下载zip:https://gith…

【wifi使用指导】wifi模块怎么用?无线路由wifi模块SKW92A/SKW77网页配置说明

据悉,在全球范围内,WiFi承载了超过一半的数据流量,并且65%-90%的智能手机流量来自WiFi。无线覆盖的实现依赖于WiFi模块提供的WiFi信号,支持AP/Client,Bridge,Gateway,Router,3G/4G R…