vue3+ts项目搭建

1、检查是否安装pnpm (默认npm安装成功的情况下,也就是安装了node)
        pnpm --version

        当前是安装成功

   a)、如果有安装的

        Ⅰ、pnpm create vite

        Ⅱ、


√ Project name: ... web_student // 直接输入你的项目名 注意命名规则
√ Select a framework: » Vue     // 上下键选中vue即可
√ Select a variant: » TypeScript // 语言中选择ts

Scaffolding project in D:\project\2024\2024-11\2024-11-20\web_student...

Done. Now run:

  cd web_student   //进入项目以后
  pnpm install     // 下载项目依赖
  pnpm run dev     // 启动项目


D:\project\2024\2024-11\2024-11-20>

   
   b)、如果没有安装

                Ⅰ、查看npm的下载源

npm config get registry


               Ⅱ、修改npm的下载源 (因为默认指向的是 国外的下载地址,指向淘宝下载地址,下载速度就会很快)

npm config set registry https://registry.npmmirror.com/

                Ⅲ、下载pnpm 

npm i -g pnpm

2、配置一下npm启动的时候 默认浏览器

{
  "name": "web_student",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite --open", // --open 配置项目启动项
    "build": "vue-tsc -b && vite build",
    "preview": "vite preview"
  },
  "dependencies": {
    "vue": "^3.5.12"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^5.1.4",
    "typescript": "~5.6.2",
    "vite": "^5.4.10",
    "vue-tsc": "^2.1.8"
  }
}

3、在 Vue 3 和 Vite 项目中,你可以通过配置 vite.config.ts 文件来设置 @ 作为路径别名(Alias),用于引用 src 目录中的文件。这样可以简化导入路径,让代码更简洁和可维护。

a)完整示例:以下是一个完整的 vite.config.ts 配置示例:

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

// https://vite.dev/config/
export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "./src"), // 配置 @ 指向 src 目录
    },  // __dirname 会报红需要使用pnpm 下载 npm install @types/node --save-dev
  },
});

b)测试使用 当前目录结构
        

当前 Water.vue

当前使用 water组件

import Water from "@/components/Water.vue";

4、安装Element-plus,我使用的是 pnpm,并且顺便将 element-plus/icons一起引入

pnpm install element-plus @element-plus/icons-vue

a)配置Volar 支持

如果您使用 Volar,请在根目录下 tsconfig.json 中通过 compilerOptions.type 指定全局组件类型

// tsconfig.json
{
  "compilerOptions": {
    // ...
    "types": ["element-plus/global"]
  }
}

b)配置按需自动导入

 首先你需要安装 unplugin-vue-components 和 unplugin-auto-import 这两款插件

pnpm install -D unplugin-vue-components unplugin-auto-import

c) 然后把下列代码插入到根目录下 vite.config.ts 文件中

import { defineConfig } from 'vite'
// 以下三项引入是为配置Element-plus自动按需导入
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: [
    // 以下两项是为配置Element-plus自动按需导入
    AutoImport({
      resolvers: [ElementPlusResolver()],
    }),
    Components({
      resolvers: [ElementPlusResolver()],
    }),
  ],
})

d)验证是否成功

Element-lus官网:https://element-plus.gitee.io/zh-CN/component/button.html

打开 Element-plus 官网吗,复制一点儿 el-button相关代码进 App.vue文件

// 这是 src目录下的 App.vue 文件
<script lang="ts" setup></script>
<template>
	<div>
	  <h1>App页面</h1>
	  <el-row class="mb-4">
		<el-button>Default</el-button>
		<el-button type="primary">Primary</el-button>
		<el-button type="success">Success</el-button>
		<el-button type="info">Info</el-button>
		<el-button type="warning">Warning</el-button>
		<el-button type="danger">Danger</el-button>
	  </el-row>
	</div>
</template>
<style lang="scss" scoped></style>

e打开页面查看,成功展示相关组件,且控制台无报错,至此自动按需导入配置完成

5、配置项目中vue的自动引入 vue3 import { ref , ... } 引入繁琐问题

        a)下载依赖

pnpm i unplugin-auto-import -D


        b)修改配置vite.config.ts

import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import path from "path";
// 以下三项引入是为配置Element-plus自动按需导入
import AutoImport from "unplugin-auto-import/vite";
import Components from "unplugin-vue-components/vite";
import { ElementPlusResolver } from "unplugin-vue-components/resolvers";

