Vue3 总结(开发)
更详细的 API 和使用见:Vue2 总结(开发)_凡 223 的博客
1. Vue Router
官网地址:Home | Vue Router (vuejs.org)
1.1 安装
npm install vue-router@4
1.2 使用
1.2.1 new Router 变成 createRouter
// 以前是
// import Router from 'vue-router'
import { createRouter } from 'vue-router'
const router = createRouter({
// ...
})
1.2.2 新的 history 配置取代 mode
mode: 'history'
配置已经被一个更灵活的 history
配置所取代。根据使用的模式,必须用适当的函数替换它:
"history"
:createWebHistory()
"hash"
:createWebHashHistory()
"abstract"
:createMemoryHistory()
import { createRouter, createWebHashHistory } from 'vue-router'
// 还有 createWebHashHistory 和 createMemoryHistory
createRouter({
history: createWebHashHistory(),
routes: [],
})
1.2.3 index.js 示例
import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: '/',
redirect: '/home',
name: 'Root',
component: () => import('@/layout/MainMenu.vue'),
children: [
{
path: '/home',
name: 'Home',
component: () => import('@/views/Home.vue')
}
],
},
{
path: '/index',
name: 'Index',
component: () => import('@/views/Index.vue'),
},
]
})
export default router
1.2.4 main.js 里引入
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(router)
.mount('#app')
1.2.5 组合式 API
<script>
import { useRouter, useRoute } from 'vue-router'
export default {
// eslint-disable-next-line vue/multi-word-component-names
name: 'Login',
setup() {
const router = useRouter()
const route = useRoute()
function pushWithQuery(query) {
// router.push('/home');
router.push({
name: 'Hone',
query: {
...route.query,
},
})
}
return {
pushWithQuery,
};
},
};
</script>
1.3 导航守卫和动态路由
可以在路由前注册一个全局前置守卫来进行动态路由
// 全局前置守卫
router.beforeEach((to, from ,next) => {
let hasRoute = store.state.menu.hasRoute;
if (to.path === '/login') {
next()
} else if(!localStorage.getItem('JWT')) {
ElMessage({
message: '请先登录',
type: 'error'
})
next('/login')
} else if (!hasRoute){
axios.get('/resNav/menu/listNavMenus').then(response => {
// 拿到 menus 菜单列表
store.commit('SET_MENUS', response.data.data.menus);
// 拿到 authorities 权限列表
store.commit('SET_AUTHORITIES', response.data.data.authorities);
if(response.data.data.menus) {
// 动态绑定路由
response.data.data.menus.forEach(menu => {
if (menu.children && menu.children.length > 0) {
transToRouter(menu)
} else {
let route = menuToRouter(menu);
if (route) {
router.addRoute('Root', route);
}
}
});
store.commit('CHANGE_ROUTE_STATUS', true);
}
next(to.path)
})
} else {
next()
}
})
function transToRouter(menu) {
if(menu.children && menu.children.length > 0) {
menu.children.forEach(child => {
transToRouter(child)
})
} else {
let route = menuToRouter(menu);
if (route) {
router.addRoute('Root', route)
}
}
}
function menuToRouter(menu) {
if(!menu.component){
return null;
} else {
return {
path: menu.path,
name: menu.permission,
component: () => import('@/views' + menu.component +'.vue'),
meta: {
title: menu.name,
icon: menu.icon
}
}
}
}
export default router
2. Vuex
官网地址:Vuex 是什么? | Vuex (vuejs.org)
2.1 安装
npm install vuex@next --save
2.2 使用
2.2.1 new Vuex.Store 变成 createStore
import { createStore } from 'vuex'
export const store = createStore({
state () {
return {
count: 1
}
}
})
2.2.2 index.js 示例
import { createStore } from 'vuex'
const store = createStore({
state: {
isCollapsed: false
}
})
export default store
2.2.3 main.js 里引入
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
const app = createApp(App)
app.use(router)
.use(store)
.mount('#app')
2.2.4 组合式 API 中使用 store
可以通过调用 useStore
函数,来在 setup
钩子函数中访问 store。这与在组件中使用选项式 API 访问 this.$store
是等效的
import { useStore } from 'vuex'
export default {
setup () {
const store = useStore()
}
}
访问 State
<script>
import { useStore } from 'vuex'
export default {
name: 'HeaderMenu',
setup() {
const store = useStore()
function collapsedSider() {
store.state.isCollapsed = !store.state.isCollapsed
}
return {
collapsedSider
}
}
}
</script>
同上,访问 Getter、Mutation 和 Action 类似
3. View UI Plus
官网地址:View Design (iviewui.com)
3.1 安装
npm install view-ui-plus --save
3.2 main.js 里引入
3.2.1 完整引入
import { createApp } from 'vue'
import App from './App.vue'
import ViewUIPlus from 'view-ui-plus'
import 'view-ui-plus/dist/styles/viewuiplus.css'
const app = createApp(App)
app.use(ViewUIPlus)
.mount('#app')
3.2.2 按需引入
助插件 babel-plugin-import 可以实现按需加载组件,减少文件体积
1、安装
npm install babel-plugin-import --save-dev
2、在文件 babel.config.js 里配置
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
],
plugins: [
[
"import",
{
"libraryName": "view-ui-plus",
"libraryDirectory": "src/components"
},
"view-ui-plus"
]
]
}
3、再进行引入
import { createApp } from 'vue'
import App from './App.vue'
import { Button, Table } from 'view-ui-plus';
import 'view-ui-plus/dist/styles/viewuiplus.css';
const app = createApp(App)
app.component('Button', Button);
app.component('Table', Table);
app.mount('#app')
3.3 使用
按照官方文档使用相关组件即可:View Design (iviewui.com)
4. Element Plus
官网地址:Element Plus (element-plus.org)
4.1 安装
npm install element-plus --save
4.2 main.js 里引入
4.2.1 完整引入
import { createApp } from 'vue'
import App from './App.vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
const app = createApp(App)
app.use(ElementPlus)
app.mount('#app')
4.2.2 按需引入
自动导入
1、安装 unplugin-vue-components
和 unplugin-auto-import
这两款插件
npm install -D unplugin-vue-components unplugin-auto-import
2、在 Webpack
的配置文件里配置
const AutoImport = require('unplugin-auto-import/webpack')
const Components = require('unplugin-vue-components/webpack')
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')
module.exports = {
// ...
plugins: [
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
],
}
手动导入
1、安装 unplugin-element-plus 来导入样式,参考 文档 进行配置
2、使用
<template>
<el-button>I am ElButton</el-button>
</template>
<script>
import { ElButton } from 'element-plus'
export default {
components: { ElButton },
}
</script>
4.3 使用
按照官方文档使用相关组件即可:Element Plus
4.3.1 图标使用
1、安装
npm install @element-plus/icons-vue
2、main.js 里注册所有图标
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
const app = createApp(App)
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
3、组件中配合 Button 使用
<template>
<el-button :icon="Fold"> </el-button>
<el-button :icon="Expand"> </el-button>
</template>
<script>
import { Fold, Expand } from '@element-plus/icons-vue'
export default {
name: 'HeaderMenu',
setup() {
return {
Fold,
Expand
}
}
}
</script>
4.3.2 消息提示使用
1、全局方法
<script>
import { getCurrentInstance } from "@vue/runtime-core";
export default {
// eslint-disable-next-line vue/multi-word-component-names
name: 'Login',
setup() {
const { proxy } = getCurrentInstance()
proxy.$message({
message: '',
type: 'success',
})
}
}
</script>
2、单独引用
import { ElMessage } from 'element-plus'
3、全局注入
main.js
import { ElMessage } from 'element-plus'
app.provide('ElMessage', ElMessage)
组件使用
<script>
import { inject } from "@vue/runtime-core";
export default {
// eslint-disable-next-line vue/multi-word-component-names
name: 'Login',
setup() {
const ElMessage = inject('ElMessage')
ElMessage({
message: '',
type: 'success',
})
}
}
</script>
5. Vue-Axios
官网地址:axios 中文文档 (axios-js.com)
5.1 安装
npm install --save axios vue-axios
5.2 main.js 里引入
import { createApp } from 'vue'
import App from './App.vue'
import axios from 'axios'
import VueAxios from 'vue-axios'
const app = createApp(App)
app.use(VueAxios, axios)
.mount('#app')
5.3 使用
1、使用 app.provide
main.js 里添加一条配置
import { createApp } from 'vue'
import App from './App.vue'
import axios from 'axios'
import VueAxios from 'vue-axios'
const app = createApp(App)
app.use(VueAxios, axios)
.mount('#app')
app.provide('axios', app.config.globalProperties.axios)
在组件中使用
<script>
import { inject } from '@vue/runtime-core';
export default {
name: 'AsideMenu',
setup() {
const axios = inject('axios')
function listMenu() {
axios.get('/resNav/menu/listMenu').then(
response => {
console.log(response.data.data.records);
}
)
}
listMenu();
},
}
</script>
2、使用 app.config.globalProperties
main.js 里添加一条配置
import { createApp } from 'vue'
import App from './App.vue'
import axios from 'axios'
import VueAxios from 'vue-axios'
const app = createApp(App)
app.use(VueAxios, axios)
.mount('#app')
app.config.globalProperties.$axios = axios;
在组件中使用
<script>
import { getCurrentInstance } from '@vue/runtime-core';
export default {
name: 'AsideMenu',
setup() {
const { proxy } = getCurrentInstance();
function listMenu() {
proxy.axios.get('/resNav/menu/listMenu').then(
response => {
console.log(response.data.data.records);
}
)
}
listMenu();
},
}
</script>
5.4 全局拦截器
创建 axios.js 文件
import axios from 'axios';
import { ElMessage } from 'element-plus'
import router from '@/router'
import ViewUIPlus from 'view-ui-plus';
const request = axios.create({
timeout: 10000,
headers: {
'Content-Type': 'application/json',
},
});
request.interceptors.request.use(config => {
if (localStorage.getItem("JWT")) {
// 请求头带上 JWT
config.headers.Authorization = localStorage.getItem("JWT");
}
return config;
});
request.interceptors.response.use(response => {
return response;
}, error => {
ViewUIPlus.LoadingBar.error()
if (error.response) {
switch (error.response.status) {
case 400:
ElMessage({
message: '请求错误',
type: 'error'
})
break;
case 401:
router.push('/login');
ElMessage({
message: '登录已过期, 请重新登录',
type: 'error'
})
break;
case 403:
ElMessage({
message: error.response.data.msg,
type: 'error'
})
break;
case 404:
ElMessage({
message: '请求错误,未找到该资源',
type: 'error'
})
break;
case 500:
ElMessage({
message: '服务器出错',
type: 'error'
})
break;
default:
ElMessage({
message: '未知错误',
type: 'error'
})
}
}
return Promise.reject(error);
});
export default request
在 main.js 文件中替换引入
import request from './axios'
import VueAxios from 'vue-axios'
app.use(VueAxios, request)
.mount('#app')