前端开发常用

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、undefinednull
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}//三个都要有

	3interface和type区别
		相同点:都可以用来定义对象类型(给对象类型起别名)
		不同点:interface只能用于对象类型,type可以用于任何任何类型
	4void//无类型,用于函数返回值
	5)any//任何类型,可以省略,不需要写
	6)unknown//any的安全类型,了解
	7)never//代表从不会出现的类型,了解
	8)元组类型//赋值时必须遵循定义的顺序和类型,是一种严格的数组
	9enum枚举类型//从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();
	3get和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、例如

​ 目录图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uZdT9Uof-1683697329988)(E:\web\course\JavaScript\笔记\assets\1678164894048.png)]

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、中间件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MKy2GUwn-1683697329988)(E:\web\course\JavaScript\笔记\assets\1678172944841.png)]

概念:一个函数,有请求也有响应,继续向下走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"  如果属性的值是布尔,会根据概率生成truefalse
	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文件,一个文件即是一个模块
	2export 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 中的数据。
          3yield 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表示可执行,-表示没有权限
	31 表示文件或目录的硬链接数
	4)lj表示所有者用户名 //谁的文件
	5)Administrators 表示文件或目录所属组名
	60 表示文件或目录大小(字节为单位)
	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')
    }
});
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值