1、git的基本操作
1、推送到远程仓库
0)创建一个文件夹,右键打开Git Bash Here
1)git init //初始化仓库
2)git add . //添加文件到暂存区
3)git commit -m '说明' //将缓存区内容添加到本地仓库
4)git push//将本地项目推送到远程仓库上
git push origin master //将本地项目推送到origin远程仓库的master分支上
git remote add origin 仓库地址 //将本地仓库与远程仓库关联起来
M:没有将修改的内容保存或暂存
2、拉取到本地仓库
1)进入要克隆的文件夹里,右键打开Git Bash Here
2)找到远程仓库的地址,并复制该地址
3)使用git clone 远程仓库地址 克隆代码到本地//克隆只需要执行一次
4)git pull 拉取代码
3、合并子分支
git branch//查分支
git checkout 分支名 //切换分支
1)切换到master分支
2)git merge 分支名//合并子分支到主分支
出现冲突:两个分支都修改了同一文件同一行代码
按钮1:保留旧的;按钮2:保留新的;按钮3:都保留;按钮4:二者对比
解决冲突后要记得保存
4、添加/生成SSH公钥
git config --lsit//查看
1)绑定账户邮箱:
git config --global user.name "用户名"
git config --global user.email "邮箱"
2)生成sshkey:ssh-keygen -t rsa -C "邮箱" 一直回车
3)ssh-agent -s
4)打开C盘–>用户–>你的用户名–>找到.ssh文件夹(linux下为cat ~/.ssh/id_rsa.pub),复制里面的内容,打开gitee,进入设置,ssh设置,粘贴到公钥,点击添加即可
5、将git客户端与码云绑定
ssh -T git@gitee.com
6、合并两个仓库
1)// 添加要合并仓库的远程地址,这里将其命名为 merge_branch
git remote add merge_branch 地址
git remote -v //查看仓库地址
2)//从远程仓库下载第二个仓库的代码
git fetch merge_branch
3)//创建dev分支,并将第二个仓库代码放在dev上
git checkout -b dev merge_branch/master//将从第二个仓库下载的 master 分支作为要合入的项目,需要先将其分支 checkout 到一个新分支上
4)//切换回原来的分支
git checkout master
5)//合并两个分支
git merge dev
git merge --no-ff --allow-unrelated-histories dev
2、echarts
2.1、echarts图表的使用
1、 获取一个dom节点,该节点必须写宽高
var myChart = echarts.init(document.querySelector(ele)); myChart.setOption({})
2、legend://图例
icon:''
itemHeight//高number
itemWidth//宽number
itemStyle: //图例样式
color:颜色
align:位置
textStyle: //图例文字样式
color:颜色
right:距离左侧
3、grid:
4、series:
1)//设置渐变色
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: 'rgb(0, 221, 214)'
},
{
offset: 1,
color: 'rgb(28, 126, 215)'
}
])
}
2)series-bar.stack: 'Total'//数据堆叠
3)symbolSize: 10, //设定实心点的大小
5、xAxis://x轴
6、yAxis://y轴
1)nameTextStyle: {color: "#fff"}//y轴上方单位的颜色
2)axisLine: {//y轴线的颜色以及宽度
show: true,//显示
lineStyle: {
color: '#666',
width: 1,
type: 'solid'
}
}
3)nameGap: '20',//y轴单位字位置
7、
window.onresize = function () {
myChart.resize();
}
showBackground: true//显示柱状图柱子背景
2.2、echarts图表的优化
1、使用echarts图表后页面加载过慢:
2、将初始化变量提出挂载后钩子函数,var myChart = null;并声明为null
3、在每次组件销毁前,手动销毁myChart,并解绑事件
onBeforeUnmount(()=>{
myChart && myChart.clear();
if (myChart != null) {
myChart.dispose()
myChart = null;
}
window.removeEventListener("resize", resize);
})
4、//页面改变重绘图表
var resize = ()=> myChart.resize();
window.addEventListener('resize',resize)
3、json-server使用
大佬笔记入门篇:https://blog.csdn.net/zhou139856/article/details/125757250?spm=1001.2014.3001.5502
大佬笔记进阶篇:https://blog.csdn.net/zhou139856/article/details/125760197?spm=1001.2014.3001.5502
4、typeScript
4.1、安装
安装:npm install -g typescript 或 cnpm install -g typescript
查看版本:tsc-v
4.2、声明
1、基本数据类型约束:number、string、boolean、undefined、null
2、引用数据类型:
1)数组类型:
写法一:var arr1:Array<number> = [] //:Array数组,<number>数组里只能放数字类型
写法二:var arr2:number[] = [] //number数字类型,[]数组
2)对象类型:
写法一:var obj:{name:string,age:number}={name:'',age:1}//对象里必须有字符串类型的name,数字类型的age,且只能有这两个
//写法二:使用interface关键字定义对象类型
interface Person{
name:string,
age:name
}
var obj:Person = {name:string,age:name}//必须两个都有
//写法三:使用type关键字定义对象类型
type Good = {
name:string,
price:number,
isfree:boolean
}
var g:Good = {name:string,price:number,isfree:boolean}//三个都要有
3)interface和type区别
相同点:都可以用来定义对象类型(给对象类型起别名)
不同点:interface只能用于对象类型,type可以用于任何任何类型
4)void//无类型,用于函数返回值
5)any//任何类型,可以省略,不需要写
6)unknown//any的安全类型,了解
7)never//代表从不会出现的类型,了解
8)元组类型//赋值时必须遵循定义的顺序和类型,是一种严格的数组
9)enum枚举类型//从0开始,(别名)
enum sex{
male,//可以用0代替
female//可以用1代替
}
10)多种类型
3、函数:
function fn(num:string):string{}//返回值必须为string类型
function fn(num:string)void{}//没有返回值void
4、泛型:<类型>//使用时临时定义类型
3.3、使用
1、.ts文件//包含类型信息和可执行代码
用途:减少代码书写时可能出现的错误
编译:tsc -w index.ts //-w持久监听,自动刷新 index.ts文件名
2、.d.ts文件//只包含类型信息,不可编译
3、内置类型声明文件
4、///三斜线指令,引入库
5、vue文件中书写ts代码,需要在<script lang='ts'></script>标签上添加lang='ts'
5、项目打包发布
项目部署工具:ftp上传、scp2上传、Jenkins、k8s
Jenkins:
Build Now:自动git拉取,打包并部署
configure:查看配置
6、node.js
1、认识node
node是一个软件,是一个开源和跨平台的JavaScript运行时环境。
当JavaScript运行 在node软件上,js称为一门后端语言
当JavaScript运行在浏览器软件上,js称为一门前端语言
ECMAScript + 模块组成
2、安装node?
官网下载安装,安装完毕后,按win+r输入cmd打开终端,输入node -v 出现版本号则安装成功
nvm版本管理工具//node版本的监控
3、nodejs模块
1、分类:
内置模块:node自带的模块
自定义模块:自己定义的模块//遵循Commonjs规范
第三方模块:下载别人写的好的模块
2、自定义模块遵循Commonjs规范:
导出:
语法一:
module.exports.x = x;
语法二:
module.exports = {
a,
fn
};
语法三:
exports.a = a;
导入:require('路径')
3、导入第三方模块
语法一:npm install swiper === npm i swiper//安装第三方swiper包
npm install 模块名 --save
npm install 模块名 -S
//生产阶段需要的模块,package.json里存储在dependencies里,直接安装,默认dependencies里
语法二:npm install swiper --save--dev
//开发阶段需要的模块,package.json里存储在devDependencies里
语法三:有些包比较常用,想要只下载一次,多次使用
npm i 模块名 -global //下载到本地一个目录里
npm root -g //查看你下载到了哪个位置
删除命令 npm uninstall 模块名
4、包说明工具//package.json
语法一:npm init //手动生成一个包说明书
语法二:npm init --yes//自动生成一个包说明书
下载包,下载到了node_modules文件夹,package.json记录了你下载的包
作用:下载第三方包过多,会导致node_modules文件夹过大,可以把node_modules删除掉,package.json里会有记录,需要时候执行一下npm i命令即可下载所有依赖包
也可以安装rimraf第三方模块,用于删除node_modules更迅速
4、内置模块
1、fs模块
fs读取语法: const fs = require('fs');//引入
//异步读取
fs.readFile('读取的内容',[编码格式],function(err,data){});//读取哪个文件,什么格式,读取完调用回调函数,参数一错误,参数二代表读取的数据
//同步读取
let data = fs.readFileSyn('读取的内容',[编码格式]);
fs写入语法:
let fs = require('fs');//引入
fs.writeFile('写入的内容','写的内容',[编码格式],function(err,data){});
fs.writeFileSyn('写入的内容','写的内容',{encoding :[编码格式]});
2、path模块:
语法: const path = require('path');
1)join:path.join("a","b","c") //把三个拼接成一个路径
2)_dirname:当前文件所在路径
3、url模块:
语法: const url = require('url');
url.parse(路径) //解析路径,拿到协议、ip...
url.parse(路径,true) // 直接将返回结果query的属性变成对象形式
4、http模块:
语法: const http = require('http');
let app = http.createServer(function(req,res){//返回值为创建好的服务应用
res.write('响应给前端的内容')//可以多行,需要配合end结束请求
res.end('响应给前端的内容')//并结束请求
})
//req包含所有的请求信息 res包含所有的响应信息
app.listen(8989,()=>{})//监听端口号
5、常用模块
创建说明书 npm init -y
1.express//用于搭建服务,对http模块的封装
1)下载express模块 npm i express
2)搭建服务器 const app = express();
3)get和post请求
app.get(路径,(req,res)=>{
req.query//获取请求参数
})
app.post(路径,(req,res)=>{
//post请求需要添加以下两行代码
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
req.body//获取请求参数
})
2.nodemon
npm i -g nodemon//安装
nodemon 文件名//启动
3.nrm
npm i -g nrm//安装
nrm test//查询镜像速度
nrm use 镜像名//切换镜像
6、express路由
1、路由概念:端口号后面的就叫做路由
post和get必须请求路由相同才可
use则是开头相同即可
2、express.use('/public',express.static('public'))//以public开头的资源可以直接访问
6.1、express路由的分离
1.创建一张路由表
let userRouter = express.Router()//空表
2.向路由表中挂载路由
userRouter.post('/login',function(req,res){})
导出 路由表 module.exports = userRouter
3.当接口路由以/user访问时,会自动进入到这张路由表a
app.use('/user',require('./router/user'));//接口以/user访问时,会自动进入到路由表(./router/user)中找
6.2、例如
目录图
1、创建一个文件夹,并初始化说明文件 npm init -y
2、下载第三方模块express npm i express
3、server.js文件
const express = require('express');
const app = express();//创建服务器
//以'/user'开头的接口会响应'router/user'文件里,对对应路由处理
app.use('/user', require('./router/user'));
//监听端口
app.listen(6666, () => {
console.log('开启成功');
})
4、user.js文件
const express = require('express');
let userRouter = express.Router();//创建空表
userRouter.post('/login', (req, res) => {
res.send('登录接口');
})
userRouter.post('/register', (req, res) => {
res.send('注册接口');
})
//导出路由表
module.exports = userRouter;
7、中间件
概念:一个函数,有请求也有响应,继续向下走next
function(req,res,next){next();//继续向下}
1.应用级别中间件:应用级别的中间件(也称为全局中间件):通过app.use()或者app.get()或者app.post(),绑定到app实例上的中间件。
例如:添加一个记录访问时间的中间件
app.use(function (req, res, next) {
fs.writeFileSync('info.txt', new Date().toLocaleString() + '---\n', { flag: 'a', encoding: 'utf-8' });
next();
})
2.路由级别的中间件:加在某一个路由表上
例如:购物车一系列接口,访问需要判断是否携带token,如果在每个接口里都写判断,代码比较冗余,利用路由级别中间件先判断是否有token,有的话再向下执行具体接口,没有直接返回没带token,这样只用写一次。
3.请求级别的中间件:写在具体的请求对应的处理函数前面
8、mongodb数据库
8.1、安装mongodb
官网:https://www.mongodb.com/
下载地址:https://www.mongodb.com/download-center/community
安装成功后,创建一个文件,用于存放数据库文件
启动:在mongodb安装目录的bin文件夹路径里输入cmd打开终端,输入mongod --dbpath后面跟上自己创建的文件夹的路径
例如:C:\mongodb\bin mongod --dbpath c:\data\db
2.基本指令:
show dbs //查看非空的库
use 数据库名 //切换数据库或创建一个空的数据库
db //查看当前所在数据库
db.表名/集合名.insert(JSON格式数据) //创建表并添加内容
db.表名/集合名.drop() //删除表内容
...
8.2、mongoose第三方模块
1、概念:用于连接mongodb数据库
2、使用:
npm i mongoose //下载mongoose模块
//在npm里搜索mongoose模块,直接复制一下代码即可
const mongoose = require('mongoose') //导入mongoose模块
mongoose.connect('mongodb://localhost:27017/h52220').then(function(){
console.log("连接成功");
})
3、使用express连接数据库,并操作数据(CRUD增删改查)
3.1、express搭建服务
○ 下载引入express
○ express 创建服务器对象app
○ 写接口
○ 监听端口号开服务器
3.2 mongoose
○ 连接mongodb数据库
○ 定义Schema规则
○ 定义model:根据规则生成的一个表
○ 使用model进行数据增删改查操作
3.3、常用方法
//增
Model.insertMany([{key:value}])
//删
Model.deleteMany({条件},err=>{})
Model.deleteOne({条件},err=>{})
//查
Model.countDocuments({条件})
Model.find({条件},{可选字段返回:0/1},{skip:0,limit:10})
Model.findOne({条件},{可选字段返回:0/1})
//改
Model.updateMany({条件},{$set:{key:value}},res=>{})
Model.updateOne({条件},{$set:{key:value}},res=>{})
9、如何生成token
1、安装第三方的工具包 jsonwebtoken
2、生成token
let token jwt.sign({id:1,username:'zs'},'zhangsan',{expiresIn:'1h'})
3、解密token
jwt.verify(token,'zhangsan',(err,data)=>{
if(!err) console.log(data)//解密出的对象
})
10、mockjs的使用
10.1、模拟数据
1、安装:npm i mockjs
2、创建mock文件夹,并导入mockjs
3、借用Mock的api来模拟数据:
var res = Mock.mock({//生成数据
//"list|100":在list数组中,生成100个规定格式的对象
"list|100":[{
"id|+1":1, //"id|+1":1 实现id自增,且从1开始
name:'@cname', //@name英文名占位符,@cname中文名占位符
"age|0-120":20, //"age|0-120":20 表示生成0-120的数字
"sex|2":true, //"sex|2":true 表示随机布尔,2表示概率问题,true(2):false(1),二比一的概率,
}]
})
4、生成数据的规则:
1)"list|100" 配合数组使用,会根据数组元素生成100个元素
2)"list|+1" 如果属性的值是数字,会以数字为初始值,会自动加1(要配和1使用)
3)"age|20-50" 如果属性的值是数字,会根据数字的范围生成随机整数
4)"sex|1" 如果属性的值是布尔,会根据概率生成true或false
5)占位符:@cname 生成中文名字 @name 生成英文名字
@province 省 @city 市 @county 区
@county(true) 生成有联系的省市区 @email 邮箱
@image(100x100,@color) 生成占位图片并规定大小,设置随机颜色
@dataimage(100x100,@color) 生成一个随机的数据图片
10.2、模拟请求
//mockjs本身自带ajax请求拦截的能力,当请求地址和请求方式一致时,会自动拦截请求,处理请求,返回响应数据
//请求方式必须小写
1、Mock.mock('/api/list,get',(req,res)=>{
//req.query 获取请求参数
//return res
return {code:200,msg:"新增成功"};
})
11、UmiJS(react框架)
官网:umijs.org
特点:Umi是一个基于路由的构建的框架,集成了各种第三方库,不需要程序员自己安装
1、安装:
1)npm create @umijs/umi-app //下载安装,输入y同意安装
2)npm i //下载安装依赖包
3)npm start //启动项目
2、pages:存放页面
3、.umirc.ts:
路由配置表
//配置请求代理
devServer:{
proxy:{
"/api":{
target:"请求地址",
changeOrigin:true,
pathRewrite:{}
}
}
}
4、状态管理:
1)在src里创建一个models文件,一个文件即是一个模块
2)export default{
namespace:'userlist', //模块名称
state:{
管理的数据
},
reducers:{//定义同步方法,纯函数
user_add(state,action){//每一个方法都有一个state和action
//深拷贝
//处理逻辑
//返回新的state
}
},
effects:{//定义异步方法
}
}
3)同步action
import {useDispatch,useSelector} from 'umi'
var dispatch = useDispatch();
dispatch({type:模块名称/同步方法名,payload:参数})
例如:dispatch({type:userlist/user_add,payload:参数})
4)异步action
1)*request_userlist是一个Generator函数,用于处理异步逻辑,接收两个参数,第一个参数是个对象,包含了当前 action 的 payload 属性;第二个参数是一个对象,包含了 call、put 和 select 方法
2)其中 call 方法用于调用异步函数,put 方法用于触发同步 action,select 方法用于获取 state 中的数据。
3)yield call( user_list, payload ) 调用了一个异步函数 user_list,并将 payload 作为参数传入。
*request_userlist({ payload }, { call, put, select }) {
var res = yield call(user_list, payload);
yield put({ type: 'save_userlist', payload: res.data.data })// 触发同步action , 保存数据
}
12、linux
12.1、文件
1、文件作用:etc配置、lib库、sbin命令、usr用户安装的、bin用户安装的软件、dev蓝牙键盘等设备、home用户
.开头的文件默认是隐藏的
2、drwxr-xr-x 1 lj Administrators 0 May 16 09:17 apk
1)d表示目录,如果是文件则是 -
2)rwxr-xr-x表示该文件或目录的权限,分三组,每组三个字符,第一组为所有者权限,第二组所属组权限,第三组其他用户权限,r表示可读,w表示可写,x表示可执行,-表示没有权限
3)1 表示文件或目录的硬链接数
4)lj表示所有者用户名 //谁的文件
5)Administrators 表示文件或目录所属组名
6)0 表示文件或目录大小(字节为单位)
7)May 16 09:17 //最后修改时间
8)文件名
12.2、指令
1、pwd:打印当前路径(绝对路径)
2、clear:清屏
3、常识:
~:当前用户文件夹
/:根文件夹
4、cd / //切换到根文件夹
cd ~ //切换到当前用户文件夹
cd .. //切换到上一级文件夹
cd . //切换到当前文件夹
5、创建目录(文件夹):mkdir 目录名
6、rm:删除文件, rmdir删除目录
7、ls:列出目录或文件列表
-l 详细信息 //最左边有d代表文件夹
-a 列出所有文件(包括隐藏文件)
8、vi:打开并编辑文件
按i进入编辑模式,写内容
按esc并按: 进入命令模式
w保存
q退出 //要保存才能退出
wq保存并退出
q!强制退出 //可以不保存直接退出
wq!强制保存并退出
set nu //显示行号,临时的
dd //删除行
dw //删除一个单词(光标需要放在单词开头)
9、mv:移动文件或目录
10、touch:创建一个新的空文件
11、cat:将文件内容输出到终端
12、cp:复制文件或目录
13、grep:在文件中查找指定的字符串
14、find:查找文件或目录
15、tar:用于压缩和解压缩文件
1)tar -czvf archive.tar.gz file1 file2 //将file1、file2打包为一个名为archive.tar.gz的压缩文件
2)tar -xzvf archive.tar.gz //解压archive.tar.gz到当前目录
16、chmod:更改文件或目录的权限
17、chown:更改文件或目录的所有者
18、ps:显示当前运行的进程
19、top:查看系统资源占用情况
20、ssh:远程登录到另一台机器
21、scp:在本地和远程之间复制文件
22、ping:测试网络连接的状态
23、echo:用于将字符串或变量的值输出到终端上
echo "Hello World" > hello.txt //输出到文件
echo "Hello Again" >> hello.txt //追加到文件
24、less:逐页显示文件内容
25、date // 显示当前日期
26、history//显示最近敲的命令
history 10 //显示十条
13、数据库(mysql)
1、切换版本:指定端口号:mysql -uroot -P端口号 -p密码
见思维导图
14、mysql+vue3增删改查
14.1、后端
1、设计数据结构,建表
create dabatase demo;
CREATE TABLE goods(
good_id INT PRIMARY KEY AUTO_INCREMENT,
good_type VARCHAR(100),
good_name VARCHAR(100) NOT NULL,
good_num INT NOT NULL
);
2、连接mysql数据库
const mysql = require('mysql');
const conn = mysql.createConnection({
host: '127.0.0.1',
user: 'root',
password: '数据库密码',
port: '端口号',
database: '数据库名'
})
conn.connect((err) => {
if (err) throw err;
console.log("mysql 数据库连接成功!");
});
module.exports = conn;
3、创建一个服务,监听端口
const express = require('express');
const app = express();
//处理post参数
// app.use(express.json());
// app.use(express.urlencoded({ extended: false }));
const goodsRouter = require('./router/goods')
app.use('/api/goods', goodsRouter)
app.listen('8888', () => {
console.log("服务端运行在 http://localhost:8888");
})
4、编写接口逻辑
const express = require('express');
//创建express子路由
const goodsRouter = express.Router();
//连接数据库
const conn = require('../db/index.js')
//分页查询
goodsRouter.get('/list', (req, res) => {
let params = req.query;
let page_num = params.page_num || 1;
let page_size = params.page_size || 10;
// const sql = `select * from goods limit ${(page_num - 1) * page_size},${page_size}`
const sql = `select * from goods`;
conn.query(sql, (err, data) => {
if (err) {
res.send({ code: 400, msg: '查询失败' });
} else {
res.send({ code: 200, msg: '查询成功', data })
}
})
})
//添加商品
goodsRouter.get('/add', (req, res) => {
const params = req.query;
const goodsType = params.good_type;
const goodsName = params.good_name;
const goodsNum = params.good_num;
const sql = `insert into goods(good_type,good_name,good_num) values(?,?,?)`;
conn.query(sql, [goodsType, goodsName, goodsNum], (err, data) => {
if (err) {
res.send({ code: 400, msg: '新增商品失败' })
} {
res.send({ code: 200, msg: '新增商品成功', data });
}
})
})
//修改商品
goodsRouter.get('/update', (req, res) => {
const params = req.query;
const id = params.good_id;
const goodsType = params.good_type;
const goodsName = params.good_name;
const goodsNum = params.good_num;
const sql = `update goods set good_type=?,good_name=?,good_num=? where good_id=?`;
conn.query(sql, [goodsType, goodsName, goodsNum, id], (err, data) => {
if (err) {
res.send({ code: 400, msg: '修改失败' });
} else {
res.send({ code: 200, msg: '修改成功', data });
}
})
})
//删除商品
goodsRouter.get('/del', (req, res) => {
const params = req.query;
const id = params.good_id;
const sql = `delete from goods where good_id=?`;
conn.query(sql, [id], (err, data) => {
if (err) {
res.send({ code: 400, msg: '删除失败' });
} {
res.send({ code: 200, msg: '删除成功', data });
}
})
})
module.exports = goodsRouter;
14.2、前端
1、配置反向代理,将请求发送到后端对应接口
server: {
proxy: {
'/api': {
target: 'http://localhost:8888'
}
}
}
2、一个请求一个函数管理
3、编写页面,及逻辑,根据需求向后端发送请求
15、表格封装
1.1、封装
<script lang="ts">
import { ref } from "vue";
type columnsType = {
//配置项
label: string;
prop?: string;
slot_name?: string;
type?: "selection" | "index";
};
interface propsType {
tableData: Array<object>; //数据源
columns: columnsType[]; //配置项
}
export default {
emit: ["onSelect", "onSelectionChange", "onSelectAll"],
props: ["table-data", "columns"],
setup(props: propsType, { emit }: any) {
//单选
var select = (selection: any, row: any) => emit("onSelect", selection, row);
//全选
var selectAll = (selection: any) => emit("onSelectAll", selection);
//选择改变
var selectionChange = (selection: any) =>
emit("onSelectionChange", selection);
//数据源
const tableData = ref(props.tableData);
//配置项
const columns = ref(props.columns);
//导出
return {
tableData,
columns,
select,
selectionChange,
selectAll,
};
},
};
</script>
<template>
<el-table
:data="tableData"
style="width: 100%"
@select="select"
@selection-change="selectionChange"
@select-all="selectAll">
<!-- 遍历配置项 -->
<template v-for="item in columns" :key="item.label">
<!-- 如果配置项里有插槽属性,则渲染插槽 -->
<el-table-column v-if="item.slot_name" :label="item.label">
<!-- 通过scope拿到行数据,并传递出去 -->
<template #default="scope">
<slot :name="item.slot_name" :scope="scope"></slot>
</template>
</el-table-column>
<!-- 正常渲染 -->
<el-table-column
v-else
:type="item.type"
:prop="item.prop"
:label="item.label" />
</template>
</el-table>
</template>
1.2、使用
<script lang="ts" setup>
var data = [
{
name: "张三",
age: "18",
},
{
name: "李四",
age: "19",
},
{
name: "王五",
age: "20",
},
];
var columns = [
{
label: "序号",
type: "index",
},
{
label: "选项",
type: "selection",
},
{
label: "姓名",
prop: "name",
},
{
label: "年龄",
prop: "age",
},
{
label: "按钮",
slot_name: "btn",
},
];
//点击按钮
var handleBtn = (row: any) => {
console.log(row);
};
//单选
var select = (selection: any, row: any) => {
console.log(selection, row, "单选");
};
//全选
var selectAll = (selection: any) => {
console.log(selection, "全选");
};
//选项值改变
var selectionChange = (selection: any) => {
console.log(selection, "选项值改变");
};
</script>
<template>
<MyTable
:table-data="data"
:columns="columns"
@onSelect="select"
@onSelectionChange="selectionChange"
@onSelectAll="selectAll">
<template #index="{ scope }">
<div>{{ scope.$index + 1 }}</div>
</template>
<template #btn="{ scope }">
<button @click="handleBtn(scope.row)">按钮</button>
</template>
</MyTable>
</template>
1.3、思路
1、将Table组件通用的js逻辑,以及一些通用的样式,封装在组件内部,实现逻辑和样式的复用,对外暴露一些属性,把数据和列配置传入组件内部,
在外部可以通过列配置可以对表格列进行类型、插槽、表头、数据进行配置,
并向外暴露了单选,多选,选项改变三个事件
16、文件上传
16.1、前端逻辑
1、<input type="file" onChange={changeFile}/> //创建一个file文件上传,并绑定一个值改变事件
var [fileDate,setFileDate] = useState(null);
//点击上传之后,值改变,后赋值给fileDate
var changeFile = (e)=>{
setFileDate(e.target.files[0])
}
//在点击提交后,创建一个formData表单对象
const formData = new FormData();
//通过append配置名,及数据
formData.append("file", fileDate);
//向后端发送
axios.post('http://localhost:8888/api/user/file',formData,{
headers:{
'Content-Type': 'multipart/form-data'
}
}).then((res=>{
console.log(res);
})).catch(error=>{
console.log(error);
})
16.2、后端逻辑(仅供参考)
const upload = multer({ dest: './src/db/' }); // 文件上传到uploads目录下
router.post('api/user/file', upload.single("file"), (req, res) => {
try {
// 获取文件名和文件类型
const { originalname } = req.file;
// 生成唯一的文件名,我通过的是时间戳+文件名
const filename = `${Date.now()}-${originalname}`;
// 文件保存路径
const filePath = path.join(__dirname, '../db/', filename);
//写入文件
fs.writeFile(filePath, req.file.buffer);
res.send('文件上传成功');
} catch {
res.status(500).send('Sever error')
}
});