当前位置:首页 > 冰箱 > 文章正文

Vue3.4+Element-plus+Vite通用后台治理系统

编辑:[db:作者] 时间:2024-08-24 23:58:32

首页

技能栈

Vue3.4+Element-plus+Vite通用后台治理系统

技能栈

描述

官网

Vue3

渐进式JavaScript框架

https://cn.vuejs.org/

Element-plus

基于 Vue 3,面向设计师和开拓者的组件库

https://element-plus.org/zh-CN/

Vite

前端构建工具

https://vitejs.cn/vite3-cn/

Pinia

符合直觉的 Vue.js 状态管理库

https://pinia.web3doc.top/

Echarts

一个基于 JavaScript 的开源可视化图表库

https://echarts.apache.org/zh/index.html

VueUse

基于Vue组合式API的实用工具集

https://www.vueusejs.com/

animate.css

一个现成的跨浏览器动画库

https://animate.style/

wangEditor

开源 Web 富文本编辑器,开箱即用,配置大略

https://www.wangeditor.com/

项目基本配置

项目全局配置

代码统一规范

Eslint:语法规则和代码风格检讨Prettier:美化代码样式Stylelint: CSS 统一规范和代码检测

.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': 'off', // 禁止定义未利用的变量 '@typescript-eslint/prefer-ts-expect-error': 'off', // 禁止利用 @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', // 对模板中的自定义组件逼迫实行属性命名样式 },}

.prettierrc.json

{ "singleQuote": false, "semi": false, "bracketSpacing": true, "htmlWhitespaceSensitivity": "ignore", "endOfLine": "auto", "trailingComma": "all", "tabWidth": 2}

.stylelintrc.cjs

// @see https://stylelint.bootcss.com/// 美化css书写的样式module.exports = { extends: [ 'stylelint-config-standard', // 配置stylelint拓展插件 'stylelint-config-html/vue', // 配置 vue 中 template 样式格式化 'stylelint-config-standard-scss', // 配置stylelint scss插件 'stylelint-config-recommended-vue/scss', // 配置 vue 中 scss 样式格式化 'stylelint-config-recess-order', // 配置stylelint css属性书写顺序插件, 'stylelint-config-prettier', // 配置stylelint和prettier兼容 ], overrides: [ { files: ['/.(scss|css|vue|html)'], customSyntax: 'postcss-scss', }, { files: ['/.(html|vue)'], customSyntax: 'postcss-html', }, ], ignoreFiles: [ '/.js', '/.jsx', '/.tsx', '/.ts', '/.json', '/.md', '/.yaml', ], / null => 关闭该规则 always => 必须 / rules: { 'value-keyword-case': null, // 在 css 中利用 v-bind,不报错 'no-descending-specificity': null, // 禁止在具有较高优先级的选择器后涌现被其覆盖的较低优先级的选择器 'function-url-quotes': 'always', // 哀求或禁止 URL 的引号 "always(必须加上引号)"|"never(没有引号)" 'no-empty-source': null, // 关闭禁止空源码 'selector-class-pattern': null, // 关闭逼迫选择器类名的格式 'property-no-unknown': null, // 禁止未知的属性(true 为不许可) 'block-opening-brace-space-before': 'always', //大括号之前必须有一个空格或不能有空缺符 'value-no-vendor-prefix': null, // 关闭 属性值前缀 --webkit-box 'property-no-vendor-prefix': null, // 关闭 属性前缀 -webkit-mask 'selector-pseudo-class-no-unknown': [ // 不许可未知的选择器 true, { ignorePseudoClasses: ['global', 'v-deep', 'deep'], // 忽略属性,修正element默认样式的时候能利用到 }, ], }, }

按钮主题色

在style/element/index.scss中配置

