前端规范——前端代码提交篇(2)


Vue 集成开发环境。

参考资料:

简介

基于 vue-cli@3.0,增加如下基本功能(后面是对应的说明文档或配置文件):

目录结构说明

  - src - 主业务代码目录
    - api - 数据的请求方法
    - assets - 共用的静态资源
    - components - 共用的组件
    - mock - 模拟接口数据
    - router - 路由配置
    - store - 全局的状态管理
    - styles - 全局的样式配置
    - utils - 工具函数存放目录
    - views - 主业务的页面路径
    - tests - 测试类目录
    - main.js - 入口文件

  - .env - 环境变量配置文件
  - .eslintrc.js - eslint 配置文件
  - .svnignore - svn 忽略文件
  - .babel.config.js - babel 编译配置文件
  - jest.config.js - jest 测试配置文件
  - perttier.config.js - perttier 配置文件
  - vue.config.js - vue-cli 的配置文件

开发流程与规范

流程

  1. 根据原型图/设计图进行路由设计(不写代码,只是画出路由的草稿图)
  2. 根据原型图/设计图将页面进行组件的划分(简单的列出各组件之前的关系草稿图)
  3. 写路由配置与基础的入口组件(此时不带任何的业务)
  4. 依次按照“父组件,子组件”顺序编写基础的页面布局(先不写交互逻辑)
  5. 布局完成后,开始设计/思考组件数据存储/交互方式,如:data props store
  6. 开始编写组件的交互逻辑(注意保持单一职责原则,考虑如何让组件间的关系解耦)
  7. 涉及到接口交互时,编写 mock 数据进行模拟交互
  8. 然后优化交互体验,增加一些过渡效果
  9. 最后进行与后端的接口联调,数据结构的调整等

规范

为了保护项目的可维护性,可扩展性以及高效的编码,编写方式务必保持一致。

以下规则不包含所有的规则,例如一些默认规则。

单一职责

对所有的组件,指令,过滤器,接口请求方法等应用单一职责原则(SRP)

  • 坚持每个组件或者模块只做一件事。
  • 坚持把文件大小限制在 400 行以内。
  • 坚持定义小函数,考虑在 75 行以内。
文件命名

保持不同类型的文件命名风格一致。

  • 组件名使用多个单词,例如组件名带上该模块的前缀。
  • 在描述性名字中,用横杠来分割单词。
  • 尽量使用功能的特性去命名。
代码编写
JS
  • 坚持使用大写驼峰来命名类。
  • 坚持使用 const 声明变量。
  • 坚持使用小写驼峰来命名属性与方法。
  • 坚持将自定义的模块导入与第三方的模块导入中间空一行。
  • 坚持在非头部的注释上面增加一行空行。
CSS
  • 坚持使用类名去命名样式。
  • 坚持使用公共的样式类,避免重复的样式属性。
  • 坚持在每个组件使用一个容器类包含所有的子类。
  • 坚持在父子组件之间不发生样式类名的重复。
HTML 规范
页面语言 LANG

推荐使用属性值 cmn-Hans-CN(简体, 中国大陆),但是考虑浏览器和操作系统的兼容性,目前仍然使用 zh-CN 属性值。注意:lang="en"会导致一些翻译问题 参考资料

<html lang="zh-CN">
元素标签及闭合

为了能让浏览器更好的解析代码以及能让代码具有更好的可读性,有如下约定:

  • 所有具有开始标签和结束标签的元素都要写上起止标签,某些允许省略开始标签或和束标签的元素亦都要写上。

  • 空元素标签都不加 “/” 字符

  • 元素属性

    • 元素属性值使用双引号语法
    • 元素属性值可以写上的都写上
  • 特殊字符引用:文本可以和字符引用混合出现。这种方法可以用来转义在文本中不能合法出现的字符。
    在 HTML 中不能使用小于号 “<” 和大于号 “>”特殊字符,浏览器会将它们作为标签解析,若要正确显示,在 HTML 源代码中使用字符实体

    <!-- 推荐 -->
    <a href="#">more&gt;&gt;</a>
    
    <!-- 不推荐 -->
    <a href="#">more>></a>
    
