从0开始搭建vue3+vite+ts+pinia项目

news2024/11/16 16:00:58

目录

项目搭建选项

项目搭建步骤

本地开发环境

Vite脚手架构建项目

关联Git仓库

开发工具

安装pinia

安装Sass

安装Vant-UI

安装postcss-pxtorem(移动端项目)

安装axios

本地调试

环境变量

本地代理

全局UI组件

路由中间件

项目部署

nginx配置

jenkins自动化部署

自由风格配置

流水线配置

灰度部署方案


项目搭建选项

  • Vue3
  • Vite
  • TypeScript
  • axios
  • Pinia
  • Sass
  • Vant-UI(M)、Element-UI(PC)
  • Eslint
  • postcss-pxtorem(M)

项目搭建步骤

本地开发环境

安装nodejs,node版本建议大于16.0.0

Download | Node.js

Vite脚手架构建项目

官网:https://cn.vitejs.dev/guide/

关联Git仓库

初始化后的项目关联远程git仓库

开发工具

Visual Studio Code

配置.vscode/setting.json,自动校验eslint并修复

{
  // 开启保存自动格式化
  "editor.formatOnSave": true,
  // 开启eslint校验
  "eslint.enable": true,
  "recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"],
  "editor.fontSize": 14,
  // vscode默认启用了根据文件类型自动设置tabsize的选项
  "editor.detectIndentation": false,
  // 重新设定tabsize
  "editor.tabSize": 2,
  // #每次保存的时候将代码按eslint格式进行修复
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  },
  // 校验文件类型
  "eslint.validate": ["html", "vue", "javascript", "jsx"],
  //  #让prettier使用eslint的代码格式进行校验
  "prettier.eslintIntegration": true,
  //  #去掉代码结尾的分号
  "prettier.semi": true,
  //  #使用带引号替代双引号
  "prettier.singleQuote": true,
  //  #让函数(名)和后面的括号之间加个空格
  "javascript.format.insertSpaceBeforeFunctionParenthesis": true,
  // #让vue中的js按编辑器自带的ts格式进行格式化
  "vetur.format.defaultFormatter.js": "vscode-typescript",
  "vetur.format.defaultFormatterOptions": {
    "js-beautify-html": {
      "wrap_attributes": "force-aligned"
      // #vue组件中html代码格式化样式
    },
    "prettier": {
      "semi": false,
      "singleQuote": true,
      "eslintIntegration": true,
      "stylelintIntegration": true,
      "tabWidth": 2,
      "vetur.format.defaultFormatter.html": "prettier"
    }
  },
  "explorer.confirmDelete": false,
  "explorer.confirmDragAndDrop": false,
  "editor.renderControlCharacters": true,
  // "editor.renderWhitespace": "all",
  "files.associations": {
    "*.cjson": "jsonc",
    "*.wxss": "css",
    "*.wxs": "javascript"
  },
  "emmet.includeLanguages": {
    "wxml": "html"
  },
  "minapp-vscode.disableAutoConfig": true,
  "bald.config": false,
  "files.autoSave": "off",
  "diffEditor.ignoreTrimWhitespace": false,
  "editor.foldingStrategy": "indentation",
  "git.path": "",
  "editor.foldingMaximumRegions": 50000,
  "security.workspace.trust.untrustedFiles": "newWindow",
  "editor.unicodeHighlight.nonBasicASCII": false,
  // 以下是格式化插件配置
  "[html]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[less]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[vue]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[typescript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[javascript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[json]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[css]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[scss]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[jsonc]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  }
}

安装pinia与持久化封装

官网:安装 | Pinia 中文文档

项目构建时已选择安装pinia,下面是使用方法以及持久化存储配置

官网:快速开始 | pinia-plugin-persistedstate

1、安装持久化存储插件 pinia-plugin-persistedstate

npm i pinia-plugin-persistedstate -S

2、main.ts

import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'

const app = createApp(App)

const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)

app.use(pinia)
app.mount('#app')

