前言

现在前端多是Vue.js+webpack,也是多亏了于此,黑盒才能有这么多的未授权可以挖。

好久没写博客了,最近搞毕设想要搞个前端,不然光脚本实在交不了差,想到之前有简单了解vue,正好趁着这个机会把之前的这篇博客好好补补,在这里还是希望毕业以后博客还能继续写下去的

常用命令

在 JavaScript 开发中,我们通常会依赖于很多js第三方库和框架,比如 Vue.js、Axios、Vue Router 等。通过使用 npm,我们可以轻松地管理这些依赖

1
2
3
4
5
6
7
8
# 安装依赖,创建 node_modules文件夹
npm install
# 建议不要直接使用 cnpm 安装依赖,会有各种诡异的 bug。可以通过如下操作解决 npm 下载速度慢的问题
npm install --registry=https://registry.npmmirror.com
# 启动服务(自定义脚本,在 package.json文件的 scripts 部分有相应的内容)
npm run serve
#生成 dist目录,用于生产环境的部署
npm run build

npm经常出现必须用特定版本才能下载依赖,我们可以使用nvm来管理npm版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#查看已经安装的node版本
nvm ls
#查看可以安装的node版本
nvm ls available
#安装指定版本
nvm install 版本号
#切换到指定版本
nvm use 版本号
#显示当前版本
nvm current
#卸载指定版本
nvm uninstall 版本号
#查看nvm版本
nvm version

vue项目目录结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
1、build:构建脚本目录
1)build.js ==> 生产环境构建脚本;
2)check-versions.js ==> 检查npm,node.js版本;
3)utils.js ==> 构建相关工具方法;
4)vue-loader.conf.js ==> 配置了css加载器以及编译css之后自动添加前缀;
5)webpack.base.conf.js ==> webpack基本配置;
6)webpack.dev.conf.js ==> webpack开发环境配置;
7)webpack.prod.conf.js ==> webpack生产环境配置;
2、public(static):静态资源目录,如HTML文件、图标等。不会被webpack构建
3、node_modules:npm或yarn安装的库和框架都存放在这个文件夹
4、src:这里是我们要开发的目录,基本上要做的事情都在这个目录里。里面包含了几个目录及文件:
1)assets:资源目录,放置一些图片或者公共js、公共css。这里的资源会被webpack构建;
2)components:存放Vue组件文件,通常是可复用的UI元素;
3)views(pages):存放路由页面组件,通常每个路由对应一个页面
3)router:配置应用的路由;
4)App.vue:根组件;
5)main.js:入口js文件;

5、config:项目配置(vue3没有该目录变成了vue.config.js文件)
1)dev.env.js ==> 开发环境变量;
2)index.js ==> 项目配置文件;
3)prod.env.js ==> 生产环境变量;
6、index.html:首页入口文件,可以添加一些 meta 信息等
7、package.json:npm包配置文件,定义了项目的npm脚本,依赖包等信息
8. package-lock.json(yarn.lock):package.json 里是一个范围(如^4.17.0),package-lock.json 中记录了每个依赖库的确切版本号
9. .env: 包含应用的环境变量

vue项目运行流程分析

一般流程是

  1. src/main.js 创建Vue实例引入其他必要的资源
  2. 请求来临时根据 src/router/index.js中的匹配规则,匹配url对应的src/views/ 中的路由页面
  3. 路由页面再调用src/Components/ 中的公共组件,嵌套在总组件 src/App.vue上,最后和src/assets/ 中的静态资源一起呈现在 public/index.html

这里的组件类似于html+js,可以进行一部分的逻辑操作

现在借用Ruoyi来看一下
抓包访问/system/user,发现会自动触发GET /dev-api/system/user/list?pageNum=1&pageSize=10返回用户信息
QQ20241008-014116

前端断点调试(因为我开了sourcemap,配合插件就能调试了)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
//ruoyi-ui/src/views/system/user/index.vue
<script>
import { listUser, getUser, delUser, addUser, updateUser, resetUserPwd, changeUserStatus } from "@/api/system/user";
.............................
created() {
this.getList();
this.getTreeselect();
this.getConfigKey("sys.user.initPassword").then(response => {
this.initPassword = response.msg;
});
},
methods: {
/** 查询用户列表 */
getList() {
this.loading = true;
listUser(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
this.userList = response.rows;
this.total = response.total;
this.loading = false;
}
);
},
..............................
//ruoyi-ui/src/api/system/user.js
import request from '@/utils/request'
export function listUser(query) {
return request({
url: '/system/user/list',
method: 'get',
params: query
})
}


