Vue 3 + TypeScript + Vite + pinia + element-plus + vue-routes 一步步带你刷出个完整后台系统

 一、先看下我的前一篇vue+pinaia .代码都在文里了。Pinia,Vue生态里Vuex的代替者_东宇科技的博客-CSDN博客我们通过创建一个简单的demo,来认识下pinia .....安装创建项目npm init vite@latestnpm install pinia....引用storeimport { createPinia } from 'pinia' const pinia = createPinia()const app =createApp(App) app.use(pinia)app.mount('#app')....创建stroeimport { defineStore} fromhttps://blog.csdn.net/ldy889/article/details/123481222

二、第二篇整合了vue-routes. https://blog.csdn.net/ldy889/article/details/123527485https://blog.csdn.net/ldy889/article/details/123527485

三、本文在上面的基础上,增加登录页面,登录后后台会返回token,然后跳转到后台首页。验证是否有权限,如直接访问后台的路由地址,路由守卫会返回到login页面登录, 前面2节可以跳着看,本节会贴出完整的代码。

1、npm init vite@latest  我们会得到一个helloWorld的项目。

Vue 3 + TypeScript + Vite + pinia + element-plus + vue-routes 一步步带你刷出个完整后台系统_第1张图片

 Vue 3 + TypeScript + Vite + pinia + element-plus + vue-routes 一步步带你刷出个完整后台系统_第2张图片

2、npm i 安装依赖,npm run dev测试看下结果

Vue 3 + TypeScript + Vite + pinia + element-plus + vue-routes 一步步带你刷出个完整后台系统_第3张图片

3、安装 npm install pinia  ,element-plus, vue-router, sass, sass-loader  

npm i vite-plugin-svg-icons -D   最终选用这个来使用svg-icon:参考:https://github.com/JetBrains/svg-sprite-loader/issues/434https://github.com/JetBrains/svg-sprite-loader/issues/434

Vue 3 + TypeScript + Vite + pinia + element-plus + vue-routes 一步步带你刷出个完整后台系统_第4张图片

 4、修改main.ts文件。

import { createApp } from 'vue'
import App from './App.vue'
 
//引入 pinia store
import { createPinia } from 'pinia'
 
//引入 element-plus
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css' 

import Router from './router' 

//引入 vite-plugin-svg-icons
import 'virtual:svg-icons-register' 
import SvgIcon from '@/components/SvgIcon/index.vue'// svg component
  
const pinia = createPinia()
const app =createApp(App) 
app.component('svg-icon', SvgIcon)
app.use(pinia)
app.use(ElementPlus)
app.use(Router)
app.mount('#app')





 5、修改src/App.vue 这个就是添加个路由槽






6、添加 src/router/index.ts , 这里用到扫描import ,vite的功能,取代原来webpack下的插件。不知道的看下我上面第二个文章。或者去vite官方文档里看下懒加载。

import { createRouter, createWebHashHistory } from "vue-router";
 
const modules = import.meta.glob("../views/*/*.vue");
for (const path in modules) {
  modules[path]().then((mod) => {
    console.log(path, mod);
  });
}

const Router = createRouter({
  history: createWebHashHistory(),
  routes: [ 
    {
      path: "/",
      component: modules["../views/login/index.vue"],
    }  
  ],
});

export default Router;

7、添加src/views/login/index.vue页面,写了一个按钮






8、运行 npm run dev : 结果: 

Vue 3 + TypeScript + Vite + pinia + element-plus + vue-routes 一步步带你刷出个完整后台系统_第5张图片

9、添加src/store/index.ts

import { defineStore} from 'pinia'

export const mainStore = defineStore('main',{
  state:()=>{
    return {
        helloWorld:'Hello World',
        count:0
    }
  },
  getters:{},
  actions:{
    changeState(){
        this.count++
        this.helloWorld='haha'
    }
  }
})

 10、修改src/views/login/index.vue页面






11、运行结果测试可以取到store里的值。到这里基本跑通了。下面开始写后台了。