3、在/src/store/目录下新建user.ts

import { defineStore } from 'pinia'

export const useUserStore = defineStore('user', {
  state: () => ({
    name: 'Tom', // 用户名
    age: 18, // 年龄
    weight: 60 // 公斤
  }),
  getters: {
    // 获取体重市斤
    getWeight: (state) => {
      return state.weight * 2
    }
  },
  actions: {
    // 修改用户名
    changeUserName(name: string) {
      this.name = name
    }
  },
  // 持久化插件配置
  persist: {
    key: 'store-user', // 本地存储key名称
    // storage: sessionStorage // 不设置默认存储localStorage
    paths: ['name'] // 指定持久化的值
  }
})

4、页面调用

<template>
  <div>
    <p>pinia-name: {{ name }}</p>
    <p>pinia-age: {{ age }}</p>
    <p>pinia-市斤: {{ storeUser.getWeight }}</p>
    <button @click="changeName">修改用户名称</button>
    <button @click="changeUser">批量修改</button>
    <button @click="changeNameFun">修改用户名称方法</button>
  </div>
</template>

<script setup lang="ts">
import { useUserStore } from '../store/user'
import { storeToRefs } from 'pinia';
const storeUser = useUserStore()
const { name, age } = storeToRefs(storeUser) // 将pinia的值响应式

// 单个修改state
const changeName = () => {
  storeUser.name = 'Jack'
}
// 批量修改
const changeUser = () => {
  storeUser.$patch({
    name: 'LiuTao',
    age: 10,
    weight: 80
  })
}
// 调用action
const changeNameFun = ()=> {
  storeUser.changeUserName('Alex')
}
</script>

安装Sass

npm i sass -D

使用

<style lang="scss">
</style>

安装Vant-UI

官网:Vant 4 - A lightweight, customizable Vue UI library for mobile web apps.

npm i vant -S

安装postcss-pxtorem(移动端项目)

移动端适配,兼容不同分辨率的手机

npm i postcss-pxtorem amfe-flexible -D

修改vite.config.ts

import postCssPxToRem from 'postcss-pxtorem'
export default defineConfig({
  ...
  css: {
    postcss: {
      plugins: [
        postCssPxToRem({
          rootValue: 75, // 1rem的大小
          propList: ['*'], // 需要转换的属性,这里选择全部都进行转换
          minPixelValue: 2 // 最小px为2,如果设置1px则不转rem
        })
      ]
    }
  }
  ...
})

在main.ts引入amfe-flexible

import 'amfe-flexible'

安装axios与请求封装

官网:axios

npm i axios -S

封装axios方法,新建/src/utils/request.ts文件

import axios from 'axios'
import type { AxiosInstance, AxiosError, AxiosResponse } from 'axios'
import { showToast } from 'vant'

const service: AxiosInstance = axios.create({
  // import.meta.env.DEV 判断是否为本地环境
  baseURL: import.meta.env.DEV ? '/api' : 'http://www.baidu.com',
  timeout: 30000
})

/* 请求拦截器 */
service.interceptors.request.use(
  (config) => {
    // 登录状态鉴权
    // if (token) {
    //   config.headers.Authorization = `Bearer ${token}`;
    // }
    return config
  },
  (error: AxiosError) => {
    showToast(error.message)
    return Promise.reject(error)
  }
)

/* 响应拦截器 */
service.interceptors.response.use(
  (response: AxiosResponse) => {
    const { code, message, data } = response.data
    // 根据自定义错误码判断请求是否成功
    if (code === '0') {
      // 将组件用的数据返回
      return data
    } else {
      // 处理业务错误。
      showToast(message)
      return Promise.reject(new Error(message))
    }
  },
  (error: AxiosError) => {
    // 处理 HTTP 网络错误
    let message = ''
    // HTTP 状态码
    const status = error.response?.status
    switch (status) {
      case 401:
        message = 'token 失效,请重新登录'
        // 这里可以触发退出的 action
        break
      case 403:
        message = '拒绝访问'
        break
      case 404:
        message = '请求地址错误'
        break
      case 500:
        message = '服务器故障'
        break
      default:
        message = '网络连接故障'
    }

    showToast(message)
    return Promise.reject(error)
  }
)

