首页 > 其他分享 >Vue+vite+ts+axios+element plus

Vue+vite+ts+axios+element plus

时间:2022-10-23 20:23:06浏览次数:79  
标签:resolved reused axios downloaded ts element instance added Progress

一、介绍

  • vue
  • vite
  • TypeScript
  • Scss
  • Element Plus
  • Route
  • axios
  • Vuex

二、步骤

2.1、创建项目

  • 使用Vite快速构建项目

    • Vite 是一种新型前端构建工具,能够显著提升前端开发体验。
    # 项目名称不建议用大写,容易报错
    $ npm init vite@latest vue.admin
    √ Select a framework: » Vue
    √ Select a variant: » TypeScript
    
    Scaffolding project in D:\vsdemo\vs2022\HisApi\vue.admin...
    
    Done. Now run:
    
      cd vue.admin
      npm install
      npm run dev
      
    $ cd vue.admin
    
    $ npm install
    
    added 44 packages, and audited 45 packages in 19s
    
    4 packages are looking for funding
      run `npm fund` for details
    
    found 0 vulnerabilities
    
    $ npm run dev
    
    > [email protected] dev
    > vite
    
    
      VITE v3.1.8  ready in 440 ms
    
      ➜  Local:   http://localhost:5173/
      ➜  Network: use --host to expose  
    
  • 目录介绍

    • node_modules:模块包
    • public:公共资源
    • src:项目目录
      • assets:静态资源
      • components:组件
      • App.vue:根组件
      • main.ts:根函数入口、全局配置生效的地方
      • style.css:
      • vite-env.d.ts
    • package.json:项目配置文件、项目的标题、版本、模块版本等信息
    • tsconfig.json:ts配置文件
    • vite.config.ts:vite的配置文件

2.2、pnpm

  • 节省磁盘空间并提升安装速度

  • 安装

    $ npm install -g pnpm
    
    $ pnpm -v
    7.13.6
    
    ## 启动
    $ pnpm dev
    
    > [email protected] dev D:\vsdemo\vs2022\HisApi\vue.admin
    > vite
    
    
      VITE v3.1.8  ready in 413 ms
    
      ➜  Local:   http://localhost:5173/
      ➜  Network: use --host to expose
    
    

2.3、scss

$ pnpm install sass --save
Progress: resolved 0, reused 1, downloaded 0, added 0
Progress: resolved 5, reused 5, downloaded 0, added 0
Progress: resolved 75, reused 48, downloaded 1, added 0
Progress: resolved 85, reused 48, downloaded 12, added 0
Packages: +17 -1
+++++++++++++++++-

dependencies:
+ sass 1.55.0

2.4、Element Plus

$ pnpm install element-plus
Progress: resolved 0, reused 1, downloaded 0, added 0
Progress: resolved 6, reused 6, downloaded 0, added 0
Progress: resolved 89, reused 63, downloaded 1, added 0
Progress: resolved 103, reused 64, downloaded 9, added 0
Packages: +21
+++++++++++++++++++++
Progress: resolved 107, reused 64, downloaded 18, added 17
Progress: resolved 107, reused 64, downloaded 20, added 20
Progress: resolved 107, reused 64, downloaded 21, added 20
.../node_modules/vue-demi postinstall$ node ./scripts/postinstall.js
.../node_modules/vue-demi postinstall: Done
Progress: resolved 107, reused 64, downloaded 21, added 21, done

dependencies:
+ element-plus 2.2.19

Done in 8.5s

  • 自动导入(推荐)

    $ pnpm install -D unplugin-vue-components unplugin-auto-import
    Progress: resolved 0, reused 1, downloaded 0, added 0
    Progress: resolved 8, reused 7, downloaded 0, added 0
    Progress: resolved 94, reused 72, downloaded 3, added 0
    Progress: resolved 135, reused 85, downloaded 24, added 0
    Packages: +34
    ++++++++++++++++++++++++++++++++++
    
    devDependencies:
    + unplugin-auto-import 0.11.2
    + unplugin-vue-components 0.22.8
    
    Done in 4.3s
    Progress: resolved 141, reused 85, downloaded 34, added 34, done
    
    
  • 修改 vite.config.ts

    import { defineConfig } from 'vite'
    import vue from '@vitejs/plugin-vue'
    import AutoImport from 'unplugin-auto-import/vite'
    import Components from 'unplugin-vue-components/vite'
    import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
    // https://vitejs.dev/config/
    export default defineConfig({
      plugins: [vue(),
      // ...
      AutoImport({
        resolvers: [ElementPlusResolver()],
      }),
      Components({
        resolvers: [ElementPlusResolver()],
      }),]
    })
    
    