// https://vite.dev/config/
export default defineConfig({
  plugins: [
    vue(), // 以下两项是为配置Element-plus自动按需导入
    AutoImport({
      resolvers: [ElementPlusResolver()],
      // 自动引入vue pinia 等
      imports: ["vue", "vue-router", "pinia"],
    }),
    Components({
      resolvers: [ElementPlusResolver()],
    }),
  ],
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "./src"), // 配置 @ 指向 src 目录
    },
  },
});

c) 全部都配置好了 可是vscode报红

d)解决报红 找到tsconfig.json 添加一行配置 这样就可以了

e) 解决完成以后

6、配置eslintrc.cjs 

D:\project\2024\2024-11\2024-11-20\web_student>pnpm i eslint -D   // 下载eslint
Packages: +78
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Progress: resolved 235, reused 175, downloaded 20, added 78, done

devDependencies:
+ eslint 9.15.0

Done in 8.3s

D:\project\2024\2024-11\2024-11-20\web_student>npx eslint --init  // 安装 eslint 配置项
You can also run this command directly using 'npm init @eslint/config@latest'.
Need to install the following packages:
@eslint/create-config@1.4.0
Ok to proceed? (y) y  // 是否要去下载 @eslint/create-config@1.4.0  是的
@eslint/create-config: v1.4.0

√ How would you like to use ESLint? · problems  // 用eslint 发现并且提示问题
√ What type of modules does your project use? · esm  // 项目使用过的类型
√ Which framework does your project use? · vue  // 是否选择vue 是的
√ Does your project use TypeScript? · typescript //  是否使用ts 是的
√ Where does your code run? · browser   // 是否在浏览器中使用 是的
The config that you've selected requires the following dependencies:  //您选择的配置需要以下依赖项  同意就行

eslint, globals, @eslint/js, typescript-eslint, eslint-plugin-vue
√ Would you like to install them now? · No / Yes // 是否现在就下载
√ Which package manager do you want to use? · pnpm  // 使用pnpm 进行下载就行
☕️Installing...
Packages: +24
++++++++++++++++++++++++
Progress: resolved 259, reused 208, downloaded 11, added 24, done

devDependencies:
+ @eslint/js ^9.15.0
+ eslint-plugin-vue 9.31.0
+ globals 15.12.0
+ typescript-eslint 8.15.0

Done in 7.2s
Successfully created D:\project\2024\2024-11\2024-11-20\web_student\eslint.config.js file.

a) 完成以上的步骤以后会生成 eslint.config.js 文件 这个是eslint9 以后的版本(我也找了很多资料最后在github中拔了一个项目以后才配置好的)

eslint.config.js 的配置 具体如下

// import globals from "globals";
// 预定义配置
import pluginJs from "@eslint/js";
import tseslint from "typescript-eslint";
import pluginVue from "eslint-plugin-vue";

// import babelParser from "@typescript-eslint/parser";
import commpnParser from "vue-eslint-parser";
import prettier from "eslint-plugin-prettier";
import babelEslintParser from "@babel/eslint-parser";

import { readFile } from "node:fs/promises";
// 配置文件自动引入的问题  报红的问题
const autoImport = JSON.parse(
  await readFile(new URL("./.eslintrc-auto-import.json", import.meta.url))
);

// "@babel/eslint-parser";

// import customConfig from "./esconfig/custom_config.js";