/* 导出封装的请求方法 */
export const http = (options: any) => {
  return new Promise((resolve, reject) => {
    // 方法一:get和delete请求,将请求体转换为queryString形式拼接在url
    // if (!options.method || options.method === 'get' || options.method === 'delete') {
    //   if (options.data) {
    //     options.url = options.url + '?' + new URLSearchParams(options.data).toString()
    //   }
    // }

    // 方法二:get和delete请求,使用params参数传参,post和put使用data参数
    const serviceOpt: any = {}
    if (!options.method || options.method === 'get' || options.method === 'delete') {
      serviceOpt.params = options.data
    } else {
      serviceOpt.data = options.data
    }
    service({
      method: options.method || 'get',
      url: options.url,
      ...serviceOpt
    })
      .then((res) => {
        resolve(res)
      })
      .catch((err) => {
        reject(err)
      })
  })
}

将封装的http方法绑定到全局变量

打开/src/mian.ts

import { http } from '@/utils/request'

app.config.globalProperties.$http = http

在vue文件使用

<script setup lang="ts">
import { onMounted, getCurrentInstance } from 'vue'
const { proxy: { $http } } = getCurrentInstance() as any
onMounted (async() => {
  const res: object = await $http({
    url: '/get/product/list',
    // method: 'get',
    data: {
      id: 1
    }
  })
  console.log(res)
})
</script>

本地调试

npm run dev执行后,只显示了Local: http://localhost:5173/,没有显示局域网ip地址,不方便局域网真机调试,需要配置启动host为0.0.0.0

打开vite.config.ts

export default defineConfig({
  server: {
    // port: 8080, // 启动端口号
    host: '0.0.0.0' // 启动显示局域网ip
  }
})

测试环境真机调试请参考:

H5移动端调试工具_不求甚解bc的博客-CSDN博客

环境变量

1、获取系统环境变量

import.meta.env.DEV // 开发环境:true
import.meta.env.PROD // 生产环境:true
import.meta.env.MODE // 开发环境:development  生产环境:production
...

2、获取命令行自定义环境变量

npm run dev --env=test

打开vite.config.ts

const env = process.env.npm_config_env || 'dev'
export default defineConfig({
  define: {
    app_env: JSON.stringify(env)
  }
})

在项目代码中使用,比如main.ts / index.vue

console.log(app_env) // 打印结果:test

注意:直接使用环境变量会提示变量未声明,需要在 env.d.ts 或 vite-env.d.ts 文件中添加类型声明

declare const app_env: string

本地代理

vite.config.ts

export default defineConfig({
  server: {
    proxy: {
      // 带选项写法:http://localhost:5173/api/bar -> http://jsonplaceholder.typicode.com/bar
      '/api': {
        target: 'http://jsonplaceholder.typicode.com',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, '')
      }
    }
  }
})

全局UI组件

vue3全局api组件_vue3 全局弹窗_不求甚解bc的博客-CSDN博客

路由中间件

vue路由中间件_不求甚解bc的博客-CSDN博客

项目部署

nginx配置

Apache,Nginx部署vue/react项目_apached发布 react_不求甚解bc的博客-CSDN博客

jenkins自动化部署

自由风格配置

jenkins部署vue/react项目_jenkins部署vue项目_不求甚解bc的博客-CSDN博客

jenkins分环境部署vue/react项目_不求甚解bc的博客-CSDN博客

流水线配置

jenkins流水线部署H5项目_jenkins部署h5_不求甚解bc的博客-CSDN博客

灰度部署方案

web前端灰度部署_不求甚解bc的博客-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/612120.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VTK-vtkInformation

