Vite4+Pinia2+vue-router4+ElmentPlus搭建Vue3项目(组件、图标等按需引入)[保姆级]

这篇具有很好参考价值的文章主要介绍了Vite4+Pinia2+vue-router4+ElmentPlus搭建Vue3项目(组件、图标等按需引入)[保姆级]。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文为快速搭建vite4项目,一些插件的详情就不做过多的解释,都放有官网链接,需要深入了解的小伙伴可自行查看。至于为什么选择使用vite,因为它具备着快速启动、按需编译、模块热更新的亮点。归根结底最大的特点就是。vue的创始人是尤雨溪大佬,vite也是他。所以放心大胆的用吧。

壹、初始化项目 😆😆😆😆

1️⃣ 通过yarn初始化项目

Vite4+Pinia2+vue-router4+ElmentPlus搭建Vue3项目(组件、图标等按需引入)[保姆级]

yarn create vite 你的项目名称 --template vue-ts

:如果没有yarn的可通过npm执行命令npm install -g yarn进行安装

2️⃣ 如下图,到这里我们的vite项目就初始化好了,跟着提示,进入ts-super-web(自己的项目名)根目录下执行yarn,下载完依赖后执行yarn dev就可以启动项目。

Vite4+Pinia2+vue-router4+ElmentPlus搭建Vue3项目(组件、图标等按需引入)[保姆级]

Vite4+Pinia2+vue-router4+ElmentPlus搭建Vue3项目(组件、图标等按需引入)[保姆级]

Vite4+Pinia2+vue-router4+ElmentPlus搭建Vue3项目(组件、图标等按需引入)[保姆级]

3️⃣ 启动成功以后浏览器访问http://127.0.0.1:5173/ 👇👇👇👇

Vite4+Pinia2+vue-router4+ElmentPlus搭建Vue3项目(组件、图标等按需引入)[保姆级]

贰、安装相关依赖 😜😜😜😜

1️⃣ element-plus为UI框架。pinia和vuex一样为状态管理。vue-router路由。nprogress顶部进度条。animate.css一个跨浏览器的动画库。

yarn add element-plus pinia vue-router nprogress animate.css

2️⃣ 安装图标库

yarn add @iconify-json/carbon @iconify-json/ep @iconify-json/noto -D

3️⃣ 按需引入涉及到的依赖安装

yarn add unplugin-vue-components unplugin-auto-import unplugin-icons -D

4️⃣ 其他依赖安装,支持sass,jsx等等

yarn add sass sass-loader @types/node @vitejs/plugin-vue-jsx -D

5️⃣ 项目根目录下修改tsconfig.json