代码注释
  • 单行注释
    一般用于简单的描述,如某些状态描述、属性描述等
    注释内容前后各一个空格字符,注释位于要注释代码的上面,单独占一行
    推荐:

    <!-- Comment Text -->
    <div>...</div>
    
  • 模块注释
    一般用于描述模块的名称以及模块开始与结束的位置
    注释内容前后各一个空格字符,<!-- S Comment Text --> 表示模块开始,<!-- E Comment Text --> 表示模块结束,模块与模块之间相隔一行
    推荐写法:

    <!-- S Comment Text A -->
    <div class="mod_a">
        ...
    </div>
    <!-- E Comment Text A -->
    
    <!-- S Comment Text B -->
    <div class="mod_b">
        ...
    </div>
    <!-- E Comment Text B -->
    
  • 嵌套注释

    <!-- S Comment Text A -->
    <div class="mod_a">
    
        <div class="mod_b">
            ...
        </div>
        <!-- /mod_b -->
    
        <div class="mod_c">
          ...
        </div>
        <!-- /mod_c -->
    
    </div>
    <!-- E Comment Text A -->
    
其他
  • 纯数字输入框:使用 type=“tel” 而不是 type=“number”
  • 代码嵌套:元素嵌套规范,每个块状元素独立一行,内联元素可选;段落元素与标题元素只能嵌套内联元素
  • 坚持考虑尽可能的扁平化布局。
  • 坚持使用语义化的标签,而不是为了该标签的样式。
  • 坚持将带计算逻辑的模版变量转换为 computed 或者 通用的 filters
  • 避免使用内联样式。
图片规范
图片格式

常见的图片格式有 GIF、PNG8、PNG24、JPEG、WEBP,根据图片格式的特性和场景需要选取适合的图片格式。

内容图
内容图多以商品图等照片类图片形式存在,颜色较为丰富,文件体积较大

  • 优先考虑 JPEG 格式,条件允许的话优先考虑 WebP 格式
  • 尽量不使用 PNG 格式,PNG8 色位太低,PNG24 压缩率低,文件体积大

背景图
背景图多为图标等颜色比较简单、文件体积不大、起修饰作用的图片

  • PNG 与 GIF 格式,优先考虑使用 PNG 格式,PNG 格式允许更多的颜色并提供更好的压缩率
  • 图像颜色比较简单的,如纯色块线条图标,优先考虑使用 PNG8 格式,避免不使用 JPEG 格式
  • 图像颜色丰富而且图片文件不太大的(40KB 以下)或有半透明效果的优先考虑 PNG24 格式
  • 图像颜色丰富而且文件比较大的(40KB - 200KB)优先考虑 JPEG 格式
  • 条件允许的,优先考虑 WebP 代替 PNG 和 JPEG 格式
图片大小

为了保证图片能更好地加载展示给用户看,团队约定:

PC 平台单张的图片的大小不应大于 200KB。

移动平台单张的图片的大小不应大于 100KB。

图片引入

HTML 中图片引入不需添加 width、height 属性,alt 属性应该写上

CSS Sprites 特点

  • 减少请求数
  • 加速图片的显示
  • 维护更新成本大
  • 更多的内存消耗,特别是大体积或有过多空白的 Sprites 图
  • 图片渗漏,相邻的不需展示的图片有可能出现在展示元素中,特别是在高清设备移动设备上

CSS Sprites 使用建议

  • 适合使用频率高更新频率低的小图标
  • 尽量不留太多的空白
  • 体积较大的图片不合并
  • 确保要合并的小图坐标数值和合并后的 Sprites 图尺寸均为偶数

Data URIs(base64 编码)

  • 减少请求数
  • 转换文件体积大,大约比原始的二进制大 33%
  • IE6 / IE7 不支持
  • 图片显示相对较慢,需要更多的 CPU 消耗

Data URIs(base64 编码)使用建议

  • 适合更新频率高的小图片,如某些具备自定义功能的标题 icon 等
  • 转换成 Base64 编码的图片应小于 8KB
  • 移动端不使用 Base64 编码
  • 要兼容 IE6/IE7 的不使用
  // 核心代码
  chainWebpack: config => {
    const urlLoader = config.module.rule('images')
    // 清除已有的所有 loader。
    // 如果你不这样做,接下来的 loader 会附加在该规则现有的 loader 之后。
    urlLoader.uses.clear()
    // 添加要替换的 loader
    urlLoader
        .test(/\.(woff|woff2|eot|ttf|svg|jpg|png|gif)\??.*$/i)
        .use('url-loader')
        .loader('url-loader')
        .options( {
            limit: 1024*8, // 8k
            name:'[path][name].[ext]', // 利用[path]路径获取文件夹名称并设置文件名
            fallback: 'file-loader',  // 当超过8192byte时,会回退使用file-loader
            context: path.resolve(__dirname,'./src'),//过滤掉[path]的相对路径
            publicPath: '/' //采用根路径
        })
  },