前言&#xff1a;本博文主要介绍vtk中的接口vtkInformation的应用&#xff0c;以及vtkInformation的衍生用法&#xff0c;希望对各位小伙伴有所帮助&#xff0c;谢谢&#xff01; 目录 vtkInformation介绍 描述&#xff1a; Information中接受的类型&#xff1a; 方法 vtk…

数据结构与算法系列之堆排序

&#x1f497; &#x1f497; 博客:小怡同学 &#x1f497; &#x1f497; 个人简介:编程小萌新 &#x1f497; &#x1f497; 如果博客对大家有用的话&#xff0c;请点赞关注再收藏 &#x1f31e; 堆的概念和结构 如果有一个关键码的集合K { &#xff0c; &#xff0c; &…

关于万物悦享推广案例

关于万物悦享推广案例 项目介绍 万物悦享是一家改变传统消费模式的公司&#xff0c;致力于让消费者在衣食住行都能把消费变成开心享受的事情。该公司通过消费增值、绿色积分、12倍通证强制出局、卷轴和撸实现这一目标。在通证经济下&#xff0c;消费者可以通过获得通证再赚回…

容器技术 — Cgroups 与 Namespaces 支撑实现的操作系统虚拟化

目录 文章目录 目录操作系统虚拟化&#xff08;容器技术&#xff09;的发展历程ChrootCgroupsCgroup SubsystemsCgroup FilesystemCgroup HierarchyCgroups 的操作规则Cgroups 的代码实现 NamespacesUTS namespacePID namespaceIPC namespaceMount namespaceNetwork namespaceU…

Blender2023超好用的插件合集,还不抓紧用起来

Blender对于艺术家或电影制作人来说不再是一个陌生的名字。Blender 拥有一套全面的工具和一个用户友好的界面&#xff0c;使初学者和专业人士都可以使用它。全球开发人员和用户社区不断更新新功能和改进。此外&#xff0c;有这么多可用的工具和插件&#xff0c;Blender可以定制…

项目经理高效时间管理6大原则及技巧

1、 ( 10 2 ) * 5法则 项目经理以10分钟为一个周期&#xff0c;每个周期休息2分钟&#xff0c;这样1小时重复5次&#xff0c;就可以保障我们目标明确但精神和身体上的精力不会透支。 10分钟周期内&#xff0c;需要全心全意做一件事&#xff0c;进入全身心投入工作状态&#xf…

Kerberos从入门到精通以及案例实操系列(二)

5、安全集群使用说明 5.1、用户要求 具体要求以下使用说明均基于普通用户&#xff0c;安全集群对用户有以下要求&#xff1a; 集群中的每个节点都需要创建该用户该用户需要属于hadoop用户组需要创建该用户对应的Kerberos主体 实操&#xff0c;此处以atguigu用户为例&#x…

Spring Boot 系统初始化器详解

Spring Boot 3.x系列文章 Spring Boot 2.7.8 中文参考指南(一)Spring Boot 2.7.8 中文参考指南(二)-WebSpring Boot 源码阅读初始化环境搭建Spring Boot 框架整体启动流程详解Spring Boot 系统初始化器详解 自定义系统初始化器 Spring Boot 有多种加载自定义初始化器的方法&am…

账号长久不用、归属不明......企业要如何管理这些失控的账号?

据报道&#xff0c;谷歌将于今年底开始删除2年未使用个谷歌个人账号。理由是&#xff0c;谷歌发现&#xff0c;如果一个账户在一定时间内未被使用&#xff0c;那么该账户被入侵的概率更大。 这些长时间未使用的账号使用的密码一般都是比较老的或重用的密码&#xff0c;关联密码…

Linux之tar归档命令

目录 Linux之tar归档命令 定义 语法格式 参数及作用 常用选项 创建&#xff08;非压缩的&#xff09;包文件 ​编辑 创建带压缩的包文件 列出包文件中的文件列表 提取包文件到指定目录 tar打包时排除 --exclude -X或--exclude-from Linux之tar归档命令 定义 用于打…

全面的软件测试

