vue前端工程化

news/2024/4/29 4:30:07/文章来源:https://blog.csdn.net/qq_31539817/article/details/136741482

前言

本文介绍的是有关于vue方面的前端工程化实践,主要通过实践操作让开发人员更好的理解整个前端工程化的流程。

本文通过开发准备阶段、开发阶段和开发完成三个阶段开介绍vue前端工程化的整体过程。

准备阶段

准备阶段我将其分为:框架选择、规范制定、脚手架搭建。

框架选择

vue的框架有很多,有脚手架框架例如vue提供脚手架、nuxt等,还有vue版本对应的版本;UI组件库可选择性更多,element、Ant Design、Naive等,还有自封的ui组件库。

本文的实践选择的脚手架框架为:vue3+vite+typescript。

使用的UI组件库为:element组件库。

框架选择:

脚手架:vue3+vite+typescript

UI组件库:element

规范制定

规范制定主要有一下几个点

结构规范

即项目的目录规范,每个项目的文件夹命名代表的含义,公共组件和页面组件应该存在在哪,工具类,静态文件应该存放在哪个文件夹,应该如何命名等。

1.规范一:功能分离结构

作者自己取得名,即各个文件夹功能分离。

如上图所示,每个文件夹又有其含义,每个有特定含义的文件都应该放到对应的文件夹内。

api文件夹

用于存放接口请求的文件夹,内部文件命名有两种规则(这个是根据作者自身开发经验总结的)

1.api文件夹内不允许子文件夹的存在,文件名应该以路由名+api作为文件名;

2.api文件夹内可以有子文件夹,子文件夹名称应该与路由文件名同名,文件名按照其含义进行命名+api,切文件夹结构应该只允许存在二级结构;

对于第一种规则,如下图所示:

页面路由home-page下的全部请求,应该放在home-page-api文件中。这种规则适合于项目接口较少的项目,一般一个页面路由全部请求不超过20个推荐使用这种方式。

对于第二种规则:如下图所示

在api文件夹内建一个与页面路由同名的文件夹,该文件夹命名规则为页面路由子路由文件夹名+api的形式,即该子路由内的全部请求方法放到对应的api中的文件内。这种规则适用于路由页面请求方法比较多的情况下使用。

assets文件夹

文件夹要求:建于路由页面同名的文件,用于存放该路由下的图片资源,文件夹不可有三级结构,对于组件所需的图片资源,应该统一存放在一个统一的文件夹内。

components文件夹

按照组件名命名文件夹

pages-view文件夹

用于存放页面组件,pages页面路由入口,pages-view存放对应页面。具有共性的页面组件可以统一放到一个文件夹或者提到components文件夹。

例如下图所示:红色框表示的是首页路由,则绿色框怎就是对应的页面组件(关系为路由组件为页面组件提供出口,路由组件只做简单props接收和简单逻辑运算)

router

用于存放路由配置,如果路由过多建议拆分路由。

store

用于存放vuex等配置,但是项目中贡献数据不建议使用vuex而是建议存放在缓存中。

utils

用于存放工具类和工具方法

2.规范二:模块分离结构

所谓的模块聚合结构,则表示的是将api请求,页面组件,路由配置都存放到view文件夹中,router作为主配置引用子路由配置。对于根路径下的components、assets和store作用和规范一的作用一样。

此处下的pages-views、api和router文件夹下的文件名要求不太高,只要文件名有特定含义即可,但是文件夹下目录不可找过三级。

3.总结
  • 规范一:适用于小项目,协作人员少的项目,结构清晰明了,维护方便,弊端是协作性比较差。
  • 规范二:适用于中大型项目,协作人员多的项目,开发人员只要在自己的目录下开发即可,不相互影响,提交代码不容易发生冲突。

命名规范

命名规范主要有:文件和文件夹命名规范、变量&方法&计算属性&类&接口命名规范、css类名命名规范、html组件引用规范&导入组件名和组件名规范。

1.文件和文件夹命名规范

