【Vue3+TS项目】硅谷甄选day02--后台管理系统模板搭建/项目配置

1 项目初始化

一个项目要有统一的规范,需要使用eslint+stylelint+prettier来对我们的代码质量做检测和修复,需要使用husky来做commit拦截,需要使用commitlint来统一提交规范,需要使用preinstall来统一包管理工具

1.1 环境准备

  • node v16.14.2

  • pnpm 8.0.0

1.2 初始化项目

本项目使用vite进行构建,vite官方中文文档参考:cn.vitejs.dev/guide/

pnpm:performant npm ,意味“高性能的 npm”。pnpm由npm/yarn衍生而来,解决了npm/yarn内部潜在的bug,极大的优化了性能,扩展了使用场景。被誉为“最先进的包管理工具”

pnpm安装指令:

npm i -g pnpm

项目初始化命令:

pnpm create vite

进入到项目根目录pnpm install安装全部依赖,安装完依赖运行程序:pnpm run dev

运行完毕项目跑在http://127.0.0.1:5173/,可以访问你得项目啦

可能出现的问题

 Cannot find module './App.vue' or its corresponding type declarations

【Vue3+TS项目】硅谷甄选day02--后台管理系统模板搭建/项目配置_第1张图片

报错原因:typescript 只能理解 .ts 文件,无法理解 .vue文件

解决方法1:安装 volar 插件,输入 volar ,有多个扩展程序,能起作用的是 Typescript Vue Plugin(Volar)

之前 vscode 检测到 vue3 ,自动推荐安装了 Vue Language Feature(Volar),但用它扔有类型报错。官方推荐,使用它时禁用 Vetur,以免有冲突。

解决方法2:创建vite项目后,项目根目录会有一个 “env.d.ts” 文件,找到该文件,在里面添加一下代码

declare module "*.vue" {
  import { DefineComponent } from "vue"
  const component: DefineComponent<{}, {}, any>
  export default component
}

小Tip:浏览器自动打开提高效率:

package.json文件中加上--open

"scripts": {
  "dev": "vite --open",
  "build": "vue-tsc && vite build",
  "preview": "vite preview"
},

发现这个不管用。。。。(可以参考我Vue2项目的自动打开浏览器配置)

2 项目配置

一、eslint配置

eslint中文官网:ESLint - Pluggable JavaScript linter - ESLint中文

ESLint最初是由 Nicholas C. Zakas 于2013年6月创建的开源项目。它的目标是提供一个插件化的javascript代码检测工具

首先安装 eslint

pnpm i eslint -D

生成配置文件:.eslint.cjs

npx eslint --init

.eslint.cjs配置文件

module.exports = {
   // 运行环境
    "env": { 
        "browser": true,// 浏览器端
        "es2021": true,// es2021
    },
    //规则继承
    "extends": [ 
       //全部规则默认是关闭的,这个配置项开启推荐规则,推荐规则参照文档
       //比如:函数不能重名、对象不能出现重复key
        "eslint:recommended",
        //vue3语法规则
        "plugin:vue/vue3-essential",
        //ts语法规则
        "plugin:@typescript-eslint/recommended"
    ],
    //要为特定类型的文件指定处理器
    "overrides": [
    ],
    //指定解析器:解析器
    //Esprima 默认解析器
    //Babel-ESLint babel解析器
    //@typescript-eslint/parser ts解析器
    "parser": "@typescript-eslint/parser",
    //指定解析器选项
    "parserOptions": {
        "ecmaVersion": "latest",//校验ECMA最新版本
        "sourceType": "module"//设置为"script"(默认),或者"module"代码在ECMAScript模块中
    },
    //ESLint支持使用第三方插件。在使用插件之前,您必须使用npm安装它
    //该eslint-plugin-前缀可以从插件名称被省略
    "plugins": [
        "vue",
        "@typescript-eslint"
    ],
    //eslint规则--最重要,需要看官网配置
    "rules": {
    }
}

1.1 vue3环境代码校验插件

# 让所有与prettier规则存在冲突的Eslint rules失效,并使用prettier进行代码检查
"eslint-config-prettier": "^8.6.0",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-node": "^11.1.0",
# 运行更漂亮的Eslint,使prettier规则优先级更高,Eslint优先级低
"eslint-plugin-prettier": "^4.2.1",
# vue.js的Eslint插件(查找vue语法错误,发现错误指令,查找违规风格指南
"eslint-plugin-vue": "^9.9.0",
# 该解析器允许使用Eslint校验所有babel code
"@babel/eslint-parser": "^7.19.1",

安装指令

pnpm install -D eslint-plugin-import eslint-plugin-vue eslint-plugin-node eslint-plugin-prettier eslint-config-prettier eslint-plugin-node @babel/eslint-parser

