Vue3

Vue3知识点汇总-只记录我所不熟练的-来源黑马笔记以及本人补充

一、一些小小问题

1、npm create vite@latest 和 npm init vue@latest 构建的项目有什么区别?

npm create vite@latestnpm init vue@latest 是两个不同的命令,用于创建不同类型的项目,具体区别如下:

  1. npm create vite@latest

  • 用途: 这个命令用来创建一个新的 Vite 项目。Vite 是一个现代的前端构建工具,支持快速的开发和构建流程。

  • 项目类型: 创建的项目可以是任何使用 Vite 的框架,比如 Vue、React、Svelte 等。

  • 灵活性: 运行这个命令后,你可以选择不同的模板,比如 Vue、React、Vanilla JavaScript 等。

  1. npm init vue@latest

  • 用途: 这个命令专门用于创建一个新的 Vue 3 项目。它会自动设置一个基于 Vue 的开发环境。

  • 项目类型: 仅针对 Vue 项目,通常会包含一些 Vue 特定的配置和最佳实践。

  • 配置: 在创建 Vue 项目时,会提供一些默认的设置,比如 Vue Router、Vuex 等。

总结

  • 如果你想创建一个灵活的项目,可以选择不同的框架,使用 npm create vite@latest

  • 如果你专注于 Vue 开发,使用 npm init vue@latest 会更合适,因为它为 Vue 项目提供了专门的配置和支持。

2、let和var变量有什么区别

在 Vue.js 中,letvar 是 JavaScript 中用于声明变量的两种关键字。它们的区别不仅仅体现在 Vue 的使用中,而是 JavaScript 本身的特性。下面是它们的主要区别:

  1. 作用域 (Scope)

  • var

    • 函数作用域var 声明的变量具有函数作用域,即它只在函数内部可访问。如果在函数外部使用 var 声明变量,则该变量为全局变量。
    • 提升 (Hoisting)var 声明的变量会被提升到函数或全局作用域的顶部,即使在声明之前使用该变量,JavaScript 引擎也会先将其初始化为 undefined
  • let

    • 块级作用域let 声明的变量有块级作用域,即它只在其被声明的代码块(如 iffor 等)内有效,外部无法访问。
    • 没有提升let 声明的变量在声明之前不可访问,访问会导致 ReferenceError(称为“暂时性死区”)。

二、Element-plus的使用

其实真正要使用的时候,去官网查文档即可

1、消息提示的使用

安装完element-plus后在需要的页面导入

1
import { ElMessage } from 'element-plus'

在需要的地方使用即可

1
ElMessage.success('服务异常');

1

2、Element-plus中的表单校验规则

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
<!-- 注册表单 -->
<el-form ref="form" size="large" autocomplete="off" v-if="isRegister" :model="registerData" :rules="rules">
<el-form-item>
<h1>注册</h1>
</el-form-item>
<el-form-item prop="username">
<el-input :prefix-icon="User" placeholder="请输入用户名" v-model="registerData.username" ></el-input>
</el-form-item>
<el-form-item prop="password">
<el-input :prefix-icon="Lock" type="password" placeholder="请输入密码"
v-model="registerData.password"></el-input>
</el-form-item>
<el-form-item prop="rePassword">
<el-input :prefix-icon="Lock" type="password" placeholder="请输入再次密码"
v-model="registerData.rePassword"></el-input>
</el-form-item>
<!-- 注册按钮 -->
<el-form-item>
<el-button class="button" type="primary" auto-insert-space v-on:click="register">
注册
</el-button>
</el-form-item>
<el-form-item class="flex">
<el-link type="info" :underline="false" @click="isRegister = false;clearRegisterDate()">
← 返回
</el-link>
</el-form-item>
</el-form>


1
2
3
4
5
6
7
8
9
10
11
12
13
14
//具体规则
const rules = {
username: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ min: 5, max: 16, message: '长度为5~16为非空字符', trigger: 'blur' }
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 5, max: 16, message: '长度为5~16为非空字符', trigger: 'blur' }
],
rePassword: [
{validator: checkRePassword,trigger:'blur'}
]
}

3、添加:underline=“false”可以使得注册框没有下划线

1
2
3
<el-link type="info" :underline="false" @click="isRegister = true;clearRegisterDate()">
注册 →
</el-link>

4、菜单项设置点击后跳转的路由路径

el-menu-item 标签的index属性可以设置点击后的路由路径

1
2
3
4
5
6
<el-menu-item index="/article/category">
<el-icon>
<Management />
</el-icon>
<span>文章分类</span>
</el-menu-item>

5、使用中文语言包

