百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

Vu3+Ts+Vite2+Pinia 搭建开发脚手架

toyiye 2024-06-28 10:04 23 浏览 0 评论

一、使用vite快速创建脚手架

1.使用yarn运行安装命令

#yarn命令安装
yarn create @vitejs/app vue3_ts_vite_pinia

2.选择vue vue-ts 完成安装

3.进入vue3_ts_vite_pinia项目,使用yarn命令安装依赖,依赖安装完成后,使用yarn dev启动项目

#安装依赖 yarn
#启动项目 yarn dev

二、路由配置(vue-router@4)

基本配置

1.使用yarn安装vue-router@4

#yarn命令安装
yarn add vue-router@4

2.src文件夹下新建router文件夹,router文件夹下新建index.ts


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

const routes: RouteRecordRaw[] = [
    {
        path: '/',
        name: 'Index',
        component: () => import('@/pages/index/Index.vue'),
    }
]
const router = createRouter({
    history: createWebHistory(),
    routes,
})

export default router


注:RouteRecordRaw为内置类型

3.在main.ts中,引入router并注册

import { createApp } from 'vue'
import App from './App.vue'
import router from './router/index'
const app = createApp(App)
app.use(router)
app.mount('#app')

4.在App.vue中设置路由展现出口 <router-view></router-view>

<template>
    // <img alt="Vue logo" src="./assets/logo.png" />
    // <HelloWorld msg="Hello Vue 3 + TypeScript + Vite" />
    <router-view></router-view>
</template>

路由守卫

1.路由守卫,告别next,在router/index.ts中添加全局路由守卫

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

const routes: RouteRecordRaw[] = [
    {
        path: '/',
        name: 'Index',
        component: () => import('@/pages/index/Index.vue'),
    }
]
const router = createRouter({
    history: createWebHistory(),
    routes,
})
router.beforeEach((to,from)=>{
        if(pass){
        console.log('pass')
          // 不再使用next()放行
        }else{
            return false 
        }
})
export default router

2.组件内路由守卫

新增组合式api可以替代原有的组件内守卫,onBeforeRouteLeave(离开当前页面路由时触发)、onBeforeRouteUpdate(路由更新时触发)

onBeforeRouteLeave((to,form)=>{
          
})

页面使用

// 跳转
import { useRouter,useRoute } from 'vue-router';
 const go=()=>{
     const Router=useRouter()
     const Route=useRoute()
     Router.push({
         name:'/login',
         query:{
             id:'123456'
         }
     })
 }

三、状态管理(Pinia配置)

Pinia 是 Vue.js 的轻量级状态管理库,也是Vue核心团队推荐的状态管理库,由于Pinia也是Vuex研发团队的产品,以及尤大大的加持,极大可能会替代Vuex,即使pinia的推广不太顺利也并不用过多担心,其许多使用方式很有可能会移植到Vuex5中。相较于Vuex,Pinia上手更简单,mutations,并且actions支持同步或异步。

基本配置

1.使用yarn安装 pinia@next

#yarn命令安装
yarn add pinia@next

2.src文件夹下新建store文件夹,store文件夹下新建main.ts

import { defineStore } from 'pinia'

export const useUserStore = defineStore({
    id: 'user',
    state: () => ({
        name: '用户名'
    }),
    getters: {
        nameLength: (state) => state.name.length,
    },
    actions: {
        updataUser(data: any) {
            console.log(data)
        }
    }
})

3.在main.ts中,引入createPinia


import { createApp } from 'vue'
import App from './App.vue'
import router from './router/index'
import { createPinia } from 'pinia'
const app = createApp(App)
app.use(createPinia())
app.use(router)
app.mount('#app')

基本使用

1.获取state

  • 直接获取
<template>
    <div>{{userStore.name}}</div>
</template>
<script setup lang="ts">
import { useUserStore } from "@/store/user.ts"
const userStore = useUserStore()

</script>

  • computed获取
<template>
    <div>{{name}}</div>
</template>
<script setup lang="ts">
import { useUserStore } from "@/store/user.ts"
const userStore = useUserStore()
const name=computed(()=>{
    userStore.name
})
</script>

  • 结构获取,但会失去响应式,需要使用storeToRefs
<template>
    <div>{{name}}</div>
</template>
<script setup lang="ts">
import { useUserStore } from "@/store/user.ts"
import {storeToRefs} from 'pinia'
const userStore = useUserStore()
const name=storeToRefs(userStore)
</script>