文件和文件夹命名:全为小写字母,多单词之前用横线隔开,主要是为了适配window和mac,windows不区分大小写,mac区分大小写。

2.变量&方法&类&接口命名规范

变量&方法&计算属性:使用小驼峰命名法,其中方法末尾需要加Fn,计算属性末尾添加Computed(这个是作者个人习惯)。

类&接口:使用大驼峰命名法,其中接口末尾加Types(作者个人习惯,用于区分类)。

3.css类名命名规范——BEM

使用BEM命名规范。

BEM(Block,Element,Modifier)是一种基于组件的web开发思想。这种开发思想主张将用户界面划分为独立的块。这使得网页开发变得简单快捷,即使是复杂的用户界面,也可以重用现有的代码,而无需复制和粘贴。

Block - 一个功能独立的页面组件,可以重用。

  • block名称描述了此模块的用途,它是什么?
  • 各个模块可以相互嵌套,嵌套层级数量不受限

例如:

<!-- `header` block -->
<header class="header"><!-- Nested `logo` block --><div class="logo"></div><!-- Nested `search-form` block --><form class="search-form"></form>
</header>

header 模块嵌套了logo模块和搜索表单模块

Element - 块的组成模块,不能与块分开使用,也不能自己单独使用。

  • element名称描述了在这模块中的用途,它是什么?
  • element名称的语法结构为  **block-name__element-name**,使用双下划线将block名称和element名称连接起来。
  • element 元素彼此之间可以相互嵌套,嵌套层级数量不受限
  • 一个element元素里可以嵌套包含一个block块,这就意味着,element名称定义不能为多层级结构,如 block__elem1__elem2 ,这种命名是不被允许的。

例如:

<form class="search-form"><div class="search-form__content"><input class="search-form__input"><button class="search-form__button">Search</button></div>
</form>

search-forminput,search-formbutton,search-form__content 即为element元素。

search-form__content 元素中嵌套了element元素。

但是search-form__content__input 这种多层级命名element元素是不被允许的,类名过长,层级结构过多,不清晰。

Modifier - 定义block块或element元素的外观、状态或行为。

  • modifier 的名称一般描述了block块或element元素的外观,它的大小?它的状态?它的颜色
  • modifier 的名称语法结构为:block-name_modifier-name;block-name__element-name_modifier-name
  • 一般使用单下划线将它跟block元素或者element元素连接起来;布尔形式,区分是或不是的状态,完整的语法结构为:block-name_modifier-name;block-name__element-name_modifier-name

例如:

<form class="search-form search-form_theme_islands"><input class="search-form__input"><!-- The `button` element has the `size` modifier with the value `m` --><button class="search-form__button search-form__button_disabled">Search</button>
</form>

search-form__button_disabled 这种命名结构是布尔形式。

key-value键值对的形式,区分不同的状态。完整的语法结构则为:

  • block-name_modifier-name_modifier-value
  • block-name__element-name_modifier-name_modifier-value

例如:

<form class="search-form search-form_theme_islands"><input class="search-form__input"><!-- The `button` element has the `size` modifier with the value `m` --><button class="search-form__button search-form__button_size_m">Search</button>
</form>

search-form__button_size_m 这种命名结构就是键值对的形式

  • modifier 不能被单独使用,必须与block元素或者element元素联合使用。因为一个modifier就是用来描述此元素的外观、大小、一个实体的状态。

 BEM的优点与缺点?

优点

  • 结构简单,一目了然
  • 组件化,代码复用
  • 不使用标签选择器,避免父级元素内的标签的受影响。举个例子,商品详情页是允许商家自定义标签的,那么商家展示区域标签的祖先元素,一旦用标签选择器定义了样式,子子孙孙都要背负.

例如,将这个网页拆分成BEM的写法

无BEM写法:

<section><h1>Sterling Calculator</h1><form action="process.php" method="post"><p>Please enter an amount: (e.g. 92p, &pound;2.12)</p><p><input name="amount"> <input type="submit" value="Calculate"></p></form>
</section>