字体图库(iconfont)

  • 轻量级:一个图标字体要比一系列的图像要小。一旦字体加载了,图标就会马上渲染出来,减少了服务器请求
  • 灵活性:本质其实是文字,可以很随意的改变颜色、产生阴影、透明效果、旋转等
  • 兼容性:几乎支持所有的浏览器,请放心使用

字体图库(iconfont)使用建议

  • 适合结构和样式比较简单的小图标
图片质量
  • 上线的图片都应该经过压缩处理,压缩后的图片不应该出现肉眼可感知的失真区域
  • 60 质量的 JPEG 格式图片与质量大于 60 的相比,肉眼已看不出明显的区别,因此保存 JPEG 图的时候,质量一般控制在 60,若保真度要求高的图片可适量提高到 80,图片大小控制在 200KB 以内
Vue 单文件
  • 坚持以 template, script, style 顺序写组件。
  • 坚持组件的 data 为函数,非对象。
  • 坚持为 prop 的属性定义 required, validator, 类型等详细信息。
  • 坚持为 v-for 设置 key
  • 避免将 v-ifv-for 用在一起。
  • 坚持为组件的私有属性使用 $_ 前缀。
  • 坚持为组件的样式设置作用域。
代码提交
  • 坚持在提交代码前校验代码,解决每一个警告。
  • 坚持一次 commit 只进行一个功能的更改。
  • 坚持使用 type(subtype): description 形式提交 commit,type 如下:
    • feat 新增的功能
    • chore 构建过程或辅助工具的变动
    • refactor 重构(即不是新增功能,也不是修改 bug 的代码变动)
    • style 修改格式,不影响逻辑
    • fix 修复问题
    • revert 回滚
    • docs 编写文档
    • test 测试类

开始

  • npm start 开启开发服务器
  • npm run build 进行打包
  • npm run build-analyzer 进行打包与体积分析
  • npm run lint 运行代码校验
  • npm run test 运行单元测试

开始开发

1.关于 api 文件的编写

2.关于 router 文件的编写

一级路由
二级路由

3.关于 vuex 文件的编写

moudles

由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。

为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:

const moduleA = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态

4.关于语法检查

  • 必须遵循语法检查,使用 Webstrom、VsCode 的可以配置,大多数编辑工具都可以配置,eslint+prettier 配置
  • 配置 fix eslint problems, 百度即可

5.components 中组件的介绍

5.1.自动注册组件

方法

<!-- global.js -->
import Vue from 'vue'

const getComponentName = (str, isInsid) => {
  const arr = str.split('/')
  if (isInsid) {
    // 如启用子文件夹需选择最后一级文件夹作为组件名
    str = arr[arr.length - 2]
  }
  // console.log(str)
  return str.charAt(0).toUpperCase() + str.slice(1)
}
// 获取全部以.vue结尾的组件 参数:directory文件夹 useSubdirectories是否使用子目录 regExp 正则
// require.context模块导出(返回)一个(require)函数,这个函数可以接收一个参数:request 函数–这里的 request 应该是指在 require() 语句中的表达式
const requireComponent = require.context('./', true, /index\.vue$/)
const requireComponentInsid = require.context('./', false, /\.vue$/)

const install = () => {
  requireComponent.keys().forEach(fileName => {
    const config = requireComponent(fileName)
    const componentName = getComponentName(fileName.replace(/^\.\//, '').replace(/\.vue+$/, ''), true)
    Vue.component(componentName, config.default || config)
  })
  requireComponentInsid.keys().forEach(fileName => {
    const config = requireComponentInsid(fileName)
    const componentName = getComponentName(fileName.replace(/^\.\//, '').replace(/\.vue+$/, ''))
    Vue.component(componentName, config.default || config)
  })
}

export default {
  install // 对外暴露install方法
}

<!-- main.js -->
import global from './components/global.js'
global.install()

6.关于 views 页面的编写

6.1.关于新增页面注意项
规范
  • 新增文件。
    1. views 下,所有的目录对应的是一节菜单,小写短横线连接,建议要英文表述清楚菜单名的意义。
    1. 具名在文件夹,而不是.vue 文件上
比如:
应该是:
-- home
-- -- index.vue
而不是
-- home.vue

好处在于home下可以为组件扩展更多类型的文件,index.option.js等等,
扩展后后依然位于一个home文件夹中,便于管理

  • 修改/src/router 下 index.js 文件
    1. 懒加载
    1. path 要唯一,且同名于 views 下的对应的组件
    1. 路由配置后,路由数据也是菜单的数据,修改后会自动同步到菜单处
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你说的誓言°变失言

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值