Vue 3 + TypeScript + Vite + pinia + element-plus + vue-routes 一步步带你刷出个完整后台系统_第6张图片

 12、修改src/views/login/index.vue页面 让他显示该有的样子。








13、接下来是一键3连的广告时间。然后详细解读下login.vue.

--------广告位置------ 

Vue 3 + TypeScript + Vite + pinia + element-plus + vue-routes 一步步带你刷出个完整后台系统_第7张图片

--------广告位置------ 

14、第一是,图标显示不了了。 关于svg图标的使用,vite里无法使用webpack的svg-sprite-loader插件,而vue-svgicon又只支持vue2,vue3该如何使用svgicon呢。【2022-3-18】

安装:  npm i vite-plugin-svg-icons -D

修改vite.config.ts

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
import {resolve} from 'path'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(), 
    createSvgIconsPlugin({
    // 指定需要缓存的图标文件夹
    iconDirs: [resolve(process.cwd(), 'src/icons/svg')],
    // 指定symbolId格式
    symbolId: 'icon-[dir]-[name]',
  
    /**
     * custom dom id
     * @default: __svg__icons__dom__
     */
    customDomId: '__svg__icons__dom__',
  }),],
  resolve: {
    // 配置别名
    alias: {
      '@': resolve(__dirname, './src')
    }
  }
})

修改main.ts

import { createApp } from 'vue'
import App from './App.vue'
 
//引入 pinia store
import { createPinia } from 'pinia'
 
//引入 element-plus
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css' 

import Router from './router' 

//引入 vite-plugin-svg-icons
import 'virtual:svg-icons-register' 
import SvgIcon from '@/components/SvgIcon/index.vue'// svg component
 
 

const pinia = createPinia()
const app =createApp(App) 
app.component('svg-icon', SvgIcon)
app.use(pinia)
app.use(ElementPlus)
app.use(Router)
app.mount('#app')

创建:src/components/SvgIcon/index.vue






更新 src/utils/validate.ts

export const validUsername = (str: string) => ['admin', 'editor'].indexOf(str.trim()) >= 0

export const isExternal = (path: string) => /^(https?:|mailto:|tel:)/.test(path)

export const isArray = (arg: any) => {
  if (typeof Array.isArray === 'undefined') {
    return Object.prototype.toString.call(arg) === '[object Array]'
  }
  return Array.isArray(arg)
}

export const isValidURL = (url: string) => {
  const reg = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/
  return reg.test(url)
}

添加一些svg文件到 src/icons/svg/...

Vue 3 + TypeScript + Vite + pinia + element-plus + vue-routes 一步步带你刷出个完整后台系统_第8张图片

 运行结果:

Vue 3 + TypeScript + Vite + pinia + element-plus + vue-routes 一步步带你刷出个完整后台系统_第9张图片

 当然点击登录会有问题。

Vue 3 + TypeScript + Vite + pinia + element-plus + vue-routes 一步步带你刷出个完整后台系统_第10张图片

 接下来要用pinia了。先安装 vue-request,axios, nprogress进度条。

npm install vue-request
npm install axios
npm i --save-dev @types/nprogress

Vue 3 + TypeScript + Vite + pinia + element-plus + vue-routes 一步步带你刷出个完整后台系统_第11张图片

创建 service/http.ts

//http.ts
import axios, { AxiosRequestConfig } from 'axios'
import NProgress from 'nprogress'

// 设置请求头和请求路径
axios.defaults.baseURL = '/api'
axios.defaults.timeout = 10000
axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8'
axios.interceptors.request.use(
  (config): AxiosRequestConfig => {
    const token = window.sessionStorage.getItem('token')
    if (token) {
      //@ts-ignore
      config.headers.token = token
    }
    return config
  },
  (error) => {
    return error
  }
)
// 响应拦截
axios.interceptors.response.use((res) => {
  if (res.data.code === 111) {
    sessionStorage.setItem('token', '')
    // token过期操作
  }
  return res
})