若ElementPlus中有些组件是非中文的可以在main.js中加上

1
2
3
import locale from 'element-plus/dist/locale/zh-cn.js'

app.use(ElementPlus,{locale})

6、分页数据变化自动调用函数

@size-change=“onSizeChange”

1
2
3
<el-pagination v-model:current-page="pageNum" v-model:page-size="pageSize" :page-sizes="[3, 5, 10, 15]"
layout="jumper, total, sizes, prev, pager, next" background :total="total" @size-change="onSizeChange"
@current-change="onCurrentChange" style="margin-top: 20px; justify-content: flex-end" />
1
2
3
4
5
//当每页条数发生了变化,调用此函数
const onSizeChange = (size) => {
pageSize.value = size
getArticles()
}

7、抽屉

给个样式图,要用的时候直接看官方文档

2

8、ElementPlus自带上传组件

  1. 这种使用方法由于不经过request.js 所以要在请求地址上加/api,请求代理才能拦截到这个请求

  2. 要自定义携带请求头

  3. 回调逻辑重要

使用这个以后文件上传不需要自己实现代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!-- 
auto-upload:设置是否自动上传
action:服务器接口路径
name:设置上传文件字段名
headers:上传请求头
on-success:上传成功的回调函数
-->
<el-upload class="avatar-uploader"
:auto-upload="true"
:show-file-list="false"
action="/api/upload"
name="file"
:headers="{ 'Authorization': tokenStore.token }" :on-success="uploadSuccess">
<img v-if="articleModel.coverImg" :src="articleModel.coverImg" class="avatar" />
<el-icon v-else class="avatar-uploader-icon">
<Plus />
</el-icon>
</el-upload>

9、富文本编辑器插件

文章内容需要使用到富文本编辑器,这里咱们使用一个开源的富文本编辑器 Quill

官网地址: https://vueup.github.io/vue-quill/

安装:

1
npm install @vueup/vue-quill@latest --save

导入组件和样式:

1
2
import { QuillEditor } from '@vueup/vue-quill'
import '@vueup/vue-quill/dist/vue-quill.snow.css'

页面长使用quill组件:

1
2
3
4
5
6
7
<quill-editor
theme="snow"
v-model:content="articleModel.content"
contentType="html"
>
</quill-editor>

样式美化:

1
2
3
4
5
6
.editor {
width: 100%;
:deep(.ql-editor) {
min-height: 200px;
}
}

10、el-dropdown

在el-dropdown-item标签上添加command属性,属性值和路由表中/user/xxx保持一致

1
2
3
4
5
6
<el-dropdown-menu>
<el-dropdown-item command="info" :icon="User">基本资料</el-dropdown-item>
<el-dropdown-item command="avatar" :icon="Crop">更换头像</el-dropdown-item>
<el-dropdown-item command="password" :icon="EditPen">重置密码</el-dropdown-item>
<el-dropdown-item command="logout" :icon="SwitchButton">退出登录</el-dropdown-item>
</el-dropdown-menu>

在el-dropdown标签上绑定command事件,当有条目被点击后,会触发这个事件

1
<el-dropdown placement="bottom-end" @command="handleCommand">

提供handleCommand函数,参数为点击条目的command属性值

1
2
3
4
5
6
7
8
9
10
11
12
//dropDown条目被点击后,回调的函数
import {useRouter} from 'vue-router'
const router = useRouter()
const handleCommand = (command)=>{
if(command==='logout'){
//退出登录
alert('退出登录')
}else{
//路由
router.push('/user/'+command)
}
}

退出登录实现:

仅供参考

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
import {ElMessage,ElMessageBox} from 'element-plus'
import { useTokenStore } from '@/stores/token.js'
const tokenStore = useTokenStore()
const handleCommand = (command) => {
if (command === 'logout') {
//退出登录
ElMessageBox.confirm(
'你确认退出登录码?',
'温馨提示',
{
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(async () => {
//用户点击了确认
//清空pinia中的token和个人信息
userInfoStore.info={}
tokenStore.token=''
//跳转到登录页
router.push('/login')
})
.catch(() => {
//用户点击了取消
ElMessage({
type: 'info',
message: '取消退出',
})
})
} else {
//路由
router.push('/user/' + command)
}
}

三、Vue3的一些用法

1、vue配置代理

为了解决跨域问题我们在vue项目以dev启动时配置代理

request.js中配置统一前缀 /api

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//导入axios
import axios from 'axios';
//公共前缀
const baseURL = '/api';
const instance = axios.create({baseURL})
//添加响应拦截器
instance.interceptors.response.use(
result=>{
return result.data;
},
err=>{
alert('服务异常');
return Promise.reject(err);//异步的状态转化成失败的状态
}
)
export default instance;

vie.config.js中配置代理

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
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))
}
},
//配置代理
server:{
proxy:{
'/api':{//指的是获取路径中包含了api的请求
target:'http://localhost:8080',//后台服务所在的源
changeOrange:true,
rewrite:(path)=>path.replace(/^\/api/,'')// /api 替换为空字符串
}
}
}
})