/ 只须要重写你须要的即可 /@forward 'element-plus/theme-chalk/src/common/var.scss' with ($colors: ( 'primary': (// 主色 'base':#0F5197, ), 'success': ( // 成功色 'base': #199D33, ), 'info': ('base': #4e4f51, ), 'warning': ( // 警告色 'base': #e26f03, ), 'danger': ( // 危险色 'base': #de2e06, ), 'error': ( // 危险色 'base': #de2e06, ), ));

vite.config.ts 配置

css: { preprocessorOptions: { scss: { javascriptEnabled: true, // 自动导入定制化样式文件进行样式覆盖 additionalData: ` @use "@/styles/element/index.scss" as ; @use "@/config/public.scss" as ; `, }, }, }, 项目集成

mock.js

mock.js 天生随机数据,拦截 Ajax 要求

参考:mock.js 官网

安装

pnpm install -D vite-plugin-mock mockjs

vite.config.ts 配置

import { viteMockServe } from 'vite-plugin-mock' plugins: [ viteMockServe({ mockPath: "./src/mock", // localEnabled: true, }) ]

UnoCSS

UnoCSS 是即时原子 CSS 引擎,普通易懂的讲,便是在template模版中书写css

参考:UnoCSS中文文档

安装

pnpm install -D unocss

vite.config.ts 配置

复制代码// vite.config.tsimport UnoCSS from 'unocss/vite'export default { plugins: [ UnoCSS({ / options / }), ],}

main.js中

// main.jsimport "virtual:uno.css"

uno.config.js中可自行配置

// uno.config.tsimport { defineConfig, presetAttributify, presetIcons, presetTypography, presetUno, presetWebFonts, transformerDirectives, transformerVariantGroup,} from "unocss"export default defineConfig({ shortcuts: { "flex-center": "flex justify-center items-center", "flex-x-center": "flex justify-center", "flex-y-center": "flex items-center", "wh-full": "w-full h-full", "flex-x-between": "flex items-center justify-between", "flex-x-end": "flex items-center justify-end", "absolute-lt": "absolute left-0 top-0", "absolute-rt": "absolute right-0 top-0 ", "fixed-lt": "fixed left-0 top-0", "b1-red": "b-1 border-solid b-red", }, theme: { colors: { primary: "var(--el-color-primary)", primary_dark: "var(--el-color-primary-light-5)", }, }, presets: [ presetUno(), presetAttributify(), presetIcons(), presetTypography(), presetWebFonts({ fonts: { // ... }, }), ], transformers: [transformerDirectives(), transformerVariantGroup()],})

VsCode安装提示插件

插件效果预览

canvas 基本利用

这里通过一个案例对canvas展示了一个基本利用,仅供参考,以业务为主。

功能代码附上

<script setup lang="ts">import debounce from "lodash/debounce"import { message } from "@/Hooks/Element-plus"import { nextTick, onMounted, ref, watch } from "vue"import cat1 from "../../assets/image/cat1.png"import cat2 from "../../assets/image/cat2.png"import dog1 from "../../assets/image/dog1.png"import dog2 from "../../assets/image/dog2.png"import canvaas_bg from "../../assets/image/canvas.webp"const picList = [dog1, cat2, dog2, cat1] as string[]const colorList = [ "#fbd04f", "#a8a1dc", "#83b6da", "#92c7ba", "#f6a356 ", "#5e5f61", "#f98787 ",] as string[]// canvas实例const canvas = ref()// 画布const ctx = ref()// 初始化背景图片const initCanvas_bg = async () => { await new Promise((resolve, reject) => { // 初始化画布 ctx.value = canvas.value.getContext("2d")! const width = 700 const height = 800 canvas.value.width = width canvas.value.height = height const img = new Image() img.onload = () => { ctx.value.drawImage(img, 0, 0, canvas.value.width, canvas.value.height) // 绘制第一张图片 resolve("ok") } img.src = canvaas_bg img.onerror = () => { reject("失落败") } })}onMounted(async () => { try { // 初始化背景canvas await initCanvas_bg() } catch (err: any) { message("error", "初始化背景失落败") }})// 选择图片const pic_val = ref("")const imgIndex = ref<number>()const selectImg = async (pic: string, i: number) => { pic_val.value = pic imgIndex.value = i}// 选择背景色const color_val = ref("")const colorIndex = ref<number>()const selectBg = async (color: string, i: number) => { color_val.value = color colorIndex.value = i}// 输入值改变const input_val = ref("")watch( [() => pic_val.value, () => color_val.value, () => input_val.value], debounce(async (newVal) => { try { // 初始化背景canvas await initCanvas_bg() let [newPic_val, newColor_val, newInut_val] = newVal // 先看背景颜色有没有 if (newColor_val) { // 设置添补色 ctx.value.fillStyle = newColor_val // 绘制正方形 ctx.value.fillRect(99, 75, 342, 477) // 再看文本 if (newInut_val) { ctx.value.fillStyle = "black" ctx.value.font = `35px 隶书` ctx.value.fillText("名:" + newInut_val, 190, 180) } // 先铺背景在画图片 if (newPic_val) { const img = new Image() img.src = newPic_val img.onload = () => { ctx.value.drawImage(img, 100, 202, 350, 350) // 绘制选择的图片 } } } else { // 再看文本 if (newInut_val) { ctx.value.fillStyle = "black" ctx.value.font = `35px 隶书` ctx.value.fillText("名:" + newInut_val, 190, 180) } // 先铺背景在画图片 if (newPic_val) { const img = new Image() img.src = newPic_val img.onload = () => { ctx.value.drawImage(img, 100, 202, 350, 350) // 绘制选择的图片 } } } } catch (err: any) { message("error", "初始化背景失落败") } }, 100),)// 导出图片const outPic = () => { let base64 = canvas.value.toDataURL() let link = document.createElement("a") link.textContent = "download image" link.href = base64 link.download = "mypainting.jpeg" link.click()}</script> 功能封装

Svg利用

// <template>中<SvgIcon icon="" width="15px" height="15px" color="#fff" />

//vite中自行调度svg图标的储存位置 createSvgIconsPlugin({ iconDirs: [path.resolve(process.cwd(), "src/assets/svgs")], symbolId: "icon-[dir]-[name]", }),

image.png

svg图标存放位置为 assets/svgs

WangEditor编辑器集成

官网

// 父组件中<template> <WangEditor v-model="editVal" height="calc(100vh - 180px)" /></template><script setup lang="ts">import { ref, watchEffect } from "vue"//初始值const editVal = ref("Hello! WangEditor")watchEffect(() => { console.log(editVal.value)})</script>

<template> <div class="wang_edit" :class="{ dark: useSetting.dark }"> <Toolbar id="toolbar-container" :editor="editorRef" :defaultConfig="toolbarConfig" mode="default" /> <Editor id="editor-container" v-model="valueHtml" :defaultConfig="editorConfig" mode="default" @onCreated="handleCreated" /> </div></template><script setup lang="ts">import { useSettingStore } from "@/stores/modules/setting"import "@wangeditor/editor/dist/css/style.css" // 引入 cssimport { onBeforeUnmount, ref, shallowRef, onMounted } from "vue"import { Editor, Toolbar } from "@wangeditor/editor-for-vue"const useSetting = useSettingStore()const props = withDefaults( defineProps<{ height: string }>(), { height: "560px", },)const valueHtml = defineModel()// 编辑器实例,必须用 shallowRefconst editorRef = shallowRef()const toolbarConfig = {}const editorConfig = { placeholder: "请输入内容...", MENU_CONF: { uploadImage: { // 自定义图片上传 async customUpload(file: any, insertFn: any) { console.log(file, insertFn) // 调用后端接口,上传图片 // 拿到上传路劲插入编辑器 // insertFn(url) }, }, },}// 组件销毁时,也及时销毁编辑器onBeforeUnmount(() => { const editor = editorRef.value if (editor == null) return editor.destroy()})const handleCreated = (editor: any) => { editorRef.value = editor // 记录 editor 实例,主要!
}</script><style scoped lang="scss">.wang_edit { border: 1px var(--el-border-color-dark) solid; border-radius: 5px; &.dark { --w-e-textarea-bg-color: #333; --w-e-toolbar-bg-color: #333; --w-e-toolbar-color: gray; --w-e-textarea-color: #fff; } #toolbar-container { border-bottom: 1px solid var(--el-border-color-dark); border-top-right-radius: 5px; border-top-left-radius: 5px; } #editor-container { height: v-bind("props.height") !important; overflow: hidden; border-bottom-right-radius: 5px; border-bottom-left-radius: 5px; }}</style>

项目运行

项目启动

# 安装 pnpm npm install pnpm -g # 安装依赖pnpm install # 项目运行pnpm run dev

项目语法检讨

#语法检讨pnpm run lint#语法修复pnpm run fix#css美化pnpm run format

项目打包

pnpm run build✍️ 写在末了

本篇从项目规范,项目运行,项目打包,详细讲述基于Vue3.4+Element-plus技能栈0到1搭建简洁,易懂的前端后台管理框架。
如有问题欢迎指出。

sjxj_天下学习室一起风雨并肩行sjxj只为兄弟情,忠肝义胆为心无愧生平只为sjxj

本站所发布的文字与图片素材为非商业目的改编或整理,版权归原作者所有,如侵权或涉及违法,请联系我们删除,如需转载请保留原文地址:http://www.baanla.com/bx/36165.html

XML地图 | 自定链接

Copyright 2005-20203 www.baidu.com 版权所有 | 琼ICP备2023011765号-4 | 统计代码

声明:本站所有内容均只可用于学习参考,信息与图片素材来源于互联网,如内容侵权与违规,请与本站联系,将在三个工作日内处理,联系邮箱:123456789@qq.com