interface ResType {
  code: number
  data?: T
  msg: string
  err?: string
}
interface Http {
  get(url: string, params?: unknown): Promise>
  post(url: string, params?: unknown): Promise>
  upload(url: string, params: unknown): Promise>
  download(url: string): void
}

const http: Http = {
  get(url, params) {
    return new Promise((resolve, reject) => {
      NProgress.start()
      axios
        .get(url, { params })
        .then((res) => {
          NProgress.done()
          resolve(res.data)
        })
        .catch((err) => {
          NProgress.done()
          reject(err.data)
        })
    })
  },
  post(url, params) {
    return new Promise((resolve, reject) => {
      NProgress.start()
      axios
        .post(url, JSON.stringify(params))
        .then((res) => {
          NProgress.done()
          resolve(res.data)
        })
        .catch((err) => {
          NProgress.done()
          reject(err.data)
        })
    })
  },
  upload(url, file) {
    return new Promise((resolve, reject) => {
      NProgress.start()
      axios
        .post(url, file, {
          headers: { 'Content-Type': 'multipart/form-data' },
        })
        .then((res) => {
          NProgress.done()
          resolve(res.data)
        })
        .catch((err) => {
          NProgress.done()
          reject(err.data)
        })
    })
  },
  download(url) {
    const iframe = document.createElement('iframe')
    iframe.style.display = 'none'
    iframe.src = url
    iframe.onload = function () {
      document.body.removeChild(iframe)
    }
    document.body.appendChild(iframe)
  },
}
export default http

 创建src/store/login.ts

import { defineStore } from "pinia";
import http from "@/service/http"; 
import   loginApi from "@/service/api/login"
import { ILoginParams } from "@/service/api/types";

export interface IUserState {
  token?: string;
  name?: string;
  avatar?: string;
  introduction?: string;
  roles?: string[];
  email?: string;
}

export const useUserStore = defineStore("user", {
  state: () => {
    return {
      userState: {},
    };
  },
  getters: {
    getUserState: (state) => state.userState  ,
  },
  actions: {
    async Login(params: ILoginParams) { 
      // const { data, error } = useRequest(http.post("/", { a: "" }));
      this.userState = await  loginApi.login(params).catch((error)=>{
        return {error:"发送请求失败:Login"};
      })
    },
  },
});

.添加src/api/login.ts

import http from '@/service/http'
import * as T from './types'

const loginApi: T.ILoginApi = {
    login(params){
        return http.post('/login', params)
    }

}
export default loginApi

添加src/api/types.ts

export interface ILoginParams {
        userName: string
        passWord: string | number
    }
export interface ILoginApi {
    login: (params: ILoginParams)=> Promise
}
    

好了到这里我们可以登录并跳转到另外一个页面了。 

祝你成功。

代码下载:vite-vue-admin-elui-demo-Typescript文档类资源-CSDN下载Vue3+TypeScript+Vite+pinia+element-plus+更多下载资源、学习资料请访问CSDN下载频道.https://download.csdn.net/download/ldy889/85001855

  Vben Admin

 一个admin后台。技术栈参考他的。

好的,目前我们能登录了。检查有token和用户信息后,跳转到dashboard页面“/”。所以我们的路由应该看起来是这样的。

import { createRouter, createWebHashHistory } from "vue-router";

const modules = import.meta.glob("../views/*/*.vue");
for (const path in modules) {
  modules[path]().then((mod) => {
    console.log(path, mod);
  });
}

const Router = createRouter({
  history: createWebHashHistory(),
  routes: [
    {
      path: "/login",
      component: modules["../views/login/index.vue"],
    },
    {
      path: "/",
      component: modules["../views/dashboard/index.vue"],
    },
  ],
});

export default Router;

Vue 3 + TypeScript + Vite + pinia + element-plus + vue-routes 一步步带你刷出个完整后台系统_第12张图片

 Vue 3 + TypeScript + Vite + pinia + element-plus + vue-routes 一步步带你刷出个完整后台系统_第13张图片

 添加 src/views/dashboard/index.vue






你可能感兴趣的:(Vue,vue.js,typescript,前端)