【后台管理系统】

项目搭建

创建vue项目

一、方式一:Vue CLI

  1. 基于webpack工具
  2. 命令:vue create

二、方式二:create-vue

  1. 基于vite工具
  2. 命令:npm init vue@latest

请添加图片描述

vue router和pinia都选择no是因为想教大家如何自己手动搭建

创建好项目后在终端输入npm install安装依赖

目录结构

.vscode文件中recommendations字段为vscode建议你安装的插件,如果你之前没安装这些插件,那么vscode会在右下角弹出弹窗问你要不要安装
请添加图片描述
public:放资源,最终打包后会放在dist文件夹中。favicon.ico为网站图标
src:源代码
.gitignore:指定提交GitHub时忽略的文件
env.d.ts:.d.ts为类型声明文件
index.html:html模板,入口文件
package.json:记录版本信息
package-lock.json:记录锁定的版本信息
tsconfig.json:(开发环境配置)

{
    
    
  "extends": "@vue/tsconfig/tsconfig.web.json",// 继承@vue/tsconfig/tsconfig.web.json配置文件,主要是框架不想让你看那么多配置内容
  // 其实@vue/tsconfig下不仅有tsconfig.web.json,还有tsconfig.node.json,tsconfig.node.json主要运用于ssr,ssr运行在node上
  "include": ["src/**/*", "src/**/*.vue", "env.d.ts"],// 哪些文件需要编译
  "compilerOptions": {
    
    
    "baseUrl": ".",
    "paths": {
    
    
      "@/*": ["./src/*"]// 用于vscode编写代码提示
    },
    "noImplicitAny": false,// 开启隐式的any
  },

  "references": [// 引入文件
    // 这里又引入了一个配置文件,为什么不把配置写在一个配置文件里?
    // 1. vite生成tsconfig.json后,不建议我们手动修改tsconfig.json,但如果在项目中有些单独的配置,建议在tsconfig.config.json进行修改
    // 最终tsconfig.config.json会被合并到tsconfig.json,因为tsc和vscode最终识别的都是tsconfig.json
    // 2. 如果项目需要运行在node上,需要在tsconfig.config.json配置:"extends": "@vue/tsconfig/tsconfig.node.json"
    // tsconfig.config.json配置的include都是基于vite环境的配置,vite代码的打包和编译都是基于node的,
    // tsconfig.json的include配置里并不包含vite.config.ts文件,vite的配置也需要打包呀
    {
    
    
      "path": "./tsconfig.config.json"
    }
  ]
}

tsconfig.config.json:(为打包所做的配置)

{
    
    
  "extends": "@vue/tsconfig/tsconfig.node.json",
  "include": ["vite.config.*", "vitest.config.*", "cypress.config.*"],// 基于vite环境的配置,vite代码的打包和编译都是基于node的,
  "compilerOptions": {
    
    
    "composite": true,// tsconfig.config.json最终会合并到tsconfig.json
    "types": ["node"]//在node环境进行编译
  }
}

vite.config.ts:配置vite

