开发规范

本文档为前端 vue 开发规范(包含规范目的,命名规范,结构化规范,注释规范,编码规范,CSS 规范)

规范目的

为提高团队协作效率,便于后台人员添加功能及前端后期优化维护,输出高质量的文档

命名规范

为了让大家书写可维护的代码,而不是一次性的代码,让团队当中其他人看你的代码能一目了然,甚至一段时间时候后你再看你某个时候写的代码也能看

普通变量命名规范

  • 命名方法 :驼峰命名法
  • 命名规范 :

    1. 命名必须是跟需求的内容相关的词,比如说我想申明一个变量,用来表示我的学校,那么我们可以这样定义const mySchool = "我的学校";
    2. 命名是复数的时候需要加s,比如说我想申明一个数组,表示很多人的名字,那么我们可以这样定义const names = new Array();

常量命名规范

  • 命名方法 : 全部大写
  • 命名规范 : 使用大写字母和下划线来组合命名,下划线用以分割单词。
const MAX_COUNT = 10
const URL = 'https://www.baidu.com/'

组件命名规范

官方文档推荐及使用遵循规则:

PascalCase (单词首字母大写命名)是最通用的声明约定

kebab-case (短横线分隔命名) 是最通用的使用约定

  • 组件名应该始终是多个单词的,根组件 App 除外
  • 有意义的名词、简短、具有可读性
  • 使用遵循 kebab-case 约定

    • 在页面中使用组件需要前后闭合,并以短线分隔,如(<abcd-date-picker></abcd-date-picker>,<abcd-table></abcd-table>
  • 导入及注册组件时,遵循 PascalCase 约定
  • 同时还需要注意:必须符合自定义元素规范: 切勿使用保留字。

method 方法命名命名规范

  • 驼峰式命名,统一使用动词或者动词+名词形式
// bad
  go、nextPage、show、open、login
// good
  jumpPage、openCarInfoDialog
  • init、refresh 单词除外
  • 尽量使用常用单词开头(set、get、go、change、has)

page 下的文件命名

  • 只有一个文件的情况下不会出现文件夹,而是直接放在 page 目录下面,如 index.vue
  • 尽量是名词,且使用驼峰命名法
  • 文件夹命名尽量语义化(maintenancManage、maintenancPlanApply)
  • 名字至少两个单词(good: workbenchIndex)(bad:workbench)

props 命名

在声明 prop 的时候,其命名应该始终使用 camelCase,而在模板中应该始终使用 kebab-case

<!-- bad -->
 <script>
 props: {
   'greeting-text': String
 }
</script>
  
<welcome-message greetingText="hi"></welcome-message>
  
 <!-- good -->
 <script>
 props: {
   greetingText: String
 }
 </script>
  
 <welcome-message greeting-text="hi"></welcome-message>

结构化规范

vue 文件基本结构

 <template>
    <div>
      <!--必须在div中编写页面-->
    </div>
 </template>
  <script>
   export default {
    components : {
       },
       data () {
         return {
         }
       },
       mounted() {
      },
       methods: {
       }
    }
   </script>
   <!--声明语言,并且添加scoped-->
   <style lang="scss" scoped>
   </style>

多个特性的元素规范

多个特性的元素应该分多行撰写,每个特性一行。(增强更易读)

<!-- bad -->
<img src="https://vuejs.org/images/logo.png" alt="Vue Logo">
<my-component foo="a" bar="b" baz="c"></my-component>
<!-- good -->
<img
  src="https://vuejs.org/images/logo.png"
  alt="Vue Logo"
>
<my-component
  foo="a"
  bar="b"
  baz="c"
>
</my-component>

元素特性的顺序

原生属性放前面,指令放后面

如下所示:

  - class
  - id,ref
  - name
  - data-*
  - src, for, type, href,value,max-length,max,min,pattern
  - title, alt,placeholder
  - is
  - v-for
  - key
  - v-if
  - v-else
  - v-show
  - v-model
  - v-bind,:
  - v-on,@
  - v-html

组件选项顺序

如下所示:

- components
  - props
  - data
  - computed
  - created
  - mounted
  - metods
  - filter
  - watch

注释规范

代码注释在一个项目的后期维护中显的尤为重要,所以我们要为每一个被复用的组件编写组件使用说明,为组件中每一个方法编写方法说明

务必添加注释列表

  1. 公共组件使用说明
  2. 各组件中重要函数或者类说明
  3. 复杂的业务逻辑处理说明
  4. 特殊情况的代码处理说明,对于代码中特殊用途的变量、存在临界值、函数中使用的 hack、使用了某种算法或思路等需要进行注释描述
  5. 多重 if 判断语句
  6. 单行注释使用//

编码规范

优秀的项目源码,即使是多人开发,看代码也如出一人之手。统一的编码规范,可使代码更易于阅读,易于理解,易于维护。尽量按照 ESLint 格式要求编写代码

源码风格

使用 ES6 风格编码

(1) 定义变量使用 let ,定义常量使用 const
(2) 静态字符串一律使用单引号或反引号,动态字符串使用反引号
  // bad
   const a = 'foobar'
   const b = 'foo' + a + 'bar'
  
   // acceptable
   const c = `foobar`
  
   // good
   const a = 'foobar'
   const b = `foo${a}bar`
   const c = 'foobar'
(3) 解构赋值
  • 数组成员对变量赋值时,优先使用解构赋值
 // 数组解构赋值
   const arr = [1, 2, 3, 4]
   // bad
   const first = arr[0]
   const second = arr[1]
  
   // good
   const [first, second] = arr
  • 函数的参数如果是对象的成员,优先使用解构赋值
 // 对象解构赋值
   // bad
   function getFullName(user) {
     const firstName = user.firstName
     const lastName = user.lastName
   }
  
   // good
   function getFullName(obj) {
     const { firstName, lastName } = obj
   }
  
   // best
   function getFullName({ firstName, lastName }) {}
(4) 拷贝数组组

  使用扩展运算符(...)拷贝数组。

 const items = [1, 2, 3, 4, 5]
 
  // bad
  const itemsCopy = items
 
  // good
  const itemsCopy = [...items]
(5) 箭头函数

  需要使用函数表达式的场合,尽量用箭头函数代替。因为这样更简洁,而且绑定了 this

   // bad
   const self = this;
   const boundMethod = function(...params) {
     return method.apply(self, params);
   }
  
   // acceptable
   const boundMethod = method.bind(this);
  
   // best
   const boundMethod = (...params) => method.apply(this, params);
(6) 模块
  • 如果模块只有一个输出值,就使用 export default,如果模块有多个输出值,就不使用 export default,export default 与普通的 export 不要同时使用
  // bad
  import * as myObject from './importModule'
 
  // good
  import myObject from './importModule'
  • 如果模块默认输出一个函数,函数名的首字母应该小写。
 function makeStyleGuide() {
  }
 
  export default makeStyleGuide;
  • 如果模块默认输出一个对象,对象名的首字母应该大写
const StyleGuide = {
    es6: {
    }
  };
 
  export default StyleGuide;

指令规范

(1) v-for 循环必须加上 key 属性,在整个 for 循环中 key 需要唯一
    <!-- good -->
    <ul>
      <li v-for="todo in todos" :key="todo.id">
        {{ todo.text }}
      </li>
    </ul>
   
    <!-- bad -->
    <ul>
     <li v-for="todo in todos">
       {{ todo.text }}
     </li>
   </ul>
(2) 避免 v-if 和 v-for 同时用在一个元素上(性能问题)

  以下为两种解决方案:

  • 将数据替换为一个计算属性,让其返回过滤后的列表
<!-- bad -->
  <ul>
    <li v-for="user in users" v-if="user.isActive" :key="user.id">
      {{ user.name }}
    </li>
  </ul>

<!-- good -->
  <ul>
    <li v-for="user in activeUsers" :key="user.id">
      {{ user.name }}
    </li>
  </ul>

  <script>
  computed: {
    activeUsers: function () {
      return this.users.filter(function (user) {
        return user.isActive
      })
    }
  }
  </script>
  • 将 v-if 移动至容器元素上 (比如 ul, ol)
<!-- bad -->
  <ul>
    <li v-for="user in users" v-if="shouldShowUsers" :key="user.id">
      {{ user.name }}
    </li>
  </ul>

<!-- good -->
  <ul v-if="shouldShowUsers">
    <li v-for="user in users" :key="user.id">
      {{ user.name }}
    </li>
  </ul>

Props 规范

Props 定义应该尽量详细

// bad 这样做只有开发原型系统时可以接受
props: ['status']

// good
props: {
  status: {
    type: String,
    required: true,
    validator: function (value) {
      return [
        'syncing',
        'synced',
        'version-conflict',
        'error'
      ].indexOf(value) !== -1
    }
  }
}

其他

  1. 避免 this.$parent
  2. 调试信息 console.log() debugger 使用完及时删除!!!

CSS 规范

通用规范

(1) 统一使用"-"连字符
(2) 省略值为 0 时的单位
// bad
  padding-bottom: 0px;
  margin: 0em;

// good
  padding-bottom: 0;
  margin: 0;
(3) 如果 CSS 可以做到,就不要使用 JS
(4) 建议并适当缩写值,提高可读性,特殊情况除外

​ “建议并适当”是因为缩写总是会包含一系列的值,而有时候我们并不希望设置某一值,反而造成了麻烦,那么这时候你可以不缩写,而是分开写。

​ 当然,在一切可以缩写的情况下,请务必缩写,它最大的好处就是节省了字节,便于维护,并使阅读更加一目了然。

(5) 当使用 Sass 的嵌套功能的时候,重要的是有一个明确的嵌套顺序,以下内容是一个 SCSS 块应具有的顺序。
  • 当前选择器的样式属性
  • 父级选择器的伪类选择器 (:first-letter, :hover, :active etc)
  • 伪类元素 (:before and :after)
  • 父级选择器的声明样式 (.selected, .active, .enlarged etc.)
  • 用 Sass 的上下文媒体查询
  • 子选择器作为最后的部分
.product-teaser {
    // 1. Style attributes
    display: inline-block;
    padding: 1rem;
    background-color: whitesmoke;
    color: grey;

    // 2. Pseudo selectors with parent selector
    &:hover {
      color: black;
    }

    // 3. Pseudo elements with parent selector
    &:before {
      content: "";
      display: block;
      border-top: 1px solid grey;
    }

    &:after {
      content: "";
      display: block;
      border-top: 1px solid grey;
    }

    // 4. State classes with parent selector
    &.active {
      background-color: pink;
      color: red;

      // 4.2. Pseuso selector in state class selector
      &:hover {
        color: darkred;
      }
    }

    // 5. Contextual media queries
    @media screen and (max-width: 640px) {
      display: block;
      font-size: 2em;
    }

    // 6. Sub selectors
    > .content > .title {
      font-size: 1.2em;

      // 6.5. Contextual media queries in sub selector
      @media screen and (max-width: 640px) {
        letter-spacing: 0.2em;
        text-transform: uppercase;
      }
    }
  }

特殊规范

  • 对用页面级组件样式,应该是有作用域的
  • 对于公用组件或者全局组件库,我们应该更倾向于选用基于 class 的 BEM 策略
BEM定义
Block Element Modifier的首字母缩写,是一种css的命名规范,一般写作.block__element--modifier

B(block):独立的页面及逻辑单元。 b-name

E(element): 块中的组成部分,不能脱离存在,一般为元素的功能单词或元素的标签。__element

M(modifier): 修饰符,一般为某个元素的样式或处于的一种状态。--modifier
<style lang='scss'></style> // bad

  <!-- 使用 scoped 作用域 -->
  <style lang='scss' scoped></style> // good

  <!-- 使用 BEM 约定 -->
  <style> // good
  .c-Button {
    border: none;
    border-radius: 2px;
  }

  .c-Button--close {
    background-color: red;
  }
  </style>

开发模式token调用后台服务

开发环境需要在request.js文件中给表头添加的token

image-20220922170729930网络请求

当整个框架搭建完毕以后,前端程序员最主要的工作就是发起请求,渲染数据。现在我们就来完整地走一遍这个过程。

配置代理

打开根目录下的vue.config.js文件

image-20220922171534362

配置拦截器

打开src/utils/request.js,此文件封装了一个axios请求对象,该系统中的网络请求都是基于这个对象来处理的。

可以在网络请求发送之前添加服务器==请求拦截==,在开发环境通常需要模拟添加请求头用户token信息

service.interceptors.request.use(
    config => {
        if (config.url.indexOf('oauth')<0) {
            config.url='/api/'+config.url;
        }
        config.headers.common.Authorization ='Bearer'+sessionStorage.getItem('access_token'); 
        return config;
    },
    error => {
        return Promise.reject();
    }
);

可以在网络请求发送之前和收到服务端回复之后进行==响应拦截==。比如根据服务端的状态码判断请求是否正常,若不正常给出相应的提示。若状态码不一致可直接返回请求数据

service.interceptors.response.use(
    response => {
        let resData = response.data;
        if (response.status === 200) {
            if (resData.code === 'CODE_4008') {
                Message.closeAll();
                Message.error('登录过期,请重新登录');
                sessionStorage.removeItem('access_token');
                sessionStorage.removeItem('userInfo');
                sessionStorage.removeItem('teamInfo');
                localStorage.removeItem('MENUSMODEL');
                window.location.href = "/#/login";
            } else {
                return resData;
            }
        } else {
            Promise.reject();
        }
    },
    error => {
        Message.error(error.response.data.msg);
        return Promise.reject();
    },
);

挂载请求对象

在src/api下的js文件中导入网络请求对象直接使用

import request from '@/utils/request'

接口描述

公共接口

获取当前用户信息

用户信息存储在SessionStorgae中,需要的话可以自行获取

(1)接口简要描述

​ 查询行政区划树

(2)请求URL
cbb-userauth/adcd/v2/queryAdTree
(3)请求方式
  • GET
(4)返回示例

image-20220922173931208

(5)返回参数说明
参数名类型说明
codeStringCODE_0000 代表失败
DataObject数据信息
MsgString提示

菜单权限控制以及动态菜单

根据用户id以及所要登录系统的userName来获取该登录人员所对应的权限菜单列表,然后通过工具函数来生成路由菜单,并存储在vuex供左侧菜单使用对应图8

(1)接口简要描述

获取权限菜单

(2)请求URL
cbb-smart-drain-backend/permission/getFunInfoByUserNameAndPid
(3)请求方式
  • GET
参数名必选类型说明
userNamestring用户userName
pidstring登录系统所代表的code值这个需要去平台查看
(4)返回示例

image-20220922174629398

(5)处理菜单数据

image-20220922175648675

image-20220922175659790

image-20220922175722510

(6)动态路由挂载

image-20220922175852377


漫姐贼6
26 声望1 粉丝