BEM 写法:

<section class="widget"><h1 class="widget__header">Sterling Calculator</h1><form class="widget__form" action="process.php" method="post"><p>Please enter an amount: (e.g. 92p, &pound;2.12)</p><p><input name="amount" class="widget__input widget__input_amount"> <input type="submit" value="Calculate" class="widget__input widget__input_submit"></p></form>
</section>

元素清单:

  • widget
  • widget__header
  • widget__form
  • widget__input

这样就形成了一个可复用的块

注意其中的 widget__input_amountwidget__input_submit为Modifier

缺点

  • 类名变的更长,一个元素可能拥有多个class
  • id选择器无用武之地
  • class命名不能重复
  • Block的抽象至关重要

谁适用于BEM

项目复杂,复用模块较多,多人协作团队使用。

4.html组件引入规范&导入组件名和组件名规范

html组件引入的组件名称使用大驼峰,带结束标签

导入组件名使用大驼峰,

import TipsDialog from '../tips-dialog/index.vue'

组件名规范使用大驼峰

defineOptions({

    name: 'CompModel'

})

代码规范

代码规范主要是代码校验和自动格式化以及git提交规范校验。

1.代码校验和自动格式化

代码校验和代码格式化两个是相辅相成的,通过插件对代码进行校验并自动格式化成符合要求的格式。要实现需要依赖两个插件eslint和prettier。

配置eslint

下载依赖

yarn add -D eslint eslint-plugin-vue

npx eslint --init

init 命令会自动生成 .eslintrc.js

修改配置为:

