跳转至

创建前后端项目

创建项目

版本

npm --version
# 9.5.0
node -v
# v18.15.0
npm init vite@latest database-front-web

element-plus

下载 element-plus

npm install element-plus --save

main.js 中

import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
app.use(ElementPlus);

router

下载 router

npm install vue-router --save

main.js 中

import router from 'vue-router'
app.use(router)

在 src 下创建 router 文件夹,在 router 文件夹中创建 index.js 文件

index.js 中

import { createRouter, createWebHistory } from 'vue-router'

const router = createRouter({
    history: createWebHistory(),
    routes: [
        {
            path: '/',
            name: "login",  // 这个名字可以随便起
            component: () => import('@/views/Login.vue'),
        }
    ]
})

export default router

写第一个页面 Login

进入网址即显示的界面

前端

配置路由

src/router/index.js

import { createRouter, createWebHistory } from 'vue-router'

const router = createRouter({
    history: createWebHistory(),
    routes: [
        {
            path: '/',
            name: "Login",
            component: () => import('@/views/Login.vue'),
        }
    ]
})

export default router

写界面

在 views 文件夹下创建一个文件 Login

<template>
  <div>注册登录页面</div>
</template>

<script setup>
</script>

<style lang="scss"></style>

发送请求

axios.get(url, { params: params }).then(function (response) {
            console.log(response);
            if (response.data.code == 200) {
                proxy.Message.success("登录成功");
                router.push({ path: '/home' });
            } else {
                proxy.Message.error("登录失败");
            }
        }).catch(function (error) {
            console.log(error);
        });

后端

主要做的时候就是写 Model(模型) 和 Controller(控制器),每写一个模型都要去数据库上下文中进行配置

配置 MySQL 数据库

添加数据库上下文

  • 数据库上下文类是为给定数据模型协调 EF Core 功能的主类。
  • 上下文派生自 Microsoft.EntityFrameworkCore.DbContext。
  • 上下文指定数据模型中包含哪些实体。
using auth.Models;
using Microsoft.EntityFrameworkCore;
namespace auth.Database;

public class AppDbContext : DbContext
{
    public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }

    public DbSet<User> Users { get; set; }  // 对应 Models/User.cs
}

下载需要的包

dotnet add package Pomelo.EntityFrameworkCore.Mysql 

没有这个包的话,下面代码中的 UseMySQL 和 ServerVersion 都不能使用

在 Program.cs 中注册数据库上下文

builder.Services.AddDbContext<auth.Database.AppDbContext>(options =>
{
    options.UseMySql(builder.Configuration.GetConnectionString("mysql"),  // dotnet add package Pomelo.EntityFrameworkCore.Mysql
        ServerVersion.AutoDetect(builder.Configuration.GetConnectionString("mysql")));
});

写 Model

模型是一组表示应用管理的数据的类。

(简单理解为 Model 与数据库中的表一一对应)

在 Models 文件夹下创建一个名为 User.cs 的文件

using System.ComponentModel.DataAnnotations;  // for Key
using System.ComponentModel.DataAnnotations.Schema;  // for Column

namespace auth.Models;

[Table("t_user")]
public class User
{
    // 请与数据库中表字段保持一致
    [Key]
    [Column("UserId")]
    public int UserId { get; set; }
    [Column("UserName")]
    public string? UserName { get; set; }
    [Column("PassWord")]
    public string? PassWord { get; set; }
}

写 Controller

在 Controllers 文件夹下创建一个名为 LoginController.cs 的文件

(简单理解为一个 xxxController.cs 文件对应一个 api,对应一个功能点)

using Microsoft.AspNetCore.Mvc;
using auth.Database;
using Microsoft.EntityFrameworkCore;

[ApiController]
[Route("api/[controller]")]  // RESTful 风格
public class loginController : ControllerBase  // 命名规范,继承自 ControllerBase 类的类名必须与 Controller 结尾
{
    private readonly AppDbContext _database;

    public loginController(AppDbContext appDbContext)
    {
        _database = appDbContext;
    }

    // http://localhost:5045/api/login?id=1&password=xxx
    [HttpGet]
    public IActionResult CheckUser(int id, string password)  // 对外暴露的接口参数名为 id 和 password
    {
        var code = 200;
        var msg = "success";
        object data = _database.Users.ToListAsync().Result;
        // 遍历 data,找到id和password匹配的用户
        foreach (var user in (System.Collections.Generic.List<auth.Models.User>)data)
        {
            if (user.UserId == id && user.PassWord == password)
            {
                code = 200;
                msg = "登录成功";
                break;
            }
            else
            {
                code = 400;
                msg = "用户名或密码错误";
            }
        }
        return Ok(new
        {
            code = code,
            msg = msg,
        });
    }
}

