【尚医通】vue3+ts前端项目开发笔记 2 —— 创建项目、封装网络请求、集成elment-plus 、重置样式、准备状态管理/路由 等开发前准备

news2024/9/19 15:26:16

尚医通开发记录(Vue3+TypeScript+Pinia+Axios)

一、接口地址

服务器地址:http://syt.atguigu.cn
医院接口:http://139.198.34.216:8201/swagger-ui.html
公共数据接口:http://139.198.34.216:8202/swagger-ui.html
会员接口:http://139.198.34.216:8203/swagger-ui.html
短信验证码接口:http://139.198.34.216:8204/swagger-ui.html
订单接口:http://139.198.34.216:8206/swagger-ui.html
文件上传接口:http://139.198.34.216:8205/swagger-ui.html
后台用户接口:http://139.198.34.216:8212/swagger-ui.html

二、创建项目

创建项目 syt_hospital

npm init vue@latest

在这里插入图片描述

项目架构

在这里插入图片描述

在这里插入图片描述

三、配置项目

1.配置icon

favicon.ico

2.配置项目代码规范

  1. 集成 editorconfig配置 https://editorconfig.org/

editorconfig有助于为不同IDE编辑器上处理同一个项目的多个开发人员维护一致的编码风格。

.editorconfig

# http://editorconfig.org
root = true

[*] # 表示所有的文件
charset = utf-8 # 设置文件字符集为utf-8
indent_style = space # 缩进风格 (tab或者space)
indent_size = 2 # 缩进大小
end_of_line = lf # 控制换行风格
trim_trailing_whitespace = true # 去除行尾的任意空白字符
insert_final_newline = true # 始终在文件末尾插入一个新行
 
[*.md] # 表示仅设置 markdown 文件适用以下规则
max_line_length = off
trim_trailing_whitespace = false

  • Vscode 需要安装插件 EditorConfig for VS Code
  1. 使用prettier工具 https://www.prettier.cn/

Prettier 是一款强大的代码格式化工具,支持 javascript、typescript、css、scss、less、jsx、angular、vue、graphql、json、markdown等语言,基本上前端能用到的文件格式它都可以搞定,是当下最流行的代码格式化工具。

  • 2.1 安装prettier