module.exports = {root: true,ignorePatterns: ['node_moduls/*'],env: {browser: true,es2021: true,node: true,commonjs: true},extends: ['eslint:recommended', 'plugin:vue/essential', 'prettier'],overrides: [],parserOptions: {ecmaVersion: 'latest',sourceType: 'module'},plugins: ['vue', 'prettier'],rules: {'linebreak-style': ['error', 'unix'],'no-multiple-empty-lines': [1, { max: 2 }], //空行最多不能超过2行'vue/multi-word-component-names': 'off' //vue组件名去掉多单词限制}
}

配置文档

规则 | Rules_Eslint_参考手册_非常教程 (verydoc.net)

配置代码风格工具prettier

安装

yarn add -D prettier eslint-config-prettier eslint-plugin-prettier

创建 .prettierrc

{"useTabs": false,"tabWidth": 4,"printWidth": 80,"singleQuote": true,"trailingComma": "none","semi": false,"endOfLine": "lf"
}

官方地址

Configuration File · Prettier 中文网

2.git提交规范

相关配置在这篇文章,内容有点多

git提交规范-CSDN博客

api和数据规范

这个部分需要后端配置,后端返回的code需要代表一定含义,这样才能做统一数据处理,例如token失效的code为多少,接口超时的code或者接口报错的返回code为多少。

1.api封装

这个部分比较灵活,需要按照公司的业务或者开发的个人习惯进行封装,以下是一个例子:

import axios, { AxiosRequestConfig } from 'axios'
import qs from 'qs'
import { getToken } from './userInfo/token'
import { subscribe, MetaDataHelper } from '@gogoal/fund-utils'
import { blob2File } from './tools'
import { isFileList, isObject } from './types'const SUCCESS_CODE = 0
const service = axios.create({// timeout: 200000, // request timeout
})
// response interceptor
service.interceptors.response.use((response) => {const res = response.dataif (res.code === SUCCESS_CODE) {return res.data} else {subscribe.notify('xhr-fail', res)console.log('xhr-fail response', response)return Promise.reject(res)// if (res.code == '1100' || res.code == '1103') {//     dealLogout()// } else {//     return Promise.reject(res)// }}},(error) => {return Promise.reject({code: 1,message: '服务器错误',error})}
)interface RequestDataParams extends AxiosRequestConfig {needToken?: boolean /* 是否需要token */needToString?: boolean /* 是否需要将参数转成token */data?: Record<string, any>headers?: Record<string, any>config?: Record<string, any>
}
// 请求接口数据
// interface ResponseData<T = any> {
//     code: number
//     data: T
//     message: string
// }const getData = function <T>({url = '',params = {},data,method = 'GET',needToken = false,needToString = false,headers,config
}: RequestDataParams): Promise<T> {if (needToken) {const token = getToken()params.token = token}const _params = {url,method}// deleteEmptyProperty(params);if (['POST', 'PUT', 'PATCH'].includes(method.toUpperCase())) {Object.assign(_params, {data: needToString ? qs.stringify(data) : data,params: params})} else {Object.assign(_params, {params: params})}if (headers) {Object.assign(_params, {headers})}if (config) {Object.assign(_params, {config})}return service(_params)
}/*** @description 公用 GET 请求*/
const get = function <T>({url,params,needToken = false,needToString = false
}: RequestDataParams) {return getData<T>({url,params,needToken,method: 'GET',needToString})
}/*** @description 公用 POST 请求*/
const post = function <T>({url,params,data,needToken = false,needToString = false
}: RequestDataParams) {return getData<T>({url,params,data,needToken,method: 'POST',needToString})
}
const upload = function ({ url, data, params = {}, needToken = false }) {// debuggerconst _url = url || '/file/comm_upload_file'const _data = new FormData()// 将得到的文件流添加到FormData对象Object.keys(data).forEach((_k) => {const _p = data[_k]if (isObject(_p)) {_data.append(_k, JSON.stringify(_p))} else if (isFileList(_p)) {Array.from(_p).forEach((res) => {_data.append(_k, res)})} else if (isArray(_p)) {_p.forEach((res) => {getType(res) == 'File' && _data.append(_k, res)})} else {_data.append(_k, _p)}})return getData({url: _url,method: 'POST',data: _data,params,needToken})
}function formatFile(query) {const _params = new FormData()// 将得到的文件流添加到FormData对象Object.keys(query).forEach((_k) => {const _p = query[_k]if (isObject(_p)) {// _params.append(_k, JSON.stringify(_p))_params.append(_k, _p)} else if (isFileList(_p)) {_p.forEach((res) => {_params.append(_k, res)})} else {_params.append(_k, _p)}})return _params
}
const downloadBlob = function (url, fileName) {const xhr = new XMLHttpRequest()xhr.open('get', url, true)xhr.responseType = 'blob' // 返回类型blob// 定义请求完成的处理函数,请求前也可以增加加载框/禁用下载按钮逻辑xhr.onload = function () {// 请求完成if (this.status === 200) {// 返回200const blob = this.responseblob2File(blob, fileName)}}// 发送ajax请求xhr.send()
}type File = {url: stringquery?: stringparams?: stringfileName: stringconfig: any
}
const downloadFile = ({ url, query, params, fileName, config = {} }: File) => {const _config: AxiosRequestConfig = Object.assign({method: 'post',headers: {'Content-Type': 'application/x-www-form-urlencoded' // 请求的数据类型为form data格式},responseType: 'blob'},config)let _url = url || '/file_export/excel/common'if (query) {_url += `?${qs.stringify(query)}`}_config.url = _url_config.headers['X-Pro'] = MetaDataHelper.getId()if (params) {_config.data = qs.stringify(params)}return new Promise<void>((resolve, reject) => {axios(_config as AxiosRequestConfig).then((response) => {const { data, message } = responseif (!data && message) {reject(response)return}blob2File(data, fileName)resolve()}).catch((error) => {reject(error)})})
}export default getDataexport {service /* 导出方便修改默认参数 */,get,post,upload,downloadFile,downloadBlob,formatFile
}

使用:

const response = await service({url: '/api/v1/zyfp_account_home/bind_mobile',method: 'post',data: {source: 'login',mobile: bindForm.value.mobile,sms_code: bindForm.value.sms_code}})
2.数据规范

这个需要后端定,主要是接口返回的数据格式,例如返回code规范,返回对象规范等,这个需要根据具体情况具体分析。

脚手架搭建

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

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于单片机HX711电子秤称重控制设计

**单片机设计介绍&#xff0c;基于单片机HX711电子秤称重控制设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机HX711的电子秤称重控制设计是一个融合了单片机技术、称重传感器技术和显示技术的综合性项目。其设计目…

C 语言贪吃蛇源码解析

贪吃蛇是一款经典的电子游戏&#xff0c;玩家控制一条不断成长的蛇&#xff0c;需要避免撞到自己的身体或者游戏边界&#xff0c;同时吃掉出现在屏幕上的食物以增长身体长度。 下面是一个简单的贪吃蛇游戏的C语言实现&#xff0c;使用了标准输入输出库conio.h和时间库windows.h…

GTC 2024 火线评论:DPU 重构文件存储访问

编者按&#xff1a;英伟达2024 GTC 大会上周在美国加州召开&#xff0c;星辰天合 CTO 王豪迈在大会现场参与了 GPU 与存储相关的最新技术讨论&#xff0c;继上一篇《GTC 2024 火线评论&#xff1a;GPU 的高效存储利用》之后&#xff0c;这是他发回的第二篇评论文章。 上一篇文章…

农村分散式生活污水分质处理及循环利用技术指南

标准已完成意见征集&#xff1a; 本文件给出了农村分散式生活污水分质处理及循环利用的总则、污水收集、污水分质处理、资源化利用、利用模式、运维管理等的指导。 本文件适用于农村分散式生活污水分质处理及循环利用的设施新建、扩建和改建工程的设计、施工与运维。 注:本文件…

微服务demo(二)nacos服务注册与集中配置

环境&#xff1a;nacos1.3.0 一、服务注册 1、pom&#xff1a; 移步spring官网https://spring.io&#xff0c;查看集成Nacos所需依赖 找到对应版本点击进入查看集成说明 然后再里面找到集成配置样例&#xff0c;这里只截一张&#xff0c;其他集成内容继续向下找 我的&#x…

蓝桥杯刷题计划-洛谷-持续更新

P8598 [蓝桥杯 2013 省 AB] 错误票据 题目 #include <bits/stdc.h> #define endl \n #define int long long #define INF 0x3f3f3f3f3f const int N 1000010; using namespace std; int arr[N]; signed main() {int N;cin>>N;int idx;while(cin>>arr[idx…

数据库审计和安全

互联网、云计算、物联网等新技术的应用&#xff0c;数据安全面临前所未有的挑战!我国信息安全已从终端安全、网络安全&#xff0c;发展到数据安全建设阶段。数据安全的核心是对“数据”全方位的安全防护&#xff0c;其产品及解决方案直接涉及国家和企业的核心机密 核心数据库存…

win10微软拼音输入法 - bug - 在PATH变量为空的情况下,无法输入中文

文章目录 win10微软拼音输入法 - bug - 在PATH变量为空的情况下&#xff0c;无法输入中文概述笔记实验前提条件100%可以重现 - 无法使用win10拼音输入法输入中文替代的输入法软件备注END win10微软拼音输入法 - bug - 在PATH变量为空的情况下&#xff0c;无法输入中文 概述 在…

ES6学习之路:迭代器Iterator和生成器Generator

迭代器 一、知识背景 什么是迭代器 迭代器就是在一个数据集合中不断取出数据的过程迭代和遍历的区别 遍历是把所有数据都取出迭代器注重的是依次取出数据&#xff0c;它不会在意有多少数据&#xff0c;也不会保证能够取出多少或者能够把数据都取完。比如斐波那契额数列&#…

linux nginx配置ssl, 实现https+ip访问

mkdir sslZhengShu openssl req -newkey rsa:2048 -nodes -keyout ca.key -out ca.csr openssl x509 -req -days 365 -in ca.csr -signkey ca.key -out ca.crt openssl genrsa -out server.key 2048 openssl req -new -key server.key -out server.csr 和之前输入一样即可 …

Python基本运算

1.逻辑运算符 第四行会有黄色的下划线是因为这个不是系统推荐的写法&#xff0c;系统推荐的是第五行的链式比较&#xff1b; 2.短路求值 对于and而言&#xff0c;左边的语句是false&#xff0c;那么整体一定是false,右边的表达式就不会进行计算&#xff1b; 对于or而言&…

FTP 文件传输服务

FTP连接 控制连接&#xff1a;TCP 21&#xff0c;用于发送FTP命令信息 数据连接&#xff1a;TCP 20&#xff0c;用于上传、下载数据 数据连接的建立类型&#xff1a; 主动模式&#xff1a;服务端从 20 端口主动向客户端发起连接 被动模式&#xff1a;服务端在指定范围…

平台介绍-搭建赛事运营平台(3)

上文介绍了品牌隔离的基本原理&#xff0c;就是通过不同的前端和微服务来实现。但是确实很多功能是类似的&#xff0c;所以从编程角度还是有些管理手段的。 前端部分&#xff1a;前端部分没有什么特别手段&#xff0c;就是两个独立的项目工程&#xff0c;分别维护。相同的部分复…

神策数据参与制定首份 SDK 网络安全国家标准

国家市场监督管理总局、国家标准化管理委员会发布中华人民共和国国家标准公告&#xff08;2023 年第 13 号&#xff09;&#xff0c;全国信息安全标准化技术委员会归口的 3 项国家标准正式发布。其中&#xff0c;首份 SDK 国家标准《信息安全技术 移动互联网应用程序&#xff0…

2核4G服务器租用价格表,阿里云/腾讯云/华为云/京东云

当前最新2核4G云服务器多少钱&#xff1f;165元一年&#xff0c;30元3个月。阿里云2核4G服务器165元一年&#xff0c;30元3个月、腾讯云2核4G5M服务器165元一年、京东云2核4G云主机126元1年&#xff0c;华为云也提供2核4G配置云服务器。阿腾云atengyun.com整理2024年最新云服务…

【NLP笔记】预训练+Prompt Tuning新范式之LLM时代(GPT3...)

文章目录 概述GPT3 【参考链接】 一张图总结大语言模型的技术分类、现状和开源情况 大语言模型LLM微调技术&#xff1a;Prompt Tuning A Survey of Large Language ModelsThe Practical Guides for Large Language ModelsGPT3&#xff1a;Language Models are Few-Shot Learner…

行存储与列存储:大数据存储方案的选择与优缺点分析

随着大数据时代的来临&#xff0c;数据的规模和复杂性呈指数级增长&#xff0c;传统的关系数据库已经不再适应这一巨大的存储量和计算要求。在大数据存储领域&#xff0c;行存储和列存储成为两种备受关注的存储方案。本文将探讨行存储和列存储的定义、优缺点&#xff0c;并结合…

python pytz是什么

pytz模块常用于时区的转换&#xff0c;常常配合datetime一起使用。我们知道datetime除了data方法生成的时间是没有时区概念&#xff0c;其他如time、datetime等都是有时区概念&#xff0c;即指定了tzinfo信息。 >>> import datetime >>> datetime.datetime.n…

骗子查询系统源码

源码简介 小权云黑管理系统 V1.0 功能如下&#xff1a; 1.添加骗子&#xff0c;查询骗子 2.可添加团队后台方便审核用 3.在线反馈留言系统 4.前台提交骗子&#xff0c;后台需要审核才能过 5.后台使用光年UI界面 6.新增导航列表&#xff0c;可给网站添加导航友链 7.可添加云黑类…

C语言运算符和表达式——增1和减1运算符

目录 增1和减1运算符 一元运算符 前缀增1/减1运算符 后缀增1/减1运算符 前缀与后缀对变量和表达式的影响 稍微复杂一点的例子 增1和减1运算符的优缺点 增1和减1运算符 增1运算符&#xff08;Increment&#xff09; *使变量的值增加1个单位 减1运算符&#xff08;Decre…