2.5、router

  • 安装

    $ pnpm install vue-router@next --save
    Progress: resolved 0, reused 1, downloaded 0, added 0
    Progress: resolved 9, reused 9, downloaded 0, added 0
    Progress: resolved 107, reused 105, downloaded 1, added 0
    Packages: +2
    ++
    
    dependencies:
    + vue-router 4.0.13 (4.1.5 is available)
    
    Done in 3.3s
    Progress: resolved 143, reused 119, downloaded 2, added 2, done
    
    
  • src目录下新建文件夹router,文件夹新建 路由文件index.ts 写入页面和路由映射关系

    import { createRouter, createWebHistory } from "vue-router";
    import Login from "./views/index/LoginPage.vue";
    
    const router = createRouter({
      history: createWebHistory(),
      routes: [{ path: "/login", component: Login }],
    });
    export default router;
    
  • main.ts

    import { createApp } from "vue";
    import "./style.css";
    import App from "./App.vue";
    import router from "./router";
    
    createApp(App).use(router).mount("#app");
    
  • 在App.vue里面加上路由标签

    <router-view></router-view>
    
    

2.6、Vuex

  • Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

  • $ pnpm install vuex@next --save
    Progress: resolved 0, reused 1, downloaded 0, added 0
    Progress: resolved 11, reused 10, downloaded 0, added 0
    Packages: +1
    +
    Progress: resolved 144, reused 121, downloaded 1, added 1, done
    
    dependencies:
    + vuex 4.0.2 (4.1.0 is available)
    
    
  • src目录下新建文件夹store,新建文件index.ts

    import { createStore } from "vuex";
    
    const store = createStore({
      // 状态变量
      state() {
        return {
          Token: "",
          NikeName: "",
        };
      },
      // 方法
      mutations: {
        SettingNikeName(state: any, NickName) {
          state.NickName = NickName;
        },
        SettingToken(state: any, Token) {
          state.Token = Token;
        },
      },
    });
    export default store;
    
    
  • main.ts

    import store from "./store/index";
    
    createApp(App).use(store).use(router).mount("#app");
    
    

2.7、echarts

  • https://echarts.apache.org/handbook/zh/get-started

  • 安装

    $ pnpm install echarts --save
    Progress: resolved 0, reused 1, downloaded 0, added 0
    Progress: resolved 11, reused 11, downloaded 0, added 0
    Progress: resolved 117, reused 114, downloaded 0, added 0
    Packages: +3
    +++
    Progress: resolved 147, reused 122, downloaded 2, added 1
    Progress: resolved 147, reused 122, downloaded 2, added 2
    
    dependencies:
    + echarts 5.4.0
    
    Done in 5.5s
    Progress: resolved 147, reused 122, downloaded 3, added 3, done
    
    