export default defineConfig({
    
    
  plugins: [vue()],// 配置插件
  resolve: {
    
    // resolve用于配置路径
    alias: {
    
    // alias用于配置别名,主要用于vite打包时,将@转为./src
      // @指向./src,默认使用es6语法,es6使用的是es module,所以用的import
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  }
})

webpack的配置文件为vue.config.js,最终会把vue cli中的webpack和vue.config.js合在一起

扫描二维码关注公众号,回复: 17505159 查看本文章

main.ts中引入.css文件没有报错是因为在env.d.ts中引入了<reference types="vite/client" />vite/client声明了.css文件。现在我们想声明.vue文件为组件,在env.d.ts中配置:

// 声明.vue文件为组件
declare module '*.vue' {
    
    
   import {
    
     DefineComponent } from 'vue'// 为什么要使用DefineComponent,可以看看视频
   const component: DefineComponent
   export default component
}

项目代码规范

editorconfig文件配置

EditorConfig有助于为不同IDE编辑器上处理同一项目的多个开发人员维护一致的编码风格。比如你们团队有人喜欢用webstorm开发,webstorm采用gbk编码,有人喜欢用vscode开发,vscode采用utf-8编码,还有的人喜欢用idea开发,idea采用utf-16编码,那么某个人打开代码的时候就会出现乱码,为了解决这一问题,可以在项目中创建.editorConfig文件,内容如下:

# http://editorconfig.org
root = true

[*] # 表示所有文件适用
charset = utf-8 # 设置文件字符集为 utf-8
indent_style = space # 缩进风格(tab | space)
indent_size = 2 # 缩进大小
end_of_line = lf # 控制换行类型(lf | cr | crlf)
trim_trailing_whitespace = true # 去除行尾的任意空白字符
insert_final_newline = true # 始终在文件末尾插入一个新行

[*.md] # 表示仅 md 文件适用以下规则
max_line_length = off# 每行字数不作限制
trim_trailing_whitespace = false# 去除尾部空格,如果前面为所有文件设置了trim_trailing_whitespace = true,这里可以设为false

配置好了之后,vscode需要安装EditorConfig for VS Code插件

现在使用prettier和eslint来配置也行,而且如果你们使用的是同一个ide编辑器的话,不需要配置该文件

prettier格式化配置

Prettier是一款强大的代码格式化工具,支持 JavaScript、TypeScript、CSS、SCSS、Less、JSX、Angular、Vue、GraphQL、JSON、Markdown 等语言,基本上前端能用到的文件格式它都可以搞定,是当下最流行的代码格式化工具。

  1. 安装:npm install prettier -D
  2. 配置.prettierrc文件(配置.prettierrc.json也行,但文件格式得为json格式):
{
    
    
  "useTabs": false,// 使用tab缩进还是空格缩进,选择false;
  "tabWidth": 2,// tab是空格的情况下,是几个空格,选择2个;
  "printWidth": 80,// 当行字符的长度,推荐80,也有人喜欢100或者120;
  "singleQuote": true,// 使用单引号还是双引号,选择true,使用单引号;
  "trailingComma": "none",// 在多行输入的尾逗号是否添加,设置为 `none`,比如对象类型的最后一个属性后面是否加一个,;
  "semi": false// 语句末尾是否要加分号,默认值true,选择false表示不加;
}
  1. 如果希望某些文件不被prettier格式化,可以创建.prettierignore忽略文件
/dist/*
.local
.output.js
/node_modules/**

**/*.svg
**/*.sh

/public/*
  1. VSCode安装prettier的插件,并在VSCode中的配置
- settings =>format on save => 勾选上
- settings => editor default format => 选择 prettier

请添加图片描述

在代码中保存代码即可生效

  1. 如果不安装插件,可以在在package.json中配置一个scripts:
    "prettier": "prettier --write ."

之后在终端执行npm run prettier就可以格式化文件了

eslint代码检测配置

eslint用于对不规范的代码进行提示

  1. 在前面创建项目的时候,我们就选择了ESLint,所以Vue会默认帮助我们配置需要的ESLint环境。
  2. VSCode需要安装ESLint插件:
  3. 解决eslint和prettier冲突的问题:
    安装插件:(vue在创建项目时,如果选择prettier,那么这两个插件会自动安装)
npm install eslint-plugin-prettier eslint-config-prettier -D

在.eslint.csj文件中添加prettier插件,之后eslint会读取prettier的配置,双方保持一致:

  extends: [
    "plugin:vue/vue3-essential",
    "eslint:recommended",
    "@vue/typescript/recommended",
    "@vue/prettier",
    "@vue/prettier/@typescript-eslint",
    'plugin:prettier/recommended'// 添加prettier插件
  ],
  1. 如果eslint不检测react,需要在.eslint.csj中进行如下配置:
  "eslint.lintTask.enable": true,
  "eslint.alwaysShowStatus": true,
  "eslint.validate": [
    "javascript",
    "javascriptreact",
    "typescript",
    "typescriptreact"
  ],
  "editor.codeActionsOnSave": {
    
    
    "source.fixAll.eslint": true
  },

如果你不希望eslint出现某个警告,可以在.eslint.csj文件中进行规则配置
请添加图片描述
请添加图片描述

css样式的重置

对默认CSS样式进行重置:

  1. normalize.css
    (1)安装:在终端输入npm install normalize.css
    (2)在main.ts中导入:import "normalize.css"
  2. reset.css
    (1)新建src/assets/css/reset.less,代码如下:
blockquote, body, button, dd, dl, dt, fieldset, form, h1, h2, h3, h4, h5, h6, hr, input, legend, li, ol, p, pre, td, textarea, th, ul {
    
    
  // color: @mainColor;
  padding: 0;
  margin: 0;
}

a {
    
    
  color: #333;
  text-decoration: none;
}

img {
    
    
  vertical-align: top;
}

(2)在index.less中先引入reset.less,再引入你写的样式
在这里插入图片描述
(3)再在main.ts中导入:import "./assets/css/index.less"
(5)vite本身不支持打包less,需要安装less才能打包:npm install less -D

router路由的配置

一、安装:npm install vue-router

因为在生产环境也依赖vue-router,所以安装的时候不用写-D

二、在index.ts中做如下配置:
在这里插入图片描述

/:pathMatch(.*):用于匹配所有可能的路径,起到兜底的作用,主要是为了确保所有未匹配的路径都会重定向到 /error/404,以便给用户返回一个统一的 404 错误页面。

三、挂载:

import router from "./router"
const app = createApp(App)
app.use(router)

四、【小技巧】使用snippet-generator生成代码块:
在线链接
使用教程

pinia状态管理配置

一、安装:npm install pinia
二、创建store/index.ts,代码如下:

import {
    
    createPinia} from "pinia"
const pinia = createPinia()
export default pinia

三、挂载:

import pinia from "./pinia"
const app = createApp(App)
app.use(pinia)

四、定义:

import {
    
     defineStore } from 'pinia'

const useCounterStore = defineStore('counter', {
    
    
  state: () => ({
    
    // 返回一个对象
    counter: 100
  }),
  getters: {
    
    
    doubleCounter(state) {
    
    
      return state.counter * 2
    }
  },
  actions: {
    
    
    changeCounterAction(newCounter: number) {
    
    
      this.counter = newCounter
    }
  }
})

export default useCounterStore

五、使用:

<template>
  <div class="main">
    <h2>main: {
   
   { counterStore.counter }}-{
   
   { counterStore.doubleCounter }}</h2>
    <button @click="changeCounter">修改counter</button>
  </div>
</template>

<script setup lang="ts">
import useCounterStore from '@/store/counter'

const counterStore = useCounterStore()

function changeCounter() {
      
      
  counterStore.changeCounterAction(999)
}
</script>

<style lang="less" scoped>
.main {
      
      
  color: red;
}
</style>

axios网络请求的配置

一、安装:npm install axios
二、在src/service/request/request.ts中进行axios二次封装:

import axios from 'axios'
import type {
    
     AxiosInstance } from 'axios'
import type {
    
     HYRequestConfig } from './type'

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

/**
 * 两个难点:
 *  1.拦截器进行精细控制
 *    > 全局拦截器
 *    > 实例拦截器
 *    > 单次请求拦截器
 *
 *  2.响应结果的类型处理(泛型)
 */

class HYRequest {
    
    
  instance: AxiosInstance

  // request实例 => axios的实例
  constructor(config: HYRequestConfig) {
    
    
    this.instance = axios.create(config)

    // 每个instance实例都添加拦截器
    this.instance.interceptors.request.use(
      (config) => {
    
    
        // loading/token
        return config
      },
      (err) => {
    
    
        return err
      }
    )
    this.instance.interceptors.response.use(
      (res) => {
    
    
        return res.data
      },
      (err) => {
    
    
        return err
      }
    )

    // 针对特定的hyRequest实例添加拦截器
    this.instance.interceptors.request.use(
      config.interceptors?.requestSuccessFn,
      config.interceptors?.requestFailureFn
    )
    this.instance.interceptors.response.use(
      config.interceptors?.responseSuccessFn,
      config.interceptors?.responseFailureFn
    )
  }

  // 封装网络请求的方法
  // T => IHomeData
  request<T = any>(config: HYRequestConfig<T>) {
    
    
    // 单次请求的成功拦截处理
    if (config.interceptors?.requestSuccessFn) {
    
    
      config = config.interceptors.requestSuccessFn(config)
    }

    // 返回Promise
    return new Promise<T>((resolve, reject) => {
    
    
      this.instance
        .request<any, T>(config)
        .then((res) => {
    
    
          // 单词响应的成功拦截处理
          if (config.interceptors?.responseSuccessFn) {
    
    
            res = config.interceptors.responseSuccessFn(res)
          }
          resolve(res)
        })
        .catch((err) => {
    
    
          reject(err)
        })
    })
  }

  get<T = any>(config: HYRequestConfig<T>) {
    
    
    return this.request({
    
     ...config, method: 'GET' })
  }
  post<T = any>(config: HYRequestConfig<T>) {
    
    
    return this.request({
    
     ...config, method: 'POST' })
  }
  delete<T = any>(config: HYRequestConfig<T>) {
    
    
    return this.request({
    
     ...config, method: 'DELETE' })
  }
  patch<T = any>(config: HYRequestConfig<T>) {
    
    
    return this.request({
    
     ...config, method: 'PATCH' })
  }
}

export default HYRequest

在src/service/request/index.ts代码如下:

import HYRequest from './request/request'
import {
    
     API_BASE_URL, TIME_OUT } from './request/config'
import localCache from '@/utils/cache'

const hyRequest = new HYRequest({
    
    
  baseURL: API_BASE_URL,
  timeout: TIME_OUT,
  interceptorHooks: {
    
    
    requestInterceptor: (config) => {
    
    
      const token = localCache.getCache('token')
      if (token) {
    
    
        config.headers.Authorization = `Bearer ${
      
      token}`
      }
      return config
    },
    requestInterceptorCatch: (err) => {
    
    
      return err
    },
    responseInterceptor: (res) => {
    
    
      return res.data
    },
    responseInterceptorCatch: (err) => {
    
    
      return err
    }
  }
})

export default hyRequest

四、在Main.vue中使用:

<script>
import hyRequest from "@/service"
hyRequest.get({
      
      url:"/home/multidata"}).then((res) => {
      
      
	console.log(res)
})
</script>

区分开发和生产环境

Vite提供了环境变量import.meta.env

  1. import.meta.env.MODE: {string}应用运行的模式:开发、生产
  2. import.meta.env.PROD: {boolean}应用是否运行在生产环境。
  3. import.meta.env.DEV: {boolean}应用是否运行在开发环境(永远与import.meta.env.PROD相反)。
  4. import.meta.env.SSR: {boolean}应用是否运行在server上。

有些变量/标识符在开发环境和生产环境下是不一样的,比如baseUrl="服务器地址",由于Vite会使用.env从环境目录中的下列文件加载额外的环境变量
请添加图片描述
所以可以在项目中创建.env.production.env.development文件用以存放不同环境的baseUrl
在这里插入图片描述
由于以VITE_为前缀的变量会被挂载到import.meta.env上,所以之后可以直接使用import.meta.env.VITE_BASE_URL获得各环境的base URL。此外.local文件在git提交代码的时候,不会被提交,这是因为在.gitignore配置了:

.env.local
.env.*.local

npm run build:打包
npm run preview:对打包的东西进行预览

element-plus全局引入

安装npm install element-plus --save
导入

  1. 全局引入:在main.ts中引入并挂载:
import ElementPlus from "element-plus"
import "element-plus/dist/index.css"
const app = createApp(App)
app.use(ElementPlus)

然后直接使用即可,但是不推荐这种方式,因为他打包体积大

如果使用了Volar,可以在tsconfig.json中通过compilerOptions.type指定全局组件类型,这样在写代码的时候,会提示你组件有哪些属性。(前提是进行了全局引入)

// tsconfig.json
{
    
    
  "compilerOptions": {
    
    
    // ...
    "types": ["element-plus/global"]
  }
}
  1. 按需引入:在main.ts中引入要使用的组件:
import {
    
    ElButton} from "element-plus"
const app = createApp(App)
app.component(ElButton.name,ElButton)

如果某个组件只在某个vue里使用,那么可以做局部引用,在vue中引入要使用的组件:

import {
    
    ElButton} from "element-plus"
  1. 使用插件自动引入:
    安装unplugin-vue-components 和 unplugin-auto-import这两款插件:npm install -D unplugin-vue-components unplugin-auto-import,然后把下列代码插入到你的Vite或Webpack的配置文件中就可以直接使用组件了:
// 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()],
    }),
  ],
})

// webpack.config.js或vue.config.js
const AutoImport = require('unplugin-auto-import/webpack')
const Components = require('unplugin-vue-components/webpack')
const {
    
     ElementPlusResolver } = require('unplugin-vue-components/resolvers')

module.exports = {
    
    
  // ...
  plugins: [
    AutoImport({
    
    
      resolvers: [ElementPlusResolver()],
    }),
    Components({
    
    
      resolvers: [ElementPlusResolver()],
    }),
  ],
}

各模块开发

登陆模块

一、设置界面铺满整个屏幕:

.app{
    
    
	width: 100vw;
	height: 100vh;
}

二、

猜你喜欢

转载自blog.csdn.net/CaraYQ/article/details/143351777