知识点

  • 修改配置文件后,要重新运行项目 npm run dev

配置跨域 CROS

在 vue3 中 vite.config.js

import { fileURLToPath, URL } from 'node:url'

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))  // 为 src 创建一个别名
    }
  },
  server: {
    proxy: {
      '/api': {
        target: 'http://localhost:5000',
        changeOrigin: true,  // 允许跨域请求
        rewrite: (path) => path.replace(/^\/api/, '')
      }
    }
  },

})

封装 axis 请求

在 src/utils 文件夹下创建 Request.js 文件

import axios from 'axios';  // 引入axios

// 创建axios实例
const instance = axios.create({
    baseURL: '/api', // api的base_url
    timeout: 5000                  // 请求超时时间
});

// 请求前过滤器
install.interceptors.request.use();

// 请求后过滤器
install.interceptors.response.use();

const request = (config) => {

}

export default request;

el-form 组件

属性名 说明 类型 默认值
model 表单数据对象 object
rules 表单验证规则 object

Vue3 中的 ref 属性

参考:https://cn.vuejs.org/guide/essentials/template-refs.html

<script setup></script> 中定义函数的两种形式

// 箭头函数
const log = () => {
  console.log(msg)
}

function log() {
    console.log(msg)
}

尽量使用箭头函数

组合式 API 和选项式 API

使用组合式 API,配合 setup 语法糖,不要使用选项式 API,组合式 API 和选项式 API 是 Vue 组件编写的两种风格,参考 https://cn.vuejs.org/guide/introduction.html#api-styles

选项式 API

使用选项式 API,我们可以用包含多个选项的对象来描述组件的逻辑,例如 datamethodsmounted。选项所定义的属性都会暴露在函数内部的 this 上,它会指向当前的组件实例。

<script>
export default {
  // data() 返回的属性将会成为响应式的状态
  // 并且暴露在 `this` 上
  data() {
    return {
      count: 0
    }
  },

  // methods 是一些用来更改状态与触发更新的函数
  // 它们可以在模板中作为事件监听器绑定
  methods: {
    increment() {
      this.count++
    }
  },

  // 生命周期钩子会在组件生命周期的各个不同阶段被调用
  // 例如这个函数就会在组件挂载完成后被调用
  mounted() {
    console.log(`The initial count is ${this.count}.`)
  }
}
</script>

<template>
  <button @click="increment">Count is: {{ count }}</button>
</template>

组合式 API

通过组合式 API,我们可以使用导入的 API 函数来描述组件逻辑。在单文件组件中,组合式 API 通常会与 <script setup> 搭配使用。这个 setup attribute 是一个标识,告诉 Vue 需要在编译时进行一些处理,让我们可以更简洁地使用组合式 API。比如,<script setup> 中的导入和顶层变量/函数都能够在模板中直接使用。

下面是使用了组合式 API 与 <script setup> 改造后和上面的模板完全一样的组件:

<script setup>
import { ref, onMounted } from 'vue'

// 响应式状态
const count = ref(0)

// 用来修改状态、触发更新的函数
function increment() {
  count.value++
}

// 生命周期钩子
onMounted(() => {
  console.log(`The initial count is ${count.value}.`)
})
</script>

<template>
  <button @click="increment">Count is: {{ count }}</button>
</template>

关于 .vue 文件的几点说明

<template>
  <div></div>
</template>

<script setup>
</script>

<style lang="scss"></style>

上面是我们项目的推荐格式,script 标签后面有 setup,style 标签后有 lang="scss"

在网上查/找代码时,你可能会看到有的代码没有这些,问题也不大,尽量用我们给的格式。

style lang="scss"></style> 包含 <style></style> ,即前者是后者的超集,所以不管你写的是什么,直接加上 lang="scss"

有无 setup 的区别比较大,一两句话也说不清楚,可以自己百度搜搜看。简单来说就说就是,加上 setup 后,就不需要 export xxx。请不要使用 <script setup lang="ts"><script> ,即不要使用 typescript语法。

可以看看这篇文章,https://blog.csdn.net/u013505589/article/details/122718376,以及官方文档,https://cn.vuejs.org/api/sfc-script-setup.html

API 开发指南

Controllers

Models

下载软件:Apifox (https://apifox.com)