export default [
  // languageOptions:配置如何检查 js 代码
  {
    // 1.1 处理 与 JavaScript 相关的配置项
    // - ecmaVersion
    // - sourceType
    // - globals
    // - parser
    // - parserOptions
    // files: ["**/*.ts", "**/*.vue"],
    // ignores: ["**/*.config.js"],

    ignores: [
      "**/*.config.js",
      "dist/**",
      "node_modules/**",
      "!**/eslint.config.js",
      "auto-imports.d.ts",
      "components.d.ts",
    ],
    languageOptions: {
      // 1.11 定义可用的全局变量
      globals: {
        ...autoImport.globals,
      },
      // 1.12 扩展
      // ecmaVersion: "latest",
      // sourceType: "module",
      parser: commpnParser,
      parserOptions: {
        ecmaVersion: "latest",
        sourceType: "module",
        parser: "@typescript-eslint/parser",
        jsxPragma: "React",
        ecmaFeatures: {
          jsx: true,
        },
      },
    },
  },
  // 原来的extends替换为如下模式
  pluginJs.configs.recommended, // eslint 推荐格则
  ...tseslint.configs.recommended,
  ...pluginVue.configs["flat/essential"],
  {
    plugins: {
      prettier,
      babelEslintParser,
    },
    rules: {
      // 开启这条规则后,会将prettier的校验规则传递给eslint,这样eslint就可以按照prettier的方式来进行代码格式的校验
      "prettier/prettier": "off",
      // eslint(https://eslint.bootcss.com/docs/rules/)
      "no-var": "error", // 要求使用 let 或 const 而不是 var
      "no-multiple-empty-lines": ["warn", { max: 1 }], // 不允许多个空行
      "no-unexpected-multiline": "error", // 禁止空余的多行
      "no-useless-escape": "off", // 禁止不必要的转义字符

      // typeScript (https://typescript-eslint.io/rules)
      "@typescript-eslint/no-unused-vars": "error", // 禁止定义未使用的变量
      "@typescript-eslint/prefer-ts-expect-error": "error", // 禁止使用 @ts-ignore
      "@typescript-eslint/no-explicit-any": "off", // 禁止使用 any 类型
      "@typescript-eslint/no-non-null-assertion": "off",
      "@typescript-eslint/no-namespace": "off", // 禁止使用自定义 TypeScript 模块和命名空间。
      "@typescript-eslint/semi": "off",

      // eslint-plugin-vue (https://eslint.vuejs.org/rules/)
      "vue/multi-word-component-names": "off", // 要求组件名称始终为 “-” 链接的单词
      "vue/script-setup-uses-vars": "error", // 防止<script setup>使用的变量<template>被标记为未使用
      "vue/no-mutating-props": "off", // 不允许组件 prop的改变
      "vue/attribute-hyphenation": "off", // 对模板中的自定义组件强制执行属性命名样式
    },
  },
];

b) 启动项配置 pageckage.json

{
  "name": "web_student",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite --open",
    "build": "vue-tsc -b && vite build",
    "preview": "vite preview",
    "lint": "eslint src",
    "fix": "eslint src --fix"
  },
  "dependencies": {
    "@element-plus/icons-vue": "^2.3.1",
    "element-plus": "^2.8.8",
    "vue": "^3.5.12"
  },
  "devDependencies": {
    "@babel/eslint-parser": "^7.25.9",
    "@eslint/compat": "^1.2.3",
    "@eslint/js": "^9.15.0",
    "@types/node": "^22.9.1",
    "@vitejs/plugin-vue": "^5.1.4",
    "eslint": "^9.15.0",
    "eslint-config-prettier": "^9.1.0",
    "eslint-plugin-import": "^2.31.0",
    "eslint-plugin-node": "^11.1.0",
    "eslint-plugin-prettier": "^5.2.1",
    "eslint-plugin-vue": "^9.31.0",
    "globals": "^15.12.0",
    "typescript": "~5.6.2",
    "typescript-eslint": "^8.15.0",
    "unplugin-auto-import": "^0.18.5",
    "unplugin-vue-components": "^0.27.4",
    "vite": "^5.4.10",
    "vue-tsc": "^2.1.8"
  }
}

c) tsconfig.json 配置这个可以@别名的问题

{
  "compilerOptions": {
    "target": "ESNext",
    "jsx": "preserve",
    "lib": ["DOM", "ESNext"],
    "baseUrl": ".",
    "module": "ESNext",
    "moduleResolution": "node",
    "paths": {
      "~/*": ["src/*"],
      "@/*": ["src/*"]
    },
    "resolveJsonModule": true,
    "types": [],
    "allowJs": true,
    "strict": true,
    "strictNullChecks": true,
    "noUnusedLocals": true,
    "importHelpers": true,
    "outDir": "dist",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "skipLibCheck": true
  },
  "exclude": ["node_modules", "dist/**/*", "public/**/*"],

  "vueCompilerOptions": {
    "target": 3, // or 2.7 for Vue 2
    "plugins": [
      "@vue-macros/volar/define-props-refs",
      "@vue-macros/volar/define-props"
    ]
  }
}

这个时候 就可以 npm run fix  而且页面中别名引入和自动引入的爆红就可以解决

7、开始配置 全局的按需加载的echarts了

a) 下载 echarts

        

pnpm i echarts -S

b) src 中放 utils 文件夹 utils中放echarts.ts 文件