//赋值完成后,回到ruoyi-ui/src/views/system/user/index.vue看看是怎么渲染的
//:data="userList" 绑定了表格的数据源,所以说vue的表单一般是没有xss漏洞的
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" align="center" />
<el-table-column label="用户编号" align="center" key="userId" prop="userId" v-if="columns[0].visible" />
<el-table-column label="用户名称" align="center" key="userName" prop="userName" v-if="columns[1].visible" :show-overflow-tooltip="true" />
...................
data() {
return {
....................
total: 0,
// 用户表格数据
userList: null,
....................

vue基础语法

导包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 导入子组件
import HelloWorld from './components/HelloWorld.vue'; //相对路径
import Home from '@/components/Home.vue'; //从 src 目录开始的绝对路径

// 导入第三方库
import ElementUI from 'element-ui'
Vue.use(ElementUI)

import './assets/styles.css'; // 导入全局样式
import './plugins/element.js'//引入element-ui组件到 Vue 实例
import router from './router' //同import router from './router/index.js',这里使用router对象

//被调用js文件
export default router //导出 router 对象或函数

路由

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import Vue from 'vue'
import VueRouter from 'vue-router'
import Login from '../components/Login.vue'
import Home from '../components/Home.vue'
import Welcome from '../components/Welcome.vue'
Vue.use(VueRouter)

const routes = [
{
path: '/',
redirect: '/login'
},
{
path: '/login',
component: Login
},
{
path: '/home',
component: Home,
redirect: '/welcome',
children: [{ path: '/welcome', component: Welcome }]//子路由
}
]

const router = new VueRouter({//创建路由对象
routes
})
export default router

编写vue模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
//实例1-文本插入
<template>
<div class="hello">
<!-- 相当于v-text纯文本 -->
<div >{{test}}</div>
<!-- v-html指令,可以将HTML字符串渲染为真正的DOM元素 -->
<div v-html="safeHTML"></div>
</div>
</template>

<script>
import DOMPurify from 'dompurify';
const hello="adf"
export default {
data () {
return {
test:hello,//注意js中的xss
safeHTML: DOMPurify.sanitize('<h1>This is safe</h1>') //DOMPurify.sanitize 会自动移除任何潜在的恶意代码,如 <script> 标签,从而保护应用免受 XSS 攻击
}
},
}
</script>

//实例2-留言板
<template>
<div class="app">
<h1>留言板</h1>
<!-- 事件绑定, v-on缩写为@,.prevent - 阻止默认事件-->
<form @submit.prevent="submitMessage">
<textarea v-model="newMessage"></textarea><!-- 文本区域,v-model双向绑定到 newMessage 数据属性,也就是说我们更改留言板的内容可以影响scrpipt中的值 -->
<button type="submit">提交</button>
</form>
<div v-for="(message, index) in safeMessages" :key="index" v-html="message"></div><!-- 动态渲染留言内容 -->
</div>
<!-- 属性绑定, v-bind 缩写为 :-->
<p><a :href="url">百度</a></p>
</template>

<script>
import DOMPurify from 'dompurify';

export default {
data() {
return {
url: 'https://www.baidu.com'
newMessage: '',
messages: []
};
},
computed: { // 计算属性用于根据data数据的变化动态计算衍生出来的属性值,支持动态变化
safeMessages() {
return this.messages.map(msg => DOMPurify.sanitize(msg));
}
},
methods: {
submitMessage() {
const sanitizedMessage = DOMPurify.sanitize(this.newMessage);
this.messages.push(sanitizedMessage);
this.newMessage = '';
}
}
};
//其他可能引起xss的点
this.$alert(response.msg, "导入结果", { dangerouslyUseHTMLString: true });//支持html的弹窗
</script>

与后端交互

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 在 main.js 中配置 axios(可选)
import axios from 'axios';
import Vue from 'vue';

// 设置 Axios 的基础 URL(如果你的 API 都是来自同一个服务器)
axios.defaults.baseURL = 'https://api.example.com';

Vue.prototype.$http = axios; // 将 axios 添加到 Vue 原型中,方便在组件中使用
methods: {
login() {
const { data: resp } = await this.$http.get('/auth?username=' + this.loginForm.username + '&password=' + this.loginForm.password)
if (resp.code !== 200) {
return this.$message.error('登录失败')
} else {
this.$message.success('登录成功')
window.sessionStorage.setItem('token', resp.data.token)
this.$router.push('/home')
}
}}

vue常用包

Element UI

Element UI 是一款基于 Vue.js 的桌面端组件库,提供了一系列高质量的 UI 组件,旨在帮助开发者更快速地构建现代化的、响应式的网页应用。它的组件库涵盖了各种常见的 UI 元素,如按钮、输入框、表格、对话框等,所有组件都遵循 Material Design 和一致的设计规范。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
//1. 实例1-登录框
<!-- :model="loginForm":绑定一个 Vue 数据对象 loginForm,该对象用于保存表单中所有字段的值
:rules="loginRules":绑定表单的验证规则
ref="loginFormRef":通过 this.$refs.loginFormRef获取该表单的引用,用于在代码中操作表单,例如手动提交或重置-->
<el-form :model="loginForm" :rules="loginRules" ref="loginFormRef" label-width="0px">
<!-- 用户名 -->
<el-form-item prop="username"><!--通过prop与loginForm 对象和loginRules对象中的 username 属性相关联-->
<el-input v-model="loginForm.username" prefix-icon="iconfont icon-user"></el-input>
</el-form-item>
<!-- 密码 -->
<el-form-item prop="password">
<el-input v-model="loginForm.password" prefix-icon="iconfont icon-3702mima" type="password">
<i slot="suffix" @click="showPwd"></i>
</el-input>
</el-form-item>
<!-- 按钮 -->
<el-form-item class="btns">
<el-button type="primary" @click="login">登录</el-button>
<el-button type="info" @click="resetLoginForm">重置</el-button>
</el-form-item>
</el-form>
<script>
export default {
data() {
return {
// 登陆表单数据对象
loginForm: {
username: '',
password: ''
},
loginFormRules: {
username: [
//required: true:这个规则表示该字段是必填的。也就是说,用户必须在该字段输入一些内容,不能为空。如果用户未输入内容,表单将无法通过验证。
//message:这是当该字段未填写时,显示给用户的错误提示信息。
//trigger: 'blur':blur 是 Vue 表单验证中常见的触发事件之一。它意味着当用户离开输入框时,会自动验证输入内容。
//min: , max:为长度限制
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ min: 3, max: 10, message: '长度在 3 到 10 个字符', trigger: 'blur' }
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 3, max: 16, message: '长度在 3 到 16 个字符', trigger: 'blur' }
],
pwdType: 'password'
}
}
}
}
</script>
//2.数据表
<el-card>
<!-- 搜索 添加区域 -->
<el-row :gutter="30">
<el-col :span="3">
<!-- placeholder 是输入框的占位符文本,当输入框为空时,显示的提示文字为 "protocol"。
@clear 是 Vue 的事件监听语法,监听清除事件
@keyup.enter.native 表示按下 Enter 键时,getIpListSingle 方法会被触发。
-->
<el-input
placeholder="protocol"
class="input-with-select"
v-model="queryInfo.protocol"
clearable
@clear="getIpList"
@keyup.enter.native="getIpListSingle"
></el-input>
</el-col>
</el-row>
<!-- 表 -->
<el-table :data="iplist" border stripe>
<el-table-column label="protocol" prop="protocol" width="120px" ></el-table-column>
</el-table>
</el-card>
<script>
import qs from "qs";