1 全过程的软件测试图解 传统的软件测试&#xff0c;开发人员完成任务之后&#xff0c;最后交付给测试人员&#xff0c;这种模式下&#xff0c;测试人员不能及早发现需求阶段的缺陷&#xff0c;同时测试工作的开展也滞后了&#xff0c;产品质量得不到有效的过程控制和分析&…

echarts折线图使用记录

1项目中引入echarts文档api介绍&#xff0c;链接地址如下 https://echarts.apache.org/handbook/zh/basics/import 2 官网基础样例介绍,链接地址如下 https://echarts.apache.org/handbook/zh/get-started/ 3 基本折线图介绍内容及链接 3.1 最简单的折线图 3.2 笛卡尔坐标系中…

【Python】Step Into Python Class

【Python】Step Into Python Class Before All Python作为一门面向过程兼容面向对象的语言&#xff0c;在面向对象中&#xff0c;使用class关键字来申明一个类。 But&#xff0c;是不是应该深入考虑一下这个class的底层实现过程呢&#xff1f;&#xff08;不考虑CPython&…

msvcp110.dll丢失怎么修复(一键修复办法)

msvcp110.dll是C编程中非常重要的库文件之一。它实现了运行时库的大部分功能&#xff0c;并提供了许多标准库和其他功能的具体实现&#xff0c;如多线程编程和IO操作等。提高程序的运行效率和稳定性。下面是详细解决msvcp110.dll丢失问题的方法跟msvcp110.dll文件的介绍。 msvc…

npm install报错 -> npm ERR! Unexpected token ‘.‘ 报错解决办法

原因&#xff1a; 我遇到这个问题的场景是用nvm1.1.7的版本安装了16.x以上的node, 然后再下载依赖的时候就报错了 总结一下就是nvm版本太低了&#xff0c;他的里面没有集成高版本node导致的 解决&#xff1a; 我们把nvm版本换到最新的就可以了 1. 卸载掉当前所有的node nvm …

ABIDE Preprocessed 结构态MRI数据集介绍及下载

ABIDE数据集介绍及下载 ABIDE Prerocessed项目是在ABIDE I 项目的基础上发展而来&#xff0c;主要是对ABIDE I中采集到的原始数据进行了一定的预处理和初步的特征提取。针对于fMRI和sMRI数据有着不同的处理方式&#xff0c;本次主要对其中提供的sMRI预处理结果进行介绍&#xf…

Python程序设计基础:标识符、变量与赋值、输入输出

文章目录 一、标识符二、变量与赋值三、输入输出 一、标识符 Python对每个标识符的命名存在要求&#xff1a; 1、每个标识符必须以字母或下划线“_”开头&#xff0c;后跟字母、数字或下划线的任意序列。根据这个规则&#xff0c;以下都是Python中的合法名称&#xff1a;a&…

excel如何实现识别文本在对应单元格填上数据?

要实现 Excel 识别文本在对应单元格填上数据&#xff0c;有以下两种方法&#xff1a; 方法一&#xff1a;使用 VLOOKUP 函数 1. 在 Excel 工作表中&#xff0c;输入一个表格&#xff0c;列名为对应的文本&#xff0c;行名为不同条目。 2. 准备输入数据&#xff0c;在一个新的…

python使用requests+excel进行接口自动化测试

在当今的互联网时代中&#xff0c;接口自动化测试越来越成为软件测试的重要组成部分。Python是一种简单易学&#xff0c;高效且可扩展的语言&#xff0c;自然而然地成为了开发人员的首选开发语言。而requests和xlwt这两个常用的Python标准库&#xff0c;能够帮助我们轻松地开发…

LInux之find查找

目录 LInux之find查找 定义 详解 格式 参数及作用 详解 1.按照文件名搜索 2.按照文件大小搜索 3.按照修改时间搜索 4.按照权限搜索 5.按照所有者和所属组搜索 6.按照文件类型搜索 7.逻辑运算符 8.其他选项 -exec参数 获取到该目录中所有以host开头的文件列表 如在…