{
  "compilerOptions": {
    "target": "esnext", // 目标语言的版本
    "useDefineForClassFields": true,
    "module": "esnext", // 生成代码的模板标准
    "moduleResolution": "node", // 模块解析策略,ts默认用node的解析策略,即相对的方式导入
    "strict": true, // 开启所有严格的类型检查
    "jsx": "preserve", // 指定将 JSX 编译成什么形式
    "jsxFactory": "h", // 当使用经典的JSX运行时编译JSX元素时,更改.js文件中调用的函数,默认:React.createElement 。
    "jsxFragmentFactory": "Fragment",
    "sourceMap": true, // 生成目标文件的sourceMap文件
    "resolveJsonModule": true, // 指定 JSX 片段工厂函数在指定了 jsxFactory 编译器选项的情况下针对 react JSX 发出时使用。
    "esModuleInterop": true, // 允许export=导出,由import from 导入
    // TS需要引用的库,即声明文件,es5 默认引用dom、es5、scripthost,如需要使用es的高级版本特性,通常都需要配置,如es8的数组新特性需要引入"ES2019.Array"
    "lib": ["esnext", "dom"],
    "types": ["vite/client", "element-plus/global", "unplugin-icons/types/vue"], // 加载的声明文件包
    "baseUrl": ".", // 解析非相对模块的基地址,默认是当前目录
    "skipLibCheck": true, // 忽略所有的声明文件( *.d.ts)的类型检查。
    "paths": { // 路径映射,相对于baseUrl
      "@/*": [
        "src/*"
      ]
    }
  },
  // 指定一个匹配列表(属于自动指定该路径下的所有ts相关文件)
  "include": ["src/**/*.ts", "**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "src/autoImport/*.d.ts"],
  "exclude": [
    "node_modules"
  ]
}

叁、配置ElementPlus、图标库,vueAPI等按需引入,支持jsx、tsx等 😉😉😉😉

为什么做按需引入,相对于全局引入来说很大程度上的减少了代码体积。

1️⃣ 在项目根目录下修改vite.config.ts

注:按需引入这里需要在src文件夹下新建一个autoImport的文件夹存在按需引入生成的文件。这样做的目的是,后期如果传git,可以屏蔽这个文件夹。

import { defineConfig } from 'vite'
import path from 'path'
import vue from '@vitejs/plugin-vue'
import Icons from 'unplugin-icons/vite'
import IconsResolver from 'unplugin-icons/resolver'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import vueJsx from '@vitejs/plugin-vue-jsx';
const pathSrc = path.resolve(__dirname, 'src')

export default defineConfig({
  resolve: {
    alias: {
      '@': pathSrc, // 文件系统路径别名
    }
  },
  plugins: [
    vue(),
    vueJsx(), // 支持jsx、tsx的写法
    AutoImport({
      imports: ['vue'],
      resolvers: [
        ElementPlusResolver(),
        IconsResolver({
          prefix: 'Icon'
        })
      ],
      dts: path.resolve(pathSrc + '/autoImport', 'auto-imports.d.ts')
    }),
    Components({
      resolvers: [
        ElementPlusResolver(),
        IconsResolver({
          enabledCollections: ['ep', 'carbon', 'noto']
        })
      ],
      dts: path.resolve(pathSrc + '/autoImport', 'components.d.ts')
    }),
    Icons({
      autoInstall: true,
      compiler: 'vue3'
    })
  ],
  server: {
    host: '0.0.0.0', // 指定服务器应该监听哪个 IP 地址
    port: 9527, // 指定开发服务器端口
    strictPort: true, // 若端口已被占用则会直接退出
    https: false, // 启用 TLS + HTTP/2
    open: false, // 启动时自动在浏览器中打开应用程序
  }
})

2️⃣ 测试ElementPlus、图标以及vue3API等按需引入情况。修改App.vue文件。

<template>
  <el-row :gutter="20">
    <el-col :span="6">
      <el-button type="primary">Primary</el-button>
    </el-col>
    <el-col :span="6">
      <el-button type="success">Success</el-button>
    </el-col>
    <el-col :span="6">
      <el-button type="info">Info</el-button>
    </el-col>
    <el-col :span="6">
      <el-button type="warning"><i-ep-delete />Warning</el-button>
    </el-col>
  </el-row>
  <br/>
  <br/>
  <br/>
  <el-button type="primary" @click="changeCount">++++</el-button>
  <br/>
  <br/>
  <br/>
  <span style="color: red;font-size: 22px;">{{ count }}</span>
</template>

<script lang="ts">
export default defineComponent({
  setup() {

    let data = reactive({
      count: 1,
    })

    const changeCount = () => {
      data.count++
    }

    return {
      changeCount,
      ...toRefs(data)
    }
  }
})
</script>

3️⃣ 成功运行至下列效果表示按需引入没有任何问题 👇👇👇👇

Vite4+Pinia2+vue-router4+ElmentPlus搭建Vue3项目(组件、图标等按需引入)[保姆级]

肆、vue-router路由以及路由拦截器配置 😋😋😋😋

至于vue-router的话,在vue2大家应该已经很熟悉了,vue全家桶必备知识。

1️⃣ src文件夹下新建router文件夹。接着新建index.ts和permission.ts两个文件。前者是路由,后面是路由拦截器,我喜欢放在一块。你可以根据自己的情况放到其他位置也行。

2️⃣ index.ts 路由配置

import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'

export const asyncRoutes: RouteRecordRaw[] = [
    {
        path: '/',
        name: 'home',
        meta: {
            title: 'home'
        },
        component: () => import('@/views/home.vue')
    },
    {
        path: '/home1',
        name: 'home1',
        meta: {
            title: 'home1'
        },
        component: () => import('@/views/home1.vue')
    }
]

const router = createRouter({
    history: createWebHashHistory(),
    routes: asyncRoutes,
    scrollBehavior: () => ({ left: 0, top: 0 })
})

export default router

3️⃣ permission.ts路由拦截器,这里面使用到了nprogress顶部加载效果

import router from '@/router'
// @ts-ignore
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'

NProgress.configure({
    easing: 'ease', // 动画方式
    showSpinner: true, // 是否显示加载ico
    trickleSpeed: 200, // 自动递增间隔
    minimum: 0.4, // 更改启动时使用的最小百分比
})

const whiteList = ['/login', '/redirect']

router.beforeEach((to, form, next) => {
    // 这里处理自己的逻辑,比如需要登录以后才能访问其他页面等等
    NProgress.start()
    next()
    NProgress.done()
})

4️⃣ src下main.ts 文件修改

import { createApp } from 'vue'

import App from './App.vue'
import 'animate.css'
import router from '@/router';
import '@/router/permission'
import 'element-plus/theme-chalk/dark/css-vars.css'

const app = createApp(App);

app.use(router)

app.mount('#app')

5️⃣ src下新建views文件夹,文件夹下新建home.vue和home1.vue两个文件

home.vue

<template>
  <div style="background: rgb(217, 217, 217);height: 100vh;width: 100%;display: flex;align-items: center;justify-content: center;">
    <el-button type="primary" @click="goHome">去home</el-button>
    <el-button type="primary" @click="changeCount">++++</el-button>
    <div style="color: red;font-size: 22px;">{{ count }}</div>
  </div>
</template>

<script lang="ts">
import {useRouter} from "vue-router";

export default defineComponent({
  setup() {

    const router = useRouter();

    let data = reactive({
      count: 1,
    })

    const changeCount = () => {
      data.count++
    }

    const goHome = () => {
      router.push({
        path: '/home1'
      })
    }

    return {
      changeCount,
      goHome,
      ...toRefs(data)
    }
  }
})
</script>

hom1.vue

<template>
  <div style="background: #ffffff;height: 100vh;width: 100%;display: flex;align-items: center;justify-content: center;">
    <el-button type="primary" @click="goHome1">回home</el-button>
    <el-button type="primary" @click="changeCount">++++</el-button>
    <div style="color: red;font-size: 22px;">{{ count }}</div>
  </div>
</template>

<script lang="ts">
import {useRouter} from "vue-router";

export default defineComponent({
  setup() {

    const router = useRouter();

    let data = reactive({
      count: 1,
    })

    const changeCount = () => {
      data.count++
    }

    const goHome1 = () => {
      router.push({
        path: '/'
      })
    }

    return {
      changeCount,
      goHome1,
      ...toRefs(data)
    }
  }
})
</script>

6️⃣ App.vue修改,这里就使用到了animate.css,给切换路由增加一些动画

<template>
  <router-view #default="{route, Component}">
    <transition leave-from-class="ts-web-fade--leave-to" enter-active-class="animate__animated animate__bounceInRight">
      <component :is="Component"></component>
    </transition>
  </router-view>
</template>

7️⃣ 项目目录

Vite4+Pinia2+vue-router4+ElmentPlus搭建Vue3项目(组件、图标等按需引入)[保姆级]

8️⃣ 最终的效果,可以看到切换路由的时候右上角有个圈圈在转动,因为截屏的原因,看不到顶部的加载条。还可以看到切换路由时的动画。

Vite4+Pinia2+vue-router4+ElmentPlus搭建Vue3项目(组件、图标等按需引入)[保姆级]

 :这里只是一个简单的搭建demo,所以拦截器没有做过多的扩展。我的另一篇文章有详细讲解动态路由的实现,但是建议先把本篇文章走完以后再去看。Vite4 + Vue3 + vue-router4 动态路由如果有问题的话可以联系我👉👉SH--TS。

伍、pinia状态管理 😱😱😱😱

为啥没有使用vuex而选择pinia来实现状态管理。相对于vuex来说,它更好的支持TypeScript、非常轻巧(体积约 1KB)等等优势。而且尤雨溪大佬也推荐使用。至于它俩如何做选择。可以根据自己的项目情况,如果是中小型项目的话推荐pinia。如果大规模、高复杂度的话就选vuex。

1️⃣ src文件夹下新建pinia,以及文件夹下新建index.ts等等。如下图

Vite4+Pinia2+vue-router4+ElmentPlus搭建Vue3项目(组件、图标等按需引入)[保姆级]

2️⃣ /pinia/modules/views.ts

import { defineStore } from 'pinia'

export interface IViewsState {
    count?: number
    title?: string
}

// 创建一个pinia, defineStore接受两个参数,第一个是id(唯一的)。参数二是配置项
export const viewsModule = defineStore('VIEWS',{
    state(): IViewsState {
        return {
            count: 1,
            title: 'Etc.End'
        }
    },
    //可以操作异步 和 同步提交state
    actions:{
        // 这里因为我的count定义的类型不是必有参数,所有它会存在空的情况.
        // 后面只需要加个!让编译器知道它不会未定义或不会为null
        // 也可以把上面的count?: number更改为count: number,下面就不用加!了
        incremental() {
            this.count!++
        },
        getCount() {
            return this.count
        }
    },
    // 类似于computed 可以帮我们去修饰我们的值
    getters:{
        newCount ():number | string {
            return this.count = 0
        },
        newTitle ():string {
            return `$-${this.title}`
        }
    },
})

3️⃣ /pinia/index.ts

import { viewsModule } from './modules/views';

export interface IAppStore {
    viewsModule: ReturnType<typeof viewsModule>;
}

const appStore: IAppStore = {} as IAppStore;

export const registerStore = () => {
    appStore.viewsModule = viewsModule();
};

export default appStore;

4️⃣ main.ts

import { createApp } from 'vue'

import App from './App.vue'
import 'animate.css'
import { createPinia } from 'pinia';
import { registerStore } from '@/pinia';
import router from '@/router';
import '@/router/permission'
import 'element-plus/theme-chalk/dark/css-vars.css'

const app = createApp(App);

app.use(router)
app.use(createPinia())
// 这里是进行一个注册,不然的话页面上是拿不到值的
registerStore()

app.mount('#app')

5️⃣ 修改之前的home.vue页面

<template>
  <div style="background: rgb(217, 217, 217);height: 100vh;width: 100%;padding-top: 100px;">
    <div style="text-align: center;margin-top: 50px;">
      <el-button type="primary" @click="goHome">去home1</el-button>
    </div>
    <div style="text-align: center;margin-top: 50px;">
      <el-button type="primary" @click="directChange">直接修改count的值</el-button>
      <el-button type="primary" @click="batchChange">批量修改pinia的值</el-button>
      <el-button type="primary" @click="callAction">actions修改pinia的值</el-button>
    </div>
    <div style="text-align: center;margin-top: 50px;color: red;font-size: 22px;">
      <div>{{ count }}</div>
      <div>{{ title }}</div>
    </div>
  </div>
</template>

<script lang="ts">
import {useRouter} from "vue-router";
import { storeToRefs } from 'pinia';
import appStore from '@/pinia';

export default defineComponent({
  setup() {

    const router = useRouter();

    // 这里是个小知识点,因为pinia不允许直接解构,比如下面
    // const { count, title } = appStore.viewsModule
    // 这样写的话会失去响应式,所以得使用storeToRefs
    const { count, title } = storeToRefs(appStore.viewsModule)

    // 直接修改views里面的count值
    const directChange = () => {
      appStore.viewsModule.count!++
    }

    // 批量修改views的值
    const batchChange = () => {
      appStore.viewsModule.$patch({
        count: 100,
        title: 'Etc-End'
      })
      // 还可以这样写,和上面一样的效果
      // appStore.viewsModule.$state = {
      //   count: 100,
      //   title: 'Etc-End'
      // }
    }

    const callAction = () => {
      appStore.viewsModule.incremental()
    }

    const goHome = () => {
      router.push({
        path: '/home1'
      })
    }

    return {
      directChange,
      batchChange,
      callAction,
      goHome,
      count,
      title
    }
  }
})
</script>

6️⃣ 修改之前的home1.vue页面

<template>
  <div style="background: rgb(217, 217, 217);height: 100vh;width: 100%;padding-top: 100px;">
    <div style="text-align: center;margin-top: 50px;">
      <el-button type="primary" @click="goHome">回home</el-button>
    </div>
    <div style="text-align: center;margin-top: 50px;">
      <el-button type="primary" @click="directChange">直接修改count的值</el-button>
      <el-button type="primary" @click="batchChange">批量修改pinia的值</el-button>
      <el-button type="primary" @click="callAction">actions修改pinia的值</el-button>
    </div>
    <div style="text-align: center;margin-top: 50px;color: red;font-size: 22px;">
      <div>{{ count }}</div>
      <div>{{ title }}</div>
    </div>
  </div>
</template>

<script lang="ts">
import {useRouter} from "vue-router";
import { storeToRefs } from 'pinia';
import appStore from '@/pinia';

export default defineComponent({
  setup() {

    const router = useRouter();

    // 这里是个小知识点,因为pinia不允许直接解构,比如下面
    // const { count, title } = appStore.viewsModule
    // 这样写的话会失去响应式,所以得使用storeToRefs
    const { count, title } = storeToRefs(appStore.viewsModule)

    // 直接修改views里面的count值
    const directChange = () => {
      appStore.viewsModule.count!++
    }

    // 批量修改views的值
    const batchChange = () => {
      appStore.viewsModule.$patch({
        count: 100,
        title: 'Etc-End'
      })
      // 还可以这样写,和上面一样的效果
      // appStore.viewsModule.$state = {
      //   count: 100,
      //   title: 'Etc-End'
      // }
    }

    const callAction = () => {
      appStore.viewsModule.incremental()
    }

    const goHome = () => {
      router.push({
        path: '/'
      })
    }

    return {
      directChange,
      batchChange,
      callAction,
      goHome,
      count,
      title
    }
  }
})
</script>

7️⃣ 最终效果,下图中可以看到,状态管理已经到达效果。切换路由后,拿到的count和title值都是更改后的。

Vite4+Pinia2+vue-router4+ElmentPlus搭建Vue3项目(组件、图标等按需引入)[保姆级]

 注:切换路由是没有问题,但页面刷新状态就会丢失。解决这个问题的话也很简单,搭配localStorage写一个插件就可以达到持久化。这里就不做演示了,自行研究一下。

陆、国际化

Vite4 + Vue3 + ElementPlus 实现国际化包括表单校验(超详细)

我是Etc.End。如果文章对你有所帮助,能否帮我点个免费的赞和收藏😍。

Vite4+Pinia2+vue-router4+ElmentPlus搭建Vue3项目(组件、图标等按需引入)[保姆级]

👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇文章来源地址https://www.toymoban.com/news/detail-418790.html

到了这里,关于Vite4+Pinia2+vue-router4+ElmentPlus搭建Vue3项目(组件、图标等按需引入)[保姆级]的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • vite + vue3 + vue-router4 + ts + element plus + pinia + axios构建项目

    最后是完整的vite.config.ts、main.ts配置 1、先用vite创建一个项目 2、安装element plus vite.config.ts配置组件按需导入,图标自动导入   main.ts配置 页面文件使用 3、安装axios main.ts 4、安装pinia /stores/index.ts /stores/counter.ts main.ts 页面使用 5、安装router4 /router/index main.ts   6、vite.config.ts常

    2023年04月25日
    浏览(46)
  • Vite4+Typescript+Vue3+Pinia 从零搭建(3) - vite配置

    项目代码同步至码云 weiz-vue3-template 关于vite的详细配置可查看 vite官方文档,本文简单介绍vite的常用配置。 项目初建后, vite.config.ts 的默认内容如下: 比如,修改 App.vue : 根目录下新建 .env 、 .env.development 、 .env.production 三个文件。 .env 文件内新增内容: .env.development 文件内

    2024年02月05日
    浏览(88)
  • Vite4+Typescript+Vue3+Pinia 从零搭建(4) - 代码规范

    项目代码同步至码云 weiz-vue3-template 要求代码规范,主要是为了提高多人协同和代码维护效率,结合到此项目,具体工作就是为项目配置 eslint 和 prettier 。 安装 EditorConfig for VS Code 插件,根目录下新建 .editorconfig 文件,增加以下配置 如果是非windows系统, end_of_line 设置为 cr 安

    2024年02月05日
    浏览(91)
  • Vite4+Typescript+Vue3+Pinia 从零搭建(2) - ts配置

    项目代码同步至码云 weiz-vue3-template 关于tsconfig的配置字段可查看其他文档,如 typeScript tsconfig配置详解 文件修改如下: 修改文件如下: 新建文件夹 types ,用来存放类型定义。比如新建 index.d.ts : 后续也可以新增其他文件,比如 global.d.ts 存放全局定义, router.d.ts 存放路由定

    2024年02月05日
    浏览(70)
  • Vite4+Typescript+Vue3+Pinia 从零搭建(7) - request封装

    项目代码同步至码云 weiz-vue3-template 基于 axios 封装请求,支持多域名请求地址 utils 目录下新建 request 文件夹,并新建 index.ts 、 request.ts 和 status.ts 文件。 此时,eslint会报 switch 前面的空格错误,需要修改 .eslintrc.cjs 里的 indent ,修改后,错误消失。 src 目录下新建 api 文件夹,

    2024年02月04日
    浏览(78)
  • Vite4+Typescript+Vue3+Pinia 从零搭建(6) - 状态管理pina

    项目代码同步至码云 weiz-vue3-template pina 是 vue3 官方推荐的状态管理库,由 Vue 核心团队维护,旨在替代 vuex。pina 的更多介绍,可从 pina官网 查看 更简洁直接的 API,提供组合式风格的 API 支持模块热更新和服务端渲染 对TS支持更为友好 src目录下新建store文件夹,并新建index.t

    2024年02月05日
    浏览(70)
  • Vue3+vite搭建基础架构(6)--- 使用vue-router

    这里记录下自己在Vue3+vite的项目使用vue-router的过程,不使用ts语法,方便以后直接使用。这里承接自己的博客Vue3+vite搭建基础架构(5)— 使用vue-i18n这篇博客,在该博客项目的基础上增加使用vue-router。 Vue3使用vue-router官方文档:https://router.vuejs.org/zh/installation.html 根据官网给

    2024年02月21日
    浏览(44)
  • 搭建vue3,TypeScript,pinia,scss,element-plus,axios,echarts,vue-router,babylon,eslint,babel,拖拽,rem自适应大屏

    1.1、使用vite初始化项目 1.1.1、创建项目文件夹 1.1.2、进入项目文件夹 1.1.3、初始化项目 1.1.4、输入项目名称 1.1.5、选择vue 1.1.6、选择TypeScript 1.1.7、查看当前源(非必要) 1.1.8、更换为国内镜像(非必要) 1.1.9、进入项目 1.1.10、安装依赖 1.1.11、运行项目 1.1.12、修改部分报错信息

    2024年04月23日
    浏览(48)
  • Vite-Admin后台管理系统|vite4+vue3+pinia前端后台框架实例

    基于 vite4.x+vue3+pinia 前端后台管理系统解决方案 ViteAdmin 。 前段时间分享了一篇vue3自研pc端UI组件库VEPlus。这次带来最新开发的基于 vite4+vue3+pinia 技术栈搭配ve-plus组件库构建的中后台权限管理系统框架。 支持vue-i18n国际化多语言、动态路由鉴权、4种布局模板及tab页面缓存 等功

    2023年04月13日
    浏览(76)
  • vue3 一个基于pinia简单易懂的系统权限管理实现方案,vue-router动态路由异步问题解决

    作为项目经验稀少的vue开发者来说,在关键技术点上的经验不多,我希望通过我的思想和实践,把好的东西分享在这里,目的是进一步促进技术交流。项目即将完成,权限是最后的收尾工作,好的权限实现方案,可以让我们没有后顾之忧,也可以提升项目的运行速度。 在开发

    2023年04月08日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包