export default {
data() {
return {
// 参数列表
queryInfo: {
ip: "",
title: "",
port: "",
pagenum: 1,
// 当前每页显示多少条数据
pagesize: 10
},
iplist: []
}
}
}

这里就列举几个重要的,详细的规则直接在这里抄就行了
https://element.eleme.cn/#/zh-CN/component/button

ECharts

ECharts 是一个非常强大的数据可视化工具,支持多种图表类型和交互功能,可以帮助开发者轻松创建交互性强、表现丰富的图表。通过简单的配置,你可以根据需要绘制出漂亮且富有表现力的图表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//1.基本格式
<el-col :xs="12" :sm="12" :lg="8">
<div id="main" style="width: 500px;height:300px;"></div>
</el-col>
<script>
// 初始化 ECharts 实例
var myChart = echarts.init(document.getElementById('main'));
// 设置图表的配置项和数据
var option = {
xAxis: {//x轴
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {},//y轴
series: [
{
type: 'bar',//图表类型
data: [23, 24, 18, 25, 27, 28, 25] //默认数据
}
]
};
// 使用刚指定的配置项和数据显示图表
myChart.setOption(option);
</script>

vue打包

webpack

Webpack 是一个现代 JavaScript 应用程序的模块打包工具,它将应用程序的各种资源(如 JavaScript、CSS、图片等)打包成一个或多个文件,以优化加载性能,打包后的代码晦涩难懂

vue.config.js中配置webpack

1
2
3
4
5
6
7
8
9
10
11
12
  // 如果你不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建,如果为true会造成webpack源码泄露
productionSourceMap: false,

configureWebpack: {
// 以便在webpack的名称字段中提供应用程序的标题,以便可以在index.html中访问它以注入正确的标题。
name: name,
resolve: {
alias: {
"@": resolve("src"),
},
},
},