2、这样可以迅速处理参数

1
2
3
4
const params = new URLSearchParams();
for(let key in loginData){
params.append(key,loginData[key]);
}

3、axios请求可以加上async以及await等待请求响应

1
2
3
4
5
6
7
8
9
//用于登录的事件函数
const login = async () => {
let result = await loginService(registerData.value)
if(result.code==0){
alert('登录成功!')
}else{
alert('登录失败!')
}
}

4、优化axios响应

可以自己写一个request.js文件。

通过后端返回响应码的形式来发送前端提示信息,添加响应拦截器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//添加响应拦截器
instance.interceptors.response.use(
result => {
//如果业务状态码为0,代表本次操作成功
if (result.data.code == 0) {
return result.data;
}
//代码走到这里,代表业务状态码不是0,本次操作失败
alert(result.data.message || '服务异常');
return Promise.reject(result.data);//异步的状态转化成失败的状态
},
err => {
alert('服务异常');
return Promise.reject(err);//异步的状态转化成失败的状态
}
)

Promise.reject 是 JavaScript 中的一个静态方法,它用于返回一个被拒绝的 Promise。在你的代码中,使用 Promise.reject 的目的是为了将请求的失败状态传递出去,让调用这个请求的地方能够处理这些错误。

5、路由

这里不讲太多,就补充一个子路由的写法以防忘记

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//定义路由关系
const routes = [
{ path: '/login', component: LoginVue },
{
path: '/',
component: LayoutVue,
//重定向
redirect: '/article/manage',
//子路由
children: [
{ path: '/article/category', component: ArticleCategoryVue },
{ path: '/article/manage', component: ArticleManageVue },
{ path: '/user/info', component: UserInfoVue },
{ path: '/user/avatar', component: UserAvatarVUe },
{ path: '/user/password', component: UserResetPasswordVue },
]
}
]

6、利用pinia使用axios请求拦截器

当用户从网页登录系统后,需要频繁和后端接口进行交互。我们可以添加请求拦截器的方式,统一将token添加到请求头中。

在 src/util/request.js中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//添加请求拦截器
instance.interceptors.request.use(
//请求前的回调
config =>{
//添加token
const tokenStore = useTokenStore();
if(tokenStore.token){
config.headers.Authorization = tokenStore.token;
}
return config;
},
//请求错误的回调
err =>{
Promise.reject(err);
}
)

7、axios会自动根据参数类型调用相关方法

Axios 会根据你传递的数据类型自动决定如何处理请求的参数。如果你传递的是一个普通的 JavaScript 对象(如 { key: value }),它会将这个对象作为请求体(body)发送(通常是 JSON 格式)。如果你传递的是 URLSearchParams 对象,它会自动将它作为查询参数(URL parameters)处理。

  1. 传递普通 JavaScript 对象(请求体)

如果你传递的是一个普通的 JavaScript 对象,Axios 会自动将它转换为 请求体,并且默认将其作为 JSON 格式发送。

1
2
3
4
5
6
7
8
9
10
11
12
13
javascriptconst userInfoData = {
username: 'newUsername',
email: 'newemail@example.com',
avatarUrl: 'https://example.com/avatar.png'
};

axios.put('/user/update', userInfoData)
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error(error);
});
  • 请求头Content-Type: application/json

  • 请求体{ "username": "newUsername", "email": "newemail@example.com", "avatarUrl": "https://example.com/avatar.png" }

在这种情况下,Axios 会自动将 userInfoData 对象转化为 JSON 格式,放入请求的 请求体(body)。

  1. 传递 URLSearchParams 对象(查询字符串)

如果你传递的是一个 URLSearchParams 对象,Axios 会将它作为查询字符串(URL 参数)进行处理。它会自动将 params 放入请求的 URL 中。

1
2
3
4
5
6
7
8
9
10
11
javascriptconst params = new URLSearchParams();
params.append('avatarUrl', 'https://example.com/avatar.png');
params.append('username', 'newUsername');

axios.put('/user/update', params)
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error(error);
});
  • 请求头Content-Type: application/x-www-form-urlencodedAxios 会自动设置这个 Content-Type)

  • URL/user/update?avatarUrl=https%3A%2F%2Fexample.com%2Favatar.png&username=newUsername