npm install prettier -D

  • 2.2. 配置 .prettierrc 文件;
    • useTabs: 使用tab缩进还是空格缩进,选择 false
      • tabWidth: tab是空格的情况下,是几个空格,选择2个
      • printWidth: 当行字符的长度,推荐80,也有人喜欢100或120
      • singleQuote: 使用单引号还是双引号,选择true ,使用单引号
      • TranilingComma: 在多行输入的尾逗号是否添加,设置为true,比如对象类型的最后一个属性后面是否加一个 , ;
      • semi: 语句末尾是否要加分号,默认值true,选择false表示不加;
{
  "useTabs":false,
 	"tabwidth":2,
  "printWidth":80,
  "singleQuote":true,
  "trailingComma":"none",
  "semi":false
}

  • 2.3. 配置 .prettierrcignore 忽略文件;

    /dist/*
    .local
    .output.js
    /node_modules/**
    
    **/*.svg
    **/*.sh
    
    /public/*
    
  • 2.4 vscode 需要安装插件 Prettier - Code formatter

  • 2.5 测试prettier是否生效

    • 测试一:在代码中保存代码

    • 测试二:配置一次性修改的命令

      package.json中配置一个 scripts:

      "prettier":"prettier --write ."

3.使用ESLint检测

  • Vue创建项目的时候,选择ESLint,会默认帮我们配置需要的ESLint环境

  • vscode需要安装ESLint插件 ESLint

  • 解决eslint和prettier冲突的问题:

    • 安装插件 (vue在创建项目时,如果选择prettier,那么这两个插件会自动安装)
    • npm install eslint-plugin-prettier eslint-config-prettier -D
  • 添加 prettier插件

      extends: [
        'plugin:prettier/recommended'
      ],
    

4.git Husky和eslint

5.git commit 规范

四、项目准备

CSS样式的重置

  • 对默认css样式进行重置:

    • normalize.css

    • reset.css

  • 安装
    npm install normalize.css
    main.ts 中 引用
    import 'normalize.css'

  • 在assets / css 中新建

    • reset.less 重置的样式
    • common.less 公共的样式
    • index.less 其他less的出口,将这个less在main.ts中引入
    //css  main.ts
    import 'normalize.css'
    import '@/assets/css/index.css'
    
  • 安装 less npm install less -D (个人习惯用less)

路由配置

import { createRouter, createWebHistory } from 'vue-router'
// 初始配置
const router = createRouter({
  history: createWebHistory(),
  // 配置映射关系:path => component
  routes: [
    {
      path: '/',
      redirect: '/home'
    },
    {
      path: '/home',
      component: () => import('../views/home/index.vue')
    },
    {
      path: '/hospital',
      component: () => import('../views/hospital/index.vue')
    },
    {
      path: '/:pathMatch(.*)',
      component: () => import('../views/not-found/index.vue')
    }
  ]
})

export default router

状态管理Pinia

  • 在store/index.ts中,创建pinia

    import { createPinia } from 'pinia'
    
    const pinia = createPinia()
    
    export default pinia
    
  • 将pinia引入到main.ts中

    import pinia from './store'
    ...
    app.use(pinia)
    

二次封装axios

  • 安装 npm install axios
// service/request/index.ts
import axios from 'axios'
import type { AxiosInstance } from 'axios'
import type { PKRequestConfig } from './type'

// 拦截器: 蒙版 loading ... / token / 修改配置

class PKRequest {
  instance: AxiosInstance
  // request实例 => axios实例
  constructor(config: PKRequestConfig) {
    this.instance = axios.create(config)
    // 全局拦截器:给每个instance实例都添加拦截器
    this.instance.interceptors.request.use(
      (config) => {
        // loading token
        console.log('全局请求成功的拦截器')
        return config
      },
      (err) => {
        console.log('全局请求失败的拦截器')
        return err
      }
    )
    this.instance.interceptors.response.use(
      (res) => {
        // loading token
        console.log('全局响应成功的拦截器')
        return res
      },
      (err) => {
        console.log('全局响应失败的拦截器')
        return err
      }
    )

    // 判断是否携带拦截器

    this.instance.interceptors.request.use(
      config.interceptors?.requestOnFulfilledFn as any,
      config.interceptors?.requestOnRejectedFn
    )
    this.instance.interceptors.response.use(
      config.interceptors?.responseOnFulfilledFn,
      config.interceptors?.responseOnRejectedFn
    )
  }

  // 封装网络请求的方法
  request<T = any>(config: PKRequestConfig<T>) {
    // 单次请求的成功拦截处理
    if (config.interceptors?.requestOnFulfilledFn) {
      config = config.interceptors.requestOnFulfilledFn(config)
    }
    // 返回的promise
    return new Promise<T>((resolve, reject) => {
      this.instance
        .request<any, T>(config)
        .then((res) => {
          // 单次响应的成功拦截处理
          if (config.interceptors?.responseOnFulfilledFn) {
            res = config.interceptors.responseOnFulfilledFn(res)
          }
          resolve(res)
        })
        .catch((err) => {
          reject(err)
        })
    })
  }
  get<T = any>(config: PKRequestConfig<T>) {
    return this.instance.request({ method: 'GET', ...config })
  }
  post<T = any>(config: PKRequestConfig<T>) {
    return this.instance.request({ method: 'POST', ...config })
  }
  put<T = any>(config: PKRequestConfig<T>) {
    return this.instance.request({ method: 'PUT', ...config })
  }
  delete<T = any>(config: PKRequestConfig<T>) {
    return this.instance.request({ method: 'DELETE', ...config })
  }
  patch<T = any>(config: PKRequestConfig<T>) {
    return this.instance.request({ method: 'PATCH', ...config })
  }
}
export default PKRequest

// type.ts
import type { AxiosRequestConfig, AxiosResponse } from 'axios'

// 针对AxiosRequestConfig进行扩展
export interface IPKInterceptors<T = AxiosResponse> {
  requestOnFulfilledFn?: (config: AxiosRequestConfig) => AxiosRequestConfig
  requestOnRejectedFn?: (err: any) => any
  responseOnFulfilledFn?: (res: T) => T
  responseOnRejectedFn?: (err: any) => any
}

export interface PKRequestConfig<T = AxiosResponse> extends AxiosRequestConfig {
  interceptors?: IPKInterceptors<T>
}
  • 创建网络请求的实例

    import PKRequest from './request/index'
    import { BASE_URL, TIME_OUT } from './config/index'
    
    // 可以创建一个实例,也可以创建多个实例
    const pkRequest = new PKRequest({
      baseURL: BASE_URL,
      timeout: TIME_OUT,
      interceptors: {
        requestOnFulfilledFn: (config) => {
          console.log('实例:请求成功的拦截')
          return config
        },
        requestOnRejectedFn: (err) => {
          console.log('实例:请求失败的拦截')
          return err
        },
        responseOnFulfilledFn: (res) => {
          console.log('实例:响应成功的拦截')
          return res
        },
        responseOnRejectedFn: (err) => {
          console.log('实例:响应失败的拦截')
          return err
        }
      }
    })
    
    export default pkRequest
    
    // config.ts
    export const BASE_URL = 'http://syt.atguigu.cn'
    export const TIME_OUT = 5000
    
  • 使用 例如:

    import pkRequest from '@/service/index'
    
    // 发送网络请求
    // 数据类型
    export interface IHomeRoot {
      code: number
      message: string
      data: any
      ok: boolean
    }
    
    
    pkRequest
      .request<IHomeRoot>({
        url: '/api/hosp/hospital/1/5'
      })
      .then((res) => {
        console.log('home', res.data)
      })
    
    

区分 development和production环境

在实际开发中,有些变量或者标识符在开发环境和生产环境的值是不一样的。比如:baseURL=“服务器地址”。

  • 区分开发环境和生产环境

    • 方法一:以baseURL 为例:不用的环境注释掉

      // export const BASE_URL = 'http://syt.atguigu.cn' //生产环境
      export const BASE_URL = 'http://syt.atguigu.cn' //开发环境
      

      缺点:太多依赖人为手动,不安全性太高

    • 方法二:vite环境变量¶

      Vite 在一个特殊的 import.meta.env 对象上暴露环境变量。这里有一些在所有情况下都可以使用的内建变量:

      • import.meta.env.MODE: {string} 应用运行的模式。
      • import.meta.env.BASE_URL: {string} 部署应用时的基本 URL。他由base 配置项决定。
      • import.meta.env.PROD: {boolean} 应用是否运行在生产环境。
      • import.meta.env.DEV: {boolean} 应用是否运行在开发环境 (永远与 import.meta.env.PROD相反)。
      • import.meta.env.SSR: {boolean} 应用是否运行在 server 上。
      let BASE_URL = ''
      if (import.meta.env.PROD) {
        BASE_URL = 'http://syt.atguigu.cn'
      } else {
        BASE_URL = 'http://syt.atguigu.cn'
      }
      
      export const TIME_OUT = 5000
      export { BASE_URL }
      
    • 方法三:Vite使用 dotenv 从你的 环境目录 中的下列文件加载额外的环境变量:

      https://cn.vitejs.dev/guide/env-and-mode.html#env-files

      .env                # 所有情况下都会加载
      .env.local          # 所有情况下都会加载,但会被 git 忽略
      .env.[mode]         # 只在指定模式下加载
      .env.[mode].local   # 只在指定模式下加载,但会被 git 忽略
      
      • 在项目中 创建文件: .env .env.development .env.production

        在这里插入图片描述

集成ElementPlus

https://element-plus.org/zh-CN/guide/quickstart.html

  • 安装 npm install element-plus --save

  • 按需引入

    安装npm install -D unplugin-vue-components unplugin-auto-import

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

问题:

  • Component name “index” should always be multi-word.eslintvue/multi-word-component-names

    • .eslintrc.cjs 中 配置
    module.exports = {
      root: true,
      extends: 
      .
      .
      .
      rules: {
        'vue/multi-word-component-names': 'off'
      }
    }
    
  • 将生成到 CommonJS 输出的文件中不允许 ‘import.meta’ 元属性。ts(1470)

    The type of import.meta.

    If you need to declare that a given property exists on import.meta, this type may be augmented via interface merging.

    tsconfig.node.json

    "compilerOptions": {
        "module": "ESNext",
      }
    

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

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

相关文章

掌握文件转换的技巧:在线工具帮你轻松转换为PDF格式

许多文件都有自己的原始格式&#xff0c;然而这些格式都可以进行修改。遇到无法打开或信息丢失的情况时&#xff0c;可以进行格式转换&#xff0c;其中效果最好的就是PDF格式&#xff0c;无论在哪个平台上查看文档&#xff0c;都有自己的格式&#xff0c;能够在所有平台上查看的…

中国首个铝基轻量化平台?纯电中型 SUV 奇瑞eQ7将于7月12日发布

奇瑞新能源将于7月12日发布首台量产车奇瑞eQ7&#xff0c;并公布中国首个铝基轻量化平台。 车型参数&#xff1a;奇瑞 eQ7是一款定位纯电动中型SUV&#xff0c;采用后置后驱和油冷扁线三合一电机技术。其以全铝车身和全铝平台为基础&#xff0c;整备质量为185kg。车身尺寸为467…

表中签到ID格式是以逗号分隔,需将ID拆开并分成多条数据

原有数据格式&#xff1a; 拆分后数据格式&#xff1a; 拆分SQL: select bc.资源名称,bc.资源ID,bc.签到时间,bc.签到人,bb.column_value 签到附件ID from report_fir.V_kw_checksign_info bc,table(hbrmw6.split_string(bc.签到附件ID,,)) bb; HBRMW6.split_string函数创…

mysql数据库内存占用高原因(数据库内存占用高)

1、查看数据库分配内存大小 ( mysql内存计算器&#xff0c;具体地址为http://www.mysqlcalculator.com/ ) select VARIABLE_NAME,VARIABLE_VALUE/1024/1024 MB from information_schema.GLOBAL_VARIABLES WHERE VARIABLE_NAME in (key_buffer_size,query_cache_size,tmp_tabl…

基本数据与封装对象转换(Java)

文章目录 1. 基本数据与对象封装转换1.1 8种基本数据类型:1.2 基本数据类型 -- > 封装对象:1.3 封装对象 -- > 基本数据类型:1.4 借助String类型作为中间桥梁 2. 自动转换规则 1. 基本数据与对象封装转换 1.1 8种基本数据类型: boolean(true/false)&#xff0c;byte(1 …

时间序列预测 | Matlab粒子群算法(PSO)优化极限梯度提升树XGBoost时间序列预测,PSO-XGBoost时间序列预测模型

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 时间序列预测 | Matlab基粒子群算法(PSO)优化极限梯度提升树XGBoost时间序列预测,PSO-XGBoost时间序列预测模型 评价指标包括:MAE、RMSE和R2等,代码质量极高,方便学习和替换数据。要求2018版本及以上。 部分源码…

【雕爷学编程】Arduino动手做(153)---2.4寸TFT液晶触摸屏模块4

37款传感器与执行器的提法&#xff0c;在网络上广泛流传&#xff0c;其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块&#xff0c;依照实践出真知&#xff08;一定要动手做&#xff09;的理念&#xff0c;以学习和交流为目的&am…

基于matlab使用激光雷达检测地平面和障碍物(附源码)

一、前言 此示例演示如何通过分割地平面并查找附近的障碍物来处理来自安装在车辆上的传感器的 3-D 激光雷达数据。这可以促进车辆导航的可驾驶路径规划。该示例还演示如何可视化流式激光雷达数据。 二、创建 Velodyne 文件读取器 本例中使用的激光雷达数据是使用安装在车辆上…

[工业互联-17]:常见EtherCAT主站与实现方法

目录 第1章 EtherCAT入门 1.1 简介 1.2 EtherCAT通信架构 第2章 EtherCAT主站方案 2.1 方案概述 2.2 主站配置步骤 2.3 EtherCAT主站软件 第3章 Windows操作系统支持EtherCAT的基本步骤 第4章 常见主站软件介绍&#xff1a;TwinCAT 4.1 简介 4.2 软件架构 4.3 应…

【计算机网络】第三章 数据链路层(概述 封装成桢 差错检错)

文章目录 第三章 数据链路层3.1 数据链路层概述3.2 封装成帧3.3 差错检测3.3.1 奇偶校验3.3.2 循环冗余校验 第三章 数据链路层 3.1 数据链路层概述 数据链路层是计算机网络体系结构中的一层&#xff0c;位于物理层和网络层之间。它负责在相邻节点之间传输数据&#xff0c;并提…

hugging face参数高效微调peft源码解析

大模型参数高效微调(PEFT) - 知乎 让天下没有难Tuning的大模型-PEFT技术简介 - 知乎 大模型参数高效微调技术原理综述&#xff08;三&#xff09;-P-Tuning、P-Tuning v2 - 知乎 你似乎来到了没有知识存在的荒原 - 知乎 大模型参数高效微调技术原理综述&#xff08;六&a…

由LM386构成的3W简易OCL功放电路/由TDA2009构成的1W高保真BTL功率放大器

由LM386构成的3W简易OCL功放电路 该电路是使用低功耗集成功率放大器 LM386 构成的 OCL 功放电路&#xff0c;电路结构简单&#xff0c;容易调试&#xff0c;非常适于自制。 一、电路工作原理 电路原理如图 31 所示。 图中IC1和IC2是两片集成功放LM386&#xff0c;接成OCL电路…

【编程的多线程学习-前章】什么是进程,PCB进程控制块抽象,cup分配,内存分配,虚拟地址,进程的通信,进程的意义

什么是进程 什么是进程/任务&#xff08;Process/Task&#xff09;进程就是一个运行起来的程序PCB 进程控制块抽象(PCB Process Control Block)pcb就是一个进程PCB具体包含的信息 CPU 分配 —— 进程调度&#xff08;Process Scheduling&#xff09;内存分配 —— 内存管理&…

Linux进度条小程序

文章目录 &#x1fa85;1. 回车换行♥1.1 回车♥1.2 换行 &#x1fa86;2. 缓冲区现象&#x1f9f8;3. 进度条实现♟3.1 逻辑♟3.2 进度条样式♟3.3 代码实现 &#x1f0cf;4. 场景使用 &#x1fa85;1. 回车换行 在学习C语言的时候&#xff0c;我们输出的时候&#xff0c;通常…

Linux 安装elasticsearch,kibana,Logstash

1、Elasticsearch 安装 cd /usr/localwget \ https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.17.7-linux-x86_64.tar.gz \ https://artifacts.elastic.co/downloads/kibana/kibana-7.17.7-linux-x86_64.tar.gz \ https://artifacts.elastic.co/downlo…

BM77-最长的括号子串

题目 给出一个长度为 n 的&#xff0c;仅包含字符 ( 和 ) 的字符串&#xff0c;计算最长的格式正确的括号子串的长度。 例1: 对于字符串 "(()" 来说&#xff0c;最长的格式正确的子串是 "()" &#xff0c;长度为 2 .例2&#xff1a;对于字符串 ")()…

AI Chat 设计模式:5. 策略模式

本文是该系列的第五篇&#xff0c;采用问答式的方式展开&#xff0c;问题由我提出&#xff0c;答案由 Chat AI 作出&#xff0c;灰色背景的文字则主要是我的旁白。 问题列表 Q.1 我想学习一下策略模式A.1Q.2 你先给我简单讲解一下吧A.2Q.3 你举得这个电商平台例子不错&#xf…

青岛大学_王卓老师【数据结构与算法】Week04_09_线性表的应用2_学习笔记

本文是个人学习笔记&#xff0c;素材来自青岛大学王卓老师的教学视频。 一方面用于学习记录与分享&#xff0c;另一方面是想让更多的人看到这么好的《数据结构与算法》的学习视频。 如有侵权&#xff0c;请留言作删文处理。 课程视频链接&#xff1a; 数据结构与算法基础–…

使用 tail -f 实时观测服务器日志输出

在开发阶段, 有 console 端的输出, 总是可以方便实时地看到应用的日志. 可一旦应用部署到服务器上之后呢, 日志被输出到文件中, 在某些情景下需要不停地查看日志文件的输出以定位某些问题, 此时是否还能像开发那样实时查看日志呢? 答案是可以的! 这个命令就是 tail -f . tail…

vue2 element-ui 2.9.1版不支持抽屉el-drawer

一个老项目中想使用抽屉 el-drawer&#xff0c;死活没有反应。 查了下element-ui的版本是2.9.1 再看其他一个正常使用抽屉的项目的element-ui版本。 但是 2.14.1 的element-ui版本又存在菜单管理无法折叠菜单项的问题。 看来还是得抽空解决在2.14.1菜单无法折叠的问题了。