1.2 修改.eslintrc.cjs配置文件

// @see https://eslint.bootcss.com/docs/rules/
​
module.exports = {
  env: {
    browser: true,
    es2021: true,
    node: true,
    jest: true,
  },
  /* 指定如何解析语法 */
  parser: 'vue-eslint-parser',
  /** 优先级低于 parse 的语法解析配置 */
  parserOptions: {
    ecmaVersion: 'latest',
    sourceType: 'module',
    parser: '@typescript-eslint/parser',
    jsxPragma: 'React',
    ecmaFeatures: {
      jsx: true,
    },
  },
  /* 继承已有的规则 */
  extends: [
    'eslint:recommended',
    'plugin:vue/vue3-essential',
    'plugin:@typescript-eslint/recommended',
    'plugin:prettier/recommended',
  ],
  plugins: ['vue', '@typescript-eslint'],
  /*
   * "off" 或 0    ==>  关闭规则
   * "warn" 或 1   ==>  打开的规则作为警告(不影响代码执行)
   * "error" 或 2  ==>  规则作为一个错误(代码不能执行,界面报错)
   */
  rules: {
    // eslint(https://eslint.bootcss.com/docs/rules/)
    'no-var': 'error', // 要求使用 let 或 const 而不是 var
    'no-multiple-empty-lines': ['warn', { max: 1 }], // 不允许多个空行
    'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
    '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', // 防止

在src文件夹目录下创建一个index.ts文件:用于注册components文件夹内部全部全局组件!!!

如果直接在入口文件注册全局组件,100个要写一百次,太多了。通过自定义插件来

// 引入项目中全部的全局组件
import SvgIcon from '@/components/SvgIcon/index.vue';
​
// 全局组件的对象
const allGlobalComponents = { SvgIcon: SvgIcon };
// 对外暴露一个插件对象
export default {
    install(app) {
        Object.keys(allGlobalComponents).forEach((key) => {
            app.component(key, allGlobalComponents[key]);
        })
    }
}
在入口文件引入src/index.ts文件,通过app.use方法安装自定义插件
// 引入自定义插件对象:注册全局组件
import globalComponent from '@/components/index.ts'
// 安装自定义插件
app.use(globalComponent)

3.5 集成sass

我们目前在组件内部已经可以使用scss样式,因为在配置styleLint工具的时候,项目当中已经安装过sass sass-loader,因此我们再组件内可以使用scss语法!!!需要加上lang="scss"

接下来我们为项目添加一些全局的样式

在src/style目录下创建一个index.scss文件,当然项目中需要用到清除默认样式,因此在index.scss引入reset.scss。reset.scss中的样式可以在npm中获取。

@import './reset.scss'

在入口文件引入

// 引入全局样式
import '@/style/index.scss'

但是你会发现在src/styles/index.scss全局样式文件中没有办法使用变量。因此需要给项目中引入全局变量。

在style/variable.scss创建一个variable.scss文件!

在vite.config.ts文件配置如下:

export default defineConfig((config) => {
    css: {
      preprocessorOptions: {
        scss: {
          javascriptEnabled: true,
          additionalData: '@import "./src/styles/variable.scss";',
        },
      },
    },
}

@import "./src/styles/variable.less";后面的;不要忘记,不然会报错!

配置完毕你会发现scss提供这些全局变量可以在组件样式中使用了!!!

3.6 mock数据

安装依赖:vite-plugin-mock - npm

注意vite-plugin-mock的版本,最新版本3.0.0会报错,建议安装2.9.6

Argument of type '{ localEnabled: boolean; }' is not assignable to parameter of type 'ViteMockOptions'. Object literal may only specify known properties, and 'localEnabled' does not exist in type 'ViteMockOptions'.

【Vue3+TS项目】硅谷甄选day02--后台管理系统模板搭建/项目配置_第3张图片

 

pnpm install -D [email protected] mockjs

在 vite.config.js 配置文件启用插件。

import { UserConfigExport, ConfigEnv } from 'vite'
import { viteMockServe } from 'vite-plugin-mock'
import vue from '@vitejs/plugin-vue'
export default ({ command })=> {
  return {
    plugins: [
      vue(),
      viteMockServe({
        localEnabled: command === 'serve',
      }),
    ],
  }
}

在根目录创建mock文件夹:去创建我们需要mock数据与接口!!!

在mock文件夹内部创建一个user.ts文件

//用户信息数据
function createUserList() {
    return [
        {
            userId: 1,
            avatar:
                'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
            username: 'admin',
            password: '111111',
            desc: '平台管理员',
            roles: ['平台管理员'],
            buttons: ['cuser.detail'],
            routes: ['home'],
            token: 'Admin Token',
        },
        {
            userId: 2,
            avatar:
                'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
            username: 'system',
            password: '111111',
            desc: '系统管理员',
            roles: ['系统管理员'],
            buttons: ['cuser.detail', 'cuser.user'],
            routes: ['home'],
            token: 'System Token',
        },
    ]
}
​
export default [
    // 用户登录接口
    {
        url: '/api/user/login',//请求地址
        method: 'post',//请求方式
        response: ({ body }) => {
            //获取请求体携带过来的用户名与密码
            const { username, password } = body;
            //调用获取用户信息函数,用于判断是否有此用户
            const checkUser = createUserList().find(
                (item) => item.username === username && item.password === password,
            )
            //没有用户返回失败信息
            if (!checkUser) {
                return { code: 201, data: { message: '账号或者密码不正确' } }
            }
            //如果有返回成功信息
            const { token } = checkUser
            return { code: 200, data: { token } }
        },
    },
    // 获取用户信息
    {
        url: '/api/user/info',
        method: 'get',
        response: (request) => {
            //获取请求头携带token
            const token = request.headers.token;
            //查看用户信息是否包含有次token用户
            const checkUser = createUserList().find((item) => item.token === token)
            //没有返回失败的信息
            if (!checkUser) {
                return { code: 201, data: { message: '获取用户信息失败' } }
            }
            //如果有返回成功信息
            return { code: 200, data: {checkUser} }
        },
    },
]

安装axios

pnpm install axios

最后通过axios测试接口!!!

3.7 axios二次封装

在开发项目的时候避免不了与后端进行交互,因此我们需要使用axios插件实现发送网络请求。在开发项目的时候我们经常会把axios进行二次封装。

目的:

  • 使用请求拦截器,可以在请求拦截器中处理一些业务(开始进度条、请求头携带公共参数)
  • 使用响应拦截器,可以在响应拦截器中处理一些业务(进度条结束、简化服务器返回的数据、处理http网络错误)

在根目录下创建utils/request.ts

import axios from "axios";
import { ElMessage } from "element-plus";
//创建axios实例
let request = axios.create({
    baseURL: import.meta.env.VITE_APP_BASE_API,
    timeout: 5000
})
//请求拦截器
request.interceptors.request.use(config => {
    return config;
});
//响应拦截器
request.interceptors.response.use((response) => {
    return response.data;
}, (error) => {
    //处理网络错误
    let msg = '';
    let status = error.response.status;
    switch (status) {
        case 401:
            msg = "token过期";
            break;
        case 403:
            msg = '无权访问';
            break;
        case 404:
            msg = "请求地址错误";
            break;
        case 500:
            msg = "服务器出现问题";
            break;
        default:
            msg = "无网络";
​
    }
    ElMessage({
        type: 'error',
        message: msg
    })
    return Promise.reject(error);
});
export default request;

注意点:

暴露的是封装好的request而不是axios

发请求时不需要再携带/api,因为基础路径里面配置好了

任何一次请求都会经过请求拦截器,所以请求拦截器中的配置config可以携带一些东西给服务器,一般是token

请求拦截器中必须返回config对象,不然请求都发不出去

3.8 API接口统一管理

在开发项目的时候,接口可能很多需要统一管理。在src目录下去创建api文件夹去统一管理项目的接口。

比如:下面方式

//统一管理咱们项目用户相关的接口
​
import request from '@/utils/request'
​
import type {
​
 loginFormData,
​
 loginResponseData,
​
 userInfoReponseData,
​
} from './type'
​
//项目用户相关的请求地址
​
enum API {
​
 LOGIN_URL = '/admin/acl/index/login',
​
 USERINFO_URL = '/admin/acl/index/info',
​
 LOGOUT_URL = '/admin/acl/index/logout',
​
}
//登录接口
export const reqLogin = (data: loginFormData) =>
 request.post(API.LOGIN_URL, data)
//获取用户信息
​
export const reqUserInfo = () =>
​
 request.get(API.USERINFO_URL)
​
//退出登录
​
export const reqLogout = () => request.post(API.LOGOUT_URL)

type.ts中可以对请求参数以及接收数据的类型进行限制 src/api/user/type.ts

// 登入接口需要携带参数ts类型
export interface loginForm {
    username: string,
    password: string
}
​
interface dataType {
    token: string
}
//定义登录接口返回数据类型
export interface loginResponseData {
    code: number,
    data: dataType
}
​
​
interface userInfo {
    userId: number,
    avatar: string,
    username: string,
    password: string,
    desc: string,
    roles: string[],
    buttons: string[],
    routes: string[],
    token: string
}
​
interface user {
    checkUser: userInfo
}
​
//定义服务器返回用户信息相关的数据类型
export interface userResponseData {
    code: number,
    data: user
}

你可能感兴趣的:(vue.js,javascript,前端,typescript)