2.8、axios

  • 安装

    $ pnpm install axios --save
    Progress: resolved 0, reused 1, downloaded 0, added 0
    Progress: resolved 22, reused 21, downloaded 0, added 0
    Progress: resolved 151, reused 125, downloaded 3, added 0
    Progress: resolved 153, reused 125, downloaded 6, added 0
    Packages: +9
    +++++++++
    Progress: resolved 156, reused 125, downloaded 9, added 9, done
    
    dependencies:
    + axios 1.1.3
    
    Done in 4.6s
    
    
  • src目录下新建http文件夹,新建index.ts文件

    import axios from 'axios'
    //需要拦截器的地方使用instance对象, 有自定义返回逻辑的地方沿用axios,在组件内部处理返回结果即可
    import instance from './filter'
    const http = "/api"; 
    
    //获取token,,因为instance开启了withCredentials 所以这里要用axios,因为instance有连接器功效,必须携带token
    export const getToken = (name: string, password: string) => {
        return axios.get(http + '/Login/GetToken?name=' + name + '&password=' + password);
    };
    
    //菜单模块
    //获取列表
    export const getMenuDataNew = async (parms: {}) => {
        instance.defaults.headers.common['Authorization'] = "Bearer " + localStorage["token"];
        return instance.post(http + "/Menu/GetMenus", parms)
    }
    //添加
    export const addMenu = async (parms: {}) => {
        instance.defaults.headers.common['Authorization'] = "Bearer " + localStorage["token"];
        return instance.post(http + "/Menu/Add", parms)
    }
    //修改
    export const editMenu = async (parms: {}) => {
        instance.defaults.headers.common['Authorization'] = "Bearer " + localStorage["token"];
        return instance.post(http + "/Menu/Edit", parms)
    }
    //删除
    export const delMenu = async (id: number) => {
        instance.defaults.headers.common['Authorization'] = "Bearer " + localStorage["token"];
        return instance.get(http + "/Menu/Del?id=" + id)
    }
    //BatchDel
    export const batchDelMenu = async (ids: string) => {
        instance.defaults.headers.common['Authorization'] = "Bearer " + localStorage["token"];
        return instance.get(http + "/Menu/BatchDel?ids=" + ids)
    }
    //分配菜单
    export const settingMenu = async (rid: string,mids: string) => {
        instance.defaults.headers.common['Authorization'] = "Bearer " + localStorage["token"];
        return instance.get(`${http}/Menu/SettingMenu?rid=${rid}&mids=${mids}`)
    }
    //角色模块
    //获取列表
    export const getRoleData = async (parms: {}) => {
        instance.defaults.headers.common['Authorization'] = "Bearer " + localStorage["token"];
        return instance.post(http + "/Role/GetRoles", parms)
    }
    //添加
    export const addRole = async (parms: {}) => {
        instance.defaults.headers.common['Authorization'] = "Bearer " + localStorage["token"];
        return instance.post(http + "/Role/Add", parms)
    }
    //修改
    export const editRole = async (parms: {}) => {
        instance.defaults.headers.common['Authorization'] = "Bearer " + localStorage["token"];
        return instance.post(http + "/Role/Edit", parms)
    }
    //删除
    export const delRole = async (id: number) => {
        instance.defaults.headers.common['Authorization'] = "Bearer " + localStorage["token"];
        return instance.get(http + "/Role/Del?id=" + id)
    }
    //BatchDel
    export const batchDelRole = async (ids: string) => {
        instance.defaults.headers.common['Authorization'] = "Bearer " + localStorage["token"];
        return instance.get(http + "/Role/BatchDel?ids=" + ids)
    }
    
    //用户模块
    //获取列表
    export const getUserData = async (parms: {}) => {
        instance.defaults.headers.common['Authorization'] = "Bearer " + localStorage["token"];
        return instance.post(http + "/Users/GetUsers", parms)
    }
    //添加
    export const addUsers = async (parms: {}) => {
        instance.defaults.headers.common['Authorization'] = "Bearer " + localStorage["token"];
        return instance.post(http + "/Users/Add", parms)
    }
    //修改
    export const editUsers = async (parms: {}) => {
        instance.defaults.headers.common['Authorization'] = "Bearer " + localStorage["token"];
        return instance.post(http + "/Users/Edit", parms)
    }
    //删除
    export const delUsers = async (id: number) => {
        instance.defaults.headers.common['Authorization'] = "Bearer " + localStorage["token"];
        return instance.get(http + "/Users/Del?id=" + id)
    }
    //BatchDel
    export const batchDelUsers = async (ids: string) => {
        instance.defaults.headers.common['Authorization'] = "Bearer " + localStorage["token"];
        return instance.get(http + "/Users/BatchDel?ids=" + ids)
    }
    //分配
    export const settingRole = async (pid: string,rids: string) => {
        instance.defaults.headers.common['Authorization'] = "Bearer " + localStorage["token"];
        return instance.get(`${http}/Users/SettingRole?pid=${pid}&rids=${rids}`)
    }
    //根据角色获取菜单
    export const getUserMenus = async () => {
        instance.defaults.headers.common['Authorization'] = "Bearer " + localStorage["token"];
        return instance.get(`${http}/Menu/GetUserMenus`)
    }
    //个人中心修改用户昵称和密码
    export const editNickNameOrPassword = async (nickName: string,password: string) => {
        instance.defaults.headers.common['Authorization'] = "Bearer " + localStorage["token"];
        return instance.get(`${http}/Users/EditNickNameOrPassword?nickName=${nickName}&password=${password}`)
    }
    
  • 在需要使用的组件里导入http中的方法即可

    import { getToken } from '../../http/index'
    //请求后端数据,获取token,并将token放入localStorage
    const token = await getToken(form.userName, form.passWord) as any as string
    const user: UserInfo = JSON.parse(new Tool().FormatToken(token))
    localStorage["token"] = token 
    localStorage["nickname"] = user.NickName
    store.commit("SettingNickName",user.NickName)
    store.commit("SettingToken",token)
    router.push({ path: '/desktop' });
    
  • 拦截器:

    • 对api的返回结果解析,返回统一的格式。
    • 对于错误信息,在拦截器中弹窗提示,业务层页面只需关注页面,无需过度关注交互
    //导入axios
    import axios from 'axios'
    import { ElMessage } from 'element-plus'
    //创建一个axios实例 
    const instance = axios.create({
        headers: {
            'content-type': 'application/json',
        },
        // true:在跨域请求时,会携带用户凭证
    	// false(默认):在跨域请求时,不会携带用户凭证;返回的 response 里也会忽略 cookie
        // withCredentials: true,
        timeout: 5000  //5秒
    })
    //http 拦截器
    instance.interceptors.response.use(
        response=>{
            //拦截请求,统一相应
            if (response.data.isSuccess) {
                return response.data.result
            } else {
                ElMessage.error(response.data.msg)
                return response.data.result
            }
        },
        //error也可以处理
        error=>{
            if (error.response) { 
                switch (error.response.status) {
                    case 401:
                        ElMessage.warning("资源没有访问权限!")
                        break
                    case 404:
                        ElMessage.warning("接口不存在,请检查接口地址是否正确!")
                        break
                    case 500:
                        ElMessage.warning("内部服务器错误,请联系系统管理员!")
                        break
                    default:
                        return Promise.reject(error.response.data)   // 返回接口返回的错误信息 
                }
            }
            else {
                ElMessage.error("遇到跨域错误,请设置代理或者修改后端允许跨域访问!")
            }
        }
    )
    export default instance
    