2.设置state

  • 直接修改
<template>
    <div>{{userStore.name}}</div>
    <div @click="updateName">修改名字</div>
</template>
<script setup lang="ts">
import { useUserStore } from "@/store/user.ts"
const userStore = useUserStore()
const updateName = () => {
    userStore.name = '直接修改后名字'
}
</script>

  • $patch 修改 store 中的数据
<template>
    <div>{{userStore.name}}</div>
    <div @click="updateName">修改名字</div>
</template>
<script setup lang="ts">
import { useUserStore } from "@/store/user.ts"
const userStore = useUserStore()
const updateName = () => {
    userStore.$patch({
       name: '$patch修改后名字'
   })
}
</script>

  • actions 修改 store 中的数据
<template>
    <div>{{userStore.name}}</div>
    <div @click="updateName">修改名字</div>
</template>
<script setup lang="ts">
import { useUserStore } from "@/store/user.ts"
const userStore = useUserStore()
const updateName = () => {
    userStore.updataUser('actions修改后名字')
}
</script>

actions中使用this修改state数据

import { defineStore } from 'pinia'

export const useUserStore = defineStore({
    id: 'user',
    state: () => ({
        name: '用户名'
    }),
    getters: {
        nameLength: (state) => state.name.length,
    },
    actions: {
        updataUser(newName: string) {
           this.name=newName
        }
    }
})

3.Getters使用

import { defineStore } from 'pinia'

export const useUserStore = defineStore({
    id: 'user',
    state: () => ({
        name: '用户名'
    }),
    getters: {
        nameLength: (state) => state.name.length,
    },
})

<template>
    <div>{{userStore.nameLength}}</div>
</template>

4.Actions使用

  • 同步actions使用

如设置state中使用方式相同,可以直接使用this设置state中数据

  • 异步actions使用

支持async await ,支持同一个store中action之间可以用this调用,不同store中action之间可以用hooks引入方式调用

