Vue3知识点汇总-只记录我所不熟练的-来源黑马笔记以及本人补充
一、一些小小问题
1、npm create vite@latest 和 npm init vue@latest 构建的项目有什么区别?
npm create vite@latest 和 npm init vue@latest 是两个不同的命令,用于创建不同类型的项目,具体区别如下:
-
npm create vite@latest
-
用途: 这个命令用来创建一个新的 Vite 项目。Vite 是一个现代的前端构建工具,支持快速的开发和构建流程。
-
项目类型: 创建的项目可以是任何使用 Vite 的框架,比如 Vue、React、Svelte 等。
-
灵活性: 运行这个命令后,你可以选择不同的模板,比如 Vue、React、Vanilla JavaScript 等。
-
npm init vue@latest
-
用途: 这个命令专门用于创建一个新的 Vue 3 项目。它会自动设置一个基于 Vue 的开发环境。
-
项目类型: 仅针对 Vue 项目,通常会包含一些 Vue 特定的配置和最佳实践。
-
配置: 在创建 Vue 项目时,会提供一些默认的设置,比如 Vue Router、Vuex 等。
总结
2、let和var变量有什么区别
在 Vue.js 中,let 和 var 是 JavaScript 中用于声明变量的两种关键字。它们的区别不仅仅体现在 Vue 的使用中,而是 JavaScript 本身的特性。下面是它们的主要区别:
-
作用域 (Scope)
-
var:
- 函数作用域:
var 声明的变量具有函数作用域,即它只在函数内部可访问。如果在函数外部使用 var 声明变量,则该变量为全局变量。
- 提升 (Hoisting):
var 声明的变量会被提升到函数或全局作用域的顶部,即使在声明之前使用该变量,JavaScript 引擎也会先将其初始化为 undefined。
-
let:
- 块级作用域:
let 声明的变量有块级作用域,即它只在其被声明的代码块(如 if、for 等)内有效,外部无法访问。
- 没有提升:
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自带上传组件
-
这种使用方法由于不经过request.js 所以要在请求地址上加/api,请求代理才能拦截到这个请求
-
要自定义携带请求头
-
回调逻辑重要
使用这个以后文件上传不需要自己实现代码
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
| 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 () => { 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
| 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'
export default defineConfig({ plugins: [ vue(), ], resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)) } }, server:{ proxy:{ '/api':{ target:'http://localhost:8080', changeOrange:true, rewrite:(path)=>path.replace(/^\/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 => { if (result.data.code == 0) { return result.data; } 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 =>{ 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)处理。
-
传递普通 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)。
-
传递 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); });
|
在这种情况下,Axios 会自动将 params 对象编码为查询字符串,并附加到 URL 后面。
-
混合参数:传递 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、安装
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
| import { useTokenStore } from '@/stores/token.js'
const tokenStore = useTokenStore();
const login = async () => { let result = await loginService(registerData.value) 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
| import { useTokenStore } from '../stores/token'
export const articleCategoryListService = () => { const tokenStore = useTokenStore() 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
| import {createPinia} from '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> <script src="echarts.js"></script> </head> <body> <div id="main" style="width: 600px;height:400px;"></div> <script type="text/javascript"> 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]()