// 引入 echarts 核心模块。
import * as echarts from "echarts/core";
//引入柱状图和折线图组件。
import { BarChart, LineChart } from "echarts/charts";
// // 引入标题、提示框、网格、数据集和数据转换器组件。
import {
  TitleComponent,
  TooltipComponent,
  GridComponent,
  // 数据集组件
  DatasetComponent,
  // 内置数据转换器组件 (filter, sort)
  TransformComponent,
  // 坐标轴的值
  LegendComponent,
  ToolboxComponent,
  MarkLineComponent,
} from "echarts/components";
// //引入标签布局和通用过渡动画特性。
// import { LabelLayout, UniversalTransition } from 'echarts/features';
// // 引入 Canvas 渲染器。
import { CanvasRenderer } from "echarts/renderers";

import type {
  // 系列类型的定义后缀都为 SeriesOption
  BarSeriesOption,
  LineSeriesOption,
} from "echarts/charts";

import type {
  // 组件类型的定义后缀都为 ComponentOption
  TitleComponentOption,
  TooltipComponentOption,
  GridComponentOption,
  DatasetComponentOption,
} from "echarts/components";
import type { ComposeOption } from "echarts/core";

// 通过 ComposeOption 来组合出一个只有必须组件和图表的 Option 类型
type ECOption = ComposeOption<
  | BarSeriesOption
  | LineSeriesOption
  | TitleComponentOption
  | TooltipComponentOption
  | GridComponentOption
  | DatasetComponentOption
>;

/** 
    注册必须的组件,包括标题、提示框、网格、数据集、数据转换器,
    以及柱状图、折线图、标签布局、通用过渡动画和 Canvas 渲染器。
*/
echarts.use([
  TitleComponent,
  TooltipComponent,
  GridComponent,
  DatasetComponent,
  TransformComponent,
  BarChart,
  LineChart,
  // LabelLayout,
  // UniversalTransition,
  LegendComponent,
  ToolboxComponent,
  CanvasRenderer,
  MarkLineComponent,
]);
// 导出
export default echarts;

c) main.ts 文件中进行全局引入

import { createApp } from "vue";
import "./style.css";
import App from "./App.vue";
//引入创建的echarts.ts文件
import echarts from "@/utils/echart";

const app = createApp(App);
// 全局配置
app.provide("$echarts", echarts);

app.mount("#app");

d)  直接使用echarts图表 Chart.vue

<script setup lang="ts">
const chartNode = ref<HTMLDivElement>();
const ECharts: any = inject("$echarts");
onMounted(() => {
  const myChart = ECharts.init(chartNode.value);

  const option = {
    title: {
      text: "Temperature Change in the Coming Week",
    },
    tooltip: {
      trigger: "axis",
    },
    legend: {},
    toolbox: {
      show: true,
      feature: {
        dataZoom: {
          yAxisIndex: "none",
        },
        dataView: { readOnly: false },
        magicType: { type: ["line", "bar"] },
        restore: {},
        saveAsImage: {},
      },
    },
    xAxis: {
      type: "category",
      boundaryGap: false,
      data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
    },
    yAxis: {
      type: "value",
      axisLabel: {
        formatter: "{value} °C",
      },
    },
    series: [
      {
        name: "Highest",
        type: "line",
        data: [10, 11, 13, 11, 12, 12, 9],
        markPoint: {
          data: [
            { type: "max", name: "Max" },
            { type: "min", name: "Min" },
          ],
        },
        markLine: {
          data: [{ type: "average", name: "Avg" }],
        },
      },
      {
        name: "Lowest",
        type: "line",
        data: [1, -2, 2, 5, 3, 2, 0],
        markPoint: {
          data: [{ name: "周最低", value: -2, xAxis: 1, yAxis: -1.5 }],
        },
        markLine: {
          data: [
            { type: "average", name: "Avg" },
            [
              {
                symbol: "none",
                x: "90%",
                yAxis: "max",
              },
              {
                symbol: "circle",
                label: {
                  position: "start",
                  formatter: "Max",
                },
                type: "max",
                name: "最高点",
              },
            ],
          ],
        },
      },
    ],
  };

  myChart.setOption(option);

  window.addEventListener("resize", () => {
    myChart.resize();
  });
});
</script>

<template>
  <div class="chart" id="test" ref="chartNode"></div>
</template>

<style scoped>
.chart {
  width: 50vw;
  height: 50vh;
  border: 1px solid #000;
}
</style>

e) app.vue开始用

<script setup lang="ts">
import Chart from "@/components/Chart.vue";
import Water from "@/components/Water.vue";
</script>

<template>
  <Chart />
  <Water></Water>
</template>