2.9、icons-vue

  • 安装

    pnpm install @element-plus/icons-vue
    
  • 使用

    <script lang="ts" setup>
    import { CoffeeCup, Apple, Drizzling, Headset } from '@element-plus/icons-vue'
    // import { defineProps } from 'vue'; // 新版不需要引用
    import { CardModel } from '../class/CardModel'
    defineProps({
        info: CardModel
    })
    </script>
    
    <div class="left">
        <coffee-cup v-if="info?.Icon == 'CoffeeCup'" />
        <apple v-if="info?.Icon == 'Apple'" />
        <drizzling v-if="info?.Icon == 'Drizzling'" />
        <headset v-if="info?.Icon == 'Headset'" />
    </div>
    
    

2.10、前端解决跨域问题

  • 和后端解决是两种方案,而不是必须前后端都解决跨域问题;

  • 代码 vite.config.ts

    // vite.config.ts
    
     server:{
        port:3000,
        open:true,
        proxy:{ 
          '/api':{
            target:'http://localhost:5294/api',
            changeOrigin:true,
            rewrite:(path) => path.replace(/^\/api/,'')
          }
        },
      }
    
    

2.11、ts的class

  • 创建类

    export class CardModel {
        Icon: string = '';
        Title: string = '';
        Count: number = 0;
    }
    
    
  • 使用

    import { CardModel } from '../class/CardModel'
    defineProps({
        info: CardModel
    })
    

标签:resolved,reused,axios,downloaded,ts,element,instance,added,Progress
From: https://www.cnblogs.com/his365/p/16819364.html

相关文章