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-componentsunplugin-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')
posted @ 2022-12-21 13:54  凡223  阅读(63)  评论(0编辑  收藏  举报