<style scoped>
.logo {
  height: 6em;
  padding: 1.5em;
  will-change: filter;
  transition: filter 300ms;
}
.logo:hover {
  filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vue:hover {
  filter: drop-shadow(0 0 2em #42b883aa);
}
</style>

页面中实际使用效果

8)配置反向代理

import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import path from "path";
// 以下三项引入是为配置Element-plus自动按需导入
import AutoImport from "unplugin-auto-import/vite";
import Components from "unplugin-vue-components/vite";
import { ElementPlusResolver } from "unplugin-vue-components/resolvers";

// https://vite.dev/config/
export default defineConfig({
  server: {
    host: "0.0.0.0",
    port: 3000,
    proxy: {
      "/base": {
        target: "https://xxxx",
        changeOrigin: true, // 是否改变源地址
        // secure: false,
        rewrite: (path) => path.replace(/^\/base/, ""),
      },
      "/get": {
        target: "https:xxxxx",
        changeOrigin: true, // 是否改变源地址
        // secure: false,
        rewrite: (path) => path.replace(/^\/get/, ""),
      },
    },
  },
  plugins: [
    vue(), // 以下两项是为配置Element-plus自动按需导入
    AutoImport({
      resolvers: [ElementPlusResolver()],
      // 自动引入vue pinia 等
      imports: ["vue", "vue-router", "pinia"],
      eslintrc: {
        enabled: false,
        filepath: "./.eslintrc-auto-import.json",
        globalsPropValue: true,
      },
    }),
    Components({
      resolvers: [ElementPlusResolver()],
    }),
  ],
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "./src"), // 配置 @ 指向 src 目录
    },
  },
});

9)配置生产依赖项和开发依赖项 主要就是接口这块的配置
 

开发接口配置     .env.development

VITE_APP_BASE_API = /
VITE_APP_BASE_API_WATER = '/base'
VITE_APP_BASE_API_SIMULATION = '/get'

生产接口的配置 .env.production

VITE_APP_BASE_API='/'

VITE_APP_BASE_API_WATER = '/old'
VITE_APP_BASE_API_SIMULATION = ''

api 接口的配置

下载 axios pnpm i axios -S

useApi 下的 index.ts


import type { AxiosRequestConfig } from 'axios'
import axios from 'axios'
import { ElMessage } from 'element-plus'

enum RequestEnums {
  TIMEOUT = 60000,
  FAIL = 500, // 请求失败
  SUCCESS = 200 // 请求成功
}

export interface Response<T = any> {
  code: number
  data: T
  message: string
  success: boolean
}

export default function useApi(
  prefix?: string,
  headers?: {
    [key: string]: any
  }
) {
  const http = axios.create({
    timeout: RequestEnums.TIMEOUT,
    headers: {
      'Content-Type': 'application/json;charset=utf-8',
      ...(headers || {})
    },
    baseURL: prefix
  })

  http.interceptors.response.use((res: any) => {
    if (res.status === RequestEnums.SUCCESS) {
      if (res.data.code != RequestEnums.SUCCESS) {
        ElMessage.error(res.data.message)
        throw res
      }
      return res
    } else {
      throw res
    }
  })
  http.interceptors.request.use((req: any) => {
    if (req.headers['Content-Type'] === 'x-www-form-urlencoded') {
      const formData = new FormData()
      Object.keys(req.data).map((i) => {
        formData.set(i, req.data[i])
      })
      req.data = formData
    }
    return req
  })

  return {
    ...http,
    get<T = any>(url: string, params?: any, config?: AxiosRequestConfig<any>) {
      return http
        .get<Response<T>>(url, {
          ...config,
          params
        })
        .then((res: any) => res.data)
    },
    post<T = any>(url: string, params?: any, config?: AxiosRequestConfig<any>) {
      return http.post<Response<T>>(url, params, config).then((res: any) => res.data)
    },
    delete<T = any>(url: string, params?: any, config?: AxiosRequestConfig<any>) {
      return http
        .delete<Response<T>>(url, {
          ...config,
          params
        })
        .then((res: any) => res.data)
    },
    put<T = any>(url: string, params?: any, config?: AxiosRequestConfig<any>) {
      return http.put<Response<T>>(url, params, config).then((res: any) => res.data)
    }
  }
}

simulativeModeling.ts 文件

import useApi from './useApi'

const { VITE_APP_BASE_API_SIMULATION } = import.meta.env

const request = useApi()
/**
 * @description 初始化当前的工况
 */
export const getConditionDataApi = (params: { code: string }) => {
  return request.get(`${VITE_APP_BASE_API_SIMULATION}/base/ioc/queryPointLatestData`, params)

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值