import { defineStore } from 'pinia'
import {userOtherStore} from './otherStore'
export const useUserStore = defineStore({
    id: 'user',
    state: () => ({
        name: '用户名'
    }),
    actions: {
        async login(params){
            const {data}=await api.login(params)
            this.updataUser(data) //同一个store中action之间可以用this调用
        },
        updataUser(newName: string) {
           this.name=newName
           const otherStore=userOtherStore() //不同store中action之间可以用hooks引入方式调用
           otherStore.setName(newName)
        }
    }
}

四、统一请求封装(Axios封装)

1.使用yarn安装 axios

#yarn命令安装
yarn add axios

2.src文件夹下新建service文件夹,service文件夹下新建http.ts

import axios, { AxiosRequestConfig } from 'axios'
// 设置请求头和请求路径
axios.defaults.baseURL = '/api';
// 现在,所有使用此实例的请求都将等待2.5秒,然后才会超时
axios.defaults.timeout = 2500;
axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8';


// 添加请求拦截器
axios.interceptors.request.use(function (config): AxiosRequestConfig<any> {
    // 在发送请求之前做些什么
    config.headers.token = 'your token'
    return config;
}, function (error) {
    // 对请求错误做些什么
    return Promise.reject(error);
});

// 添加响应拦截器
axios.interceptors.response.use(function (response) {
    // 2xx 范围内的状态码都会触发该函数。
    // 对响应数据做点什么
    return response;
}, function (error) {
    // 超出 2xx 范围的状态码都会触发该函数。
    // 对响应错误做点什么
    return Promise.reject(error);
});
interface ResType<T> {
    code: number
    data?: T
    msg: string
    err?: string
}
interface Http {
    get<T>(url: string, params?: unknown): Promise<ResType<T>>
    post<T>(url: string, params?: unknown): Promise<ResType<T>>
    upload<T>(url: string, params: unknown): Promise<ResType<T>>
    download(url: string): void
}
const http: Http = {
    get(url, params) {
        return new Promise((resolve, reject) => {
            axios
                .get(url, { params })
                .then((res) => {
                    resolve(res.data)
                })
                .catch((err) => {
                    reject(err.data)
                })
        })
    },
    post(url, params) {
        return new Promise((resolve, reject) => {
            axios
                .post(url, JSON.stringify(params))
                .then((res) => {
                    resolve(res.data)
                })
                .catch((err) => {
                    reject(err.data)
                })
        })
    },
    upload(url, file) {
        return new Promise((resolve, reject) => {
            axios
                .post(url, file, {
                    headers: { 'Content-Type': 'multipart/form-data' },
                })
                .then((res) => {
                    resolve(res.data)
                })
                .catch((err) => {
                    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

3.service文件夹下新建api文件夹,做请求统一管理,api下新建login,login下新建login.ts、type.ts

  • login.ts
import http from '@/service/http'
import { ILoginApi } from './type'
const loginApi: ILoginApi = {
    login(params) {
        return http.post('/login', params)
    }
}

  • type.ts
  
export interface DataType {
    name: string
}
export interface ResType<T> {
    code: number
    data?: T
    msg: string
    err?: string
}
export interface ILoginApiParams {
    id: number
}
export interface ILoginApi {
    login: (params: ILoginApiParams) => Promise<ResType<DataType>>
}

五、UI组件库(Naive UI、Ant Design Vue、Element Plus)

UI组件库目前选择比较多,Naive UI是尤大大推荐的组件库,内容样式比较美观新颖,但毕竟是新组件库,Ant Design Vue是Ant Design 的 Vue 实现,用户人数较多,比较成熟,像一些目前比较厉害的开源后台vben-admin等都是使用Ant Design Vue,至于Element Plus也是刚刚开发完成,因此还是选择Ant Design Vue较为靠谱。

基本配置

1.使用yarn安装 ant-design-vue@next

#yarn命令安装
yarn add ant-design-vue@next

2.main.ts中全局注册

import { createApp } from 'vue'
import App from './App.vue'
import router from './router/index'
import { createPinia } from 'pinia'
import Antd from 'ant-design-vue';
import 'ant-design-vue/dist/antd.css';

const app = createApp(App)
app.use(createPinia())
app.use(router)
app.use(Antd);
app.mount('#app')

3.组件内使用

<template>
    <div :style="{ background: 'rgb(190, 200, 200)', padding: '26px 16px 16px' }">
        <a-button type="primary" ghost>Primary</a-button>
        <a-button ghost>Default</a-button>
        <a-button type="dashed" ghost>Dashed</a-button>
        <a-button danger ghost>Danger</a-button>
        <a-button type="link" ghost>Link</a-button>
    </div>
    <!-- <img alt="Vue logo" src="./assets/logo.png" />
    <HelloWorld msg="Hello Vue 3 + TypeScript + Vite" />-->
</template>

六、环境变量配置及vite基本配置

环境变量配置

1.最外层文件位置新建.env.development.env.production文件

  • .env.development
NODE_ENV=development

VITE_APP_WEB_URL= 'YOUR WEB URL'

  • .env.production
NODE_ENV=production

VITE_APP_WEB_URL= 'YOUR WEB URL'

2.组件内使用环境

console.log(import.meta.env.VITE_APP_WEB_URL)

Vite环境配置

1.配置类型别名

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'

// https://vitejs.dev/config/
export default defineConfig({
    plugins: [vue()],
    resolve: {
        alias: {
            '@': path.resolve(__dirname, 'src'),
        },
    },
    
})

如果path报错,安装@types/node即可

2.引入如scss等的全局样式

export default defineConfig({
    plugins: [vue()],
    css: {
        preprocessorOptions: {
            scss: {
                additionalData: '@import "@/assets/style/main.scss";'
            }
        }
    },
})

3.代理配置

server: {
      port: VITE_PORT,
      // Load proxy configuration from .env
      proxy: {},
    },

4.在预构建中强制排除的依赖项。

optimizeDeps: {
      // @iconify/iconify: The dependency is dynamically and virtually loaded by @purge-icons/generated, so it needs to be specified explicitly
      include: [
        '@iconify/iconify',
        'ant-design-vue/es/locale/zh_CN',
        'moment/dist/locale/zh-cn',
        'ant-design-vue/es/locale/en_US',
        'moment/dist/locale/eu',
      ],
      exclude: ['vue-demi'],
    },

5.build打包

 build: {
      target: 'es2015',
      outDir: OUTPUT_DIR,
      terserOptions: {
        compress: {
          keep_infinity: true,
          // 生产环境去除 `console` `debugger` 值为布尔值
          drop_console: VITE_DROP_CONSOLE, 
          drop_debugger: VITE_DROP_DEBUGGER 
        },
      },
      // Turning off brotliSize display can slightly reduce packaging time
      brotliSize: false,
      chunkSizeWarningLimit: 1500,
    },

更多配置可以阅读大神的文章 手撕vben-admin 里边对框架配置做了详细解读,特别是vite配置,可以收藏哦, 地址:https://www.kuxiaoxin.com/

参考资料

https://juejin.cn/user/1116759545088190,Vite2 + Vue3 + TypeScript + Pinia 搭建一套企业级的开发脚手架

文章来自:https://juejin.cn/post/7065135389798825998, @宜简,授权发布于公众号(前端晚间课)

相关推荐

# Python 3 # Python 3字典Dictionary(1)

Python3字典字典是另一种可变容器模型,且可存储任意类型对象。字典的每个键值(key=>value)对用冒号(:)分割,每个对之间用逗号(,)分割,整个字典包括在花括号({})中,格式如...

Python第八课:数据类型中的字典及其函数与方法

Python3字典字典是另一种可变容器模型,且可存储任意类型对象。字典的每个键值...

Python中字典详解(python 中字典)

字典是Python中使用键进行索引的重要数据结构。它们是无序的项序列(键值对),这意味着顺序不被保留。键是不可变的。与列表一样,字典的值可以保存异构数据,即整数、浮点、字符串、NaN、布尔值、列表、数...

Python3.9又更新了:dict内置新功能,正式版十月见面

机器之心报道参与:一鸣、JaminPython3.8的热乎劲还没过去,Python就又双叒叕要更新了。近日,3.9版本的第四个alpha版已经开源。从文档中,我们可以看到官方透露的对dic...

Python3 基本数据类型详解(python三种基本数据类型)

文章来源:加米谷大数据Python中的变量不需要声明。每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建。在Python中,变量就是变量,它没有类型,我们所说的"类型"是变...

一文掌握Python的字典(python字典用法大全)

字典是Python中最强大、最灵活的内置数据结构之一。它们允许存储键值对,从而实现高效的数据检索、操作和组织。本文深入探讨了字典,涵盖了它们的创建、操作和高级用法,以帮助中级Python开发...

超级完整|Python字典详解(python字典的方法或操作)

一、字典概述01字典的格式Python字典是一种可变容器模型,且可存储任意类型对象,如字符串、数字、元组等其他容器模型。字典的每个键值key=>value对用冒号:分割,每个对之间用逗号,...

Python3.9版本新特性:字典合并操作的详细解读

处于测试阶段的Python3.9版本中有一个新特性:我们在使用Python字典时,将能够编写出更可读、更紧凑的代码啦!Python版本你现在使用哪种版本的Python?3.7分?3.5分?还是2.7...

python 自学,字典3(一些例子)(python字典有哪些基本操作)

例子11;如何批量复制字典里的内容2;如何批量修改字典的内容3;如何批量修改字典里某些指定的内容...

Python3.9中的字典合并和更新,几乎影响了所有Python程序员

全文共2837字,预计学习时长9分钟Python3.9正在积极开发,并计划于今年10月发布。2月26日,开发团队发布了alpha4版本。该版本引入了新的合并(|)和更新(|=)运算符,这个新特性几乎...

Python3大字典:《Python3自学速查手册.pdf》限时下载中

最近有人会想了,2022了,想学Python晚不晚,学习python有前途吗?IT行业行业薪资高,发展前景好,是很多求职群里严重的香饽饽,而要进入这个高薪行业,也不是那么轻而易举的,拿信工专业的大学生...

python学习——字典(python字典基本操作)

字典Python的字典数据类型是基于hash散列算法实现的,采用键值对(key:value)的形式,根据key的值计算value的地址,具有非常快的查取和插入速度。但它是无序的,包含的元素个数不限,值...

324页清华教授撰写【Python 3 菜鸟查询手册】火了,小白入门字典

如何入门学习python...

Python3.9中的字典合并和更新,了解一下

全文共2837字,预计学习时长9分钟Python3.9正在积极开发,并计划于今年10月发布。2月26日,开发团队发布了alpha4版本。该版本引入了新的合并(|)和更新(|=)运算符,这个新特性几乎...

python3基础之字典(python中字典的基本操作)

字典和列表一样,也是python内置的一种数据结构。字典的结构如下图:列表用中括号[]把元素包起来,而字典是用大括号{}把元素包起来,只不过字典的每一个元素都包含键和值两部分。键和值是一一对应的...

取消回复欢迎 发表评论:

请填写验证码