1、前端技术栈:Vue 3 + Pinia + Vite + TypeScript + Element-Plus + Axios + Eslint + Sass + 其它…
- Pinia 不需要 Vuex 自定义复杂的类型去支持 TypeScript,天生对类型推断就非常友好,并且对 Vue Devtool 的支持也非常好,被称为下一代 Vuex。
- 学习 TypeScript 推荐视频(黑马程序员)
2、后端技术栈:Node.js + Koa 2 + MySQL + 其它…
- Koa 2 实现异步是通过 async/awaite,Koa 实现异步是通过 generator/yield,而 Express 实现异步是通过回调函数的方式。写 Node.js 建议使用 Koa2 > Koa > Express。
- 学习 Koa 2 推荐文档(aka 老师) + 配套视频
学习 Koa 2 推荐文档2(廖雪峰)
项目演示地址
前端的项目链接
小剧场
- 报错
GET http://127.0.0.1:5173/index/means1.png 404 (Not Found)- 报错截图
- 相关代码
- 问题
在使用v-for
循环渲染标签的时候,图片资源无法渲染。
- 分析问题
- 可能是相对路径或者绝对路径问题导致图片资源加载失败。
- 可能是 vue 3 中对静态资源方式进入做了更改。
- 可能是其它问题。
如何使用 element-plus 表单验证单个字段
以上是整个表单。
一般情况下,我们使用 element-plus 框架提供的validate
方法会对整个表单都进行校验。
我希望在填写 “电话” 的时候,只使用校验规则的电话部分;在填写 “邮箱” 的时候,只使用校验规则的邮箱部分…
此时,我们可以使用 element-plus 提供的validateField
方法,就能很好地解决问题。
同时,使用clearValidate
方法可以达到清除部分校验规则的目的。
使用方法如下:
<el-form ref="ruleFormRef" :model="form" :rules="rules" label-width="110px" label-position="left">
<el-form-item label="电话" prop="phone">
<el-input v-model="form.phone" placeholder="请输入电话" />
<el-button type="primary" @click="saveValue('phone', ruleFormRef)">保存</el-button>
<el-button @click="inputValue('phone', 'close')">取消</el-button>
</el-form-item>
<el-form-item label="邮箱" class="item" prop="email">
<el-input v-model="form.email" placeholder="请输入邮箱" />
<el-button type="primary" @click="saveValue('email', ruleFormRef)">保存</el-button>
<el-button @click="inputValue('email', 'close')">取消</el-button>
</el-form-item>
</el-form>
<script lang="ts" setup>
import { reactive, ref } from "vue";
import type { FormInstance, FormRules } from "element-plus";
import { validateEmailNotEmpty, validatePhoneNotEmpty } from "@/utils/validator";
/* src/utils/validator.ts
export const validatePhoneNotEmpty = (rule: any, value: any, callback: any) => {
if (value === "") {
callback(new Error("Phone can not be empty"));
} else {
const reg =
/^(0|86|17951)?(13[0-9]|15[012356789]|166|17[3678]|18[0-9]|14[57])[0-9]{8}$/;
if (reg.test(value)) {
// 正确
callback();
} else {
// 错误
callback(new Error("Wrong format! Please check and enter again"));
}
}
};
export const validateEmailNotEmpty = (rule: any, value: any, callback: any) => {
if (value === "") {
callback(new Error("Email can not be empty"));
} else {
const reg = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
if (reg.test(value)) {
// 正确
callback();
} else {
// 错误
callback(new Error("Wrong format! Please check and enter again"));
}
}
};
*/
const ruleFormRef = ref<FormInstance>();
const form = reactive({
phone: "", // 电话
email: "", // 邮箱
})
// 校验规则
const rules = reactive<FormRules>({
phone: [
{
trigger: "blur",
validator: validatePhoneNotEmpty,
},
],
email: [
{
trigger: "blur",
validator: validateEmailNotEmpty,
},
]
})
// 重置该表单项,并移除校验结果
const clearValidate = (formEl: FormInstance | undefined) => {
if (!formEl) return;
formEl.clearValidate();
};
// 保存
const saveValue = async (item: string, formEl: FormInstance | undefined) => {
if (!formEl) return;
if (item === "phone") {
formEl.validateField("phone", () => null); // 对单一字段 phone 进行校验
} else if (item === "email") {
formEl.validateField("email", () => null); // 对单一字段 email 进行校验
}
};
// 取消
const inputValue = (item: string, bool: string) => {
if(item === "phone"){
form.phone = "";
clearValidate(ruleFormRef.value); // 清除 phone 的校验规则
} else if(item === "email"){
form.email= "";
clearValidate(ruleFormRef.value); // 清除 email 的校验规则
}
}
</script>
后端的项目链接
小剧场
写多条 SQL 语句的时候,不能嵌套着用
*
,否则在做数据合并时,如果字段重复,会报冲突的错误。
错误写法:
推荐写法:
小剧场
数据库的时间是正确的,但是获取的时候,时间少了 8 小时。如图:
MySQL 时间正确,但是后端获取到的时间就是错误的,所以在后端连接 MySQL 的配置中加了timezone: "08:00"
这样解决了后端获取时间错误的问题。搞定!
MySQL 语句
多表合并查询
应用:(根据某相同字段)查询多个表中数据的集合。
语法:select 字段,字段,字段 from 表a,表b where 表a.字段=表b.字段
例:select username,password,phone,note from user,message where user.id=message.user_id
或:select * from user,message where user.id=message.user_id
1. 内联接
释义:A={ 1, 2, 3, 4, 5 } B= { 2, 5, 8 } A∩B = { 2, 5 }
sql 简单写法:
select a.列1, a.列2, b.列1, b.列2
from A a, B b
where a.主键 = b.外键
A:表名
B:表名
sql 标准写法:
select a.列1, a.列2, b.列1, b.列2
from A a
inner join B b
on a.主键 = b.外键
2. 外联接
左外联接
左边有的,右边没有的以 null 填充
sql 写法:
select ...
from ...
left join ...
on ...
例:
select S.studentName,R.subjectNo,R.student.Result
from student as s
left join result as R
on s.studentNo=R.studentNo;
右外联接
右边有的,左边没有的以 null 填充
3. 交叉联接(全联接 | 笛卡尔积)
释义:A={ A, B, C } B= { a, b } A*B = { Aa, Ab, Ba, Bb, Ca, Cb }
sql 简单写法:
select a.*, b.*
from A a, B b
sql 标准写法:
select a.*, b.*
from A a CROSS join B b
此推荐和本文无直接关系:
番外:如何上线你的项目?这里提供了代码,可以快速体验项目上线的快感
点击这里可查看如何进入宝塔:
至此,前后端均已上传到服务器上。下面的操作,要将项目跑起来,在浏览器中可以在线查看
在服务器的宝塔操作面板上,添加 Node 项目 → 选择项目目录【第4步创建的】
番外:导入本地 txt 文件到 MySQL 表中
导入完毕后可能发会遇到一些报错,暂时不要理。
原因:前端路由配置有问题。
解决:调整前端的路由模式。
核心操作:修改 router 配置中的 createWebHistory 为 createWebHashHistory
解决办法:
listen 8066; # 没有被占用的端口
server_name localhost; # 固定 localhost
index index.html index.htm index.php; # 不用改
root /www/wwwroot/koa2/public; # 服务器上的图片资源路径
try_files $uri $uri/ /index.html; # 固定内容,没有请自行添加
要点:上传图片的到服务器时候,用的依旧是 api 接口的端口号;从服务器获取图片的时候,用的是 Nginx 配置中的端口号。
背景:绑定后域名,要加上端口号才能正常访问到网页。想要去除端口后,网页也能正常访问到。怎么优化?
80 端口是默认端口,默认不显示。访问到 80 端口时,代理到了 8088 端口,实现了去除域名后+端口才能访问网页的问题。
项目演示地址
前端的项目链接 (⑅˃◡˂⑅) 记得在 github 点赞收藏哦!
后端的项目链接 (⑅˃◡˂⑅) 记得在 github 点赞收藏哦!