在这种情况下,Axios 会自动将 params 对象编码为查询字符串,并附加到 URL 后面。

  1. 混合参数:传递 params 作为 URL 参数 + 请求体(例如 POST/PUT 请求)

你还可以将 params 作为 URL 参数传递,同时传递一个请求体。Axios 会将 URL 参数放在 URL 中,将请求体中的数据放入请求体。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
javascriptconst userInfoData = {
username: 'newUsername',
email: 'newemail@example.com',
};

const params = new URLSearchParams();
params.append('avatarUrl', 'https://example.com/avatar.png');

axios.put('/user/update?' + params.toString(), userInfoData)
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error(error);
});
  • URL/user/update?avatarUrl=https%3A%2F%2Fexample.com%2Favatar.png

  • 请求体{ "username": "newUsername", "email": "newemail@example.com" }

  • 请求头Content-Type: application/json

四、Pinia状态管理库

Pinia 是 Vue 3 的一个状态管理库,旨在提供更简洁、更易用的状态管理、共享解决方案。

1、安装

1
npm install pinia

2、使用pinia

在main.js中写

1
2
3
4
import { createPinia } from 'pinia'

const pinia = createPinia()
app.use(pinia)

3、定义store

在目录下自定义文件名: *.js

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
import{defineStore} from 'pinia'
import {ref} from 'vue'
/*
第一个参数:名字:唯一性
第二个参数:函数,函数的内部可以定义状态的所有内容
*/

export const useTokenStore = defineStore('token',()=>{
//定义状态的内容

//定义一个响应式变量
const token = ref('')

//定义一个函数
const setToken = (newToken)=>{
token.value = newToken;
}

const removeToken = ()=>{
token.value = "";
}


return {
token,setToken,removeToken
}

},
{
persist:true
})

4、使用store

在需要使用的地方导入刚刚写的js,然后我们直接调用对应的方法即可保存状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//导入token状态
import { useTokenStore } from '@/stores/token.js'

//调用useTokenStore得到状态
const tokenStore = useTokenStore();

//用于登录的事件函数
const login = async () => {
let result = await loginService(registerData.value)
//保存token
tokenStore.setToken(result.data)

ElMessage.success('登录成功!')
router.push('/')
}

在需要的时候就可以将保存的状态取出,发送给后端

在article.js中导入@/stores/token.js, 从pinia中获取到存储的token,在发起查询文章分类列表的时候把token通过请求头的形式携带给服务器

1
2
3
4
5
6
7
8
9
10
11
//导入@/stores/token.js
import { useTokenStore } from '../stores/token'


//文章分类列表查询
export const articleCategoryListService = () => {
//获取token状态
const tokenStore = useTokenStore()
//通过请求头Authorization携带token
return request.get('/category', { headers: { 'Authorization': tokenStore.token } })
}

5、按需使用的Pinia持久化插件

默认情况下,由于pinia是内存存储,当你刷新页面的时候pinia中的数据会丢失,可以借助于persist插件解决这个问题,persist插件支持将pinia中的数据持久化到sessionStorage和localStorage中

5.1 安装persist插件
1
npm install pinia-persistedstate-plugin
5.2 导入persist插件

在main.js中写

1
2
3
4
5
6
7
8
9
10
11
12
//导入pinia
import {createPinia} from 'pinia'

//导入pinia的持久化插件
import { createPersistedState } from 'pinia-persistedstate-plugin'

//创建实例分别挂载并使用
const pinia = createPinia();
const persist = createPersistedState();
pinia.use(persist);

app.use(pinia);

五、Apache ECharts

1、介绍

Apache ECharts 是一款基于 Javascript 的数据可视化图表库,提供直观,生动,可交互,可个性化定制的数据可视化图表。

官网地址:https://echarts.apache.org/zh/index.html

2、入门案例

HTML代码

js引入 echarts.js

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
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>ECharts</title>
<!-- 引入刚刚下载的 ECharts 文件 -->
<script src="echarts.js"></script>
</head>
<body>
<!-- 为 ECharts 准备一个定义了宽高的 DOM -->
<div id="main" style="width: 600px;height:400px;"></div>
<script type="text/javascript">
// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('main'));

// 指定图表的配置项和数据
var option = {
title: {
text: 'ECharts 入门示例'
},
tooltip: {},
legend: {
data: ['销量']
},
xAxis: {
data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']
},
yAxis: {},
series: [
{
name: '销量',
type: 'bar',
data: [5, 20, 36, 10, 10, 20]
}
]
};

// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
</script>
</body>
</html>

3