спецификация кода внешнего интерфейса code-review

внешний интерфейс JavaScript
спецификация кода внешнего интерфейса code-review

Так называемые неправила не образуют круг, фронтальное время в командеcode-reviewУстановлено, что коды, написанные разными разработчиками в разные периоды, можно охарактеризовать как разнообразные. Поэтому мы выдвинули некоторые соответствующие спецификации кода, надеясь в будущем сформировать стандарты кодирования команды.

Цель разработки спецификации

  • Унифицируйте стиль кодирования, стандартизируйте, повысьте эффективность совместной работы в команде
  • Вывод читаемого, поддерживаемого и согласованного кода при совместной работе в команде

Эта статья была включена в github:GitHub.com/Майкл-Ли Чжиган…

HTML статьи

включить стандартный режим

используя HTML5doctypeвключить стандартный режим

<!DOCTYPE html>

Унифицированное использование кодировки UTF-8

<meta charset="utf-8" />

Установите приоритет последней версии IE и Chrome

<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />

Добавьте область просмотра для мобильных устройств

<meta name="viewport" content="initial-scale=1, maximum-scale=3, minimum-scale=1, user-scalable=no" />

Самозакрывающиеся этикетки не нужно закрывать

Например:img,input,br,hrЖдать

<img src="https://xxx.png" alt="Google" />
<br />
<input type="text" name="title" />

Используйте семантические теги

HTML-теги могут использовать семантику, попробуйте использовать семантические теги, чтобы страница не содержала тегов div или p.

<!-- bad -->
<div>
  <p></p>
</div>

<!-- good -->
<header></header>
<footer></footer>

Требования к порядку атрибутов

Атрибуты HTML должны отображаться в определенном порядке, чтобы обеспечить удобочитаемость.

id
class
name
data-xxx
src, for, type, href
title, alt
aria-xxx, role

CSS-статьи

Номенклатура БЭМ

  • блок: модуль, с которым связаны слова имени -
  • элемент: элемент, дочерний элемент модуля, связанный с блоком с помощью __
  • модификатор: Модификация, вариант модуля, определяющий специальный модуль, связанный с блоком с --
/* 举个例子 */
.block__element {
}
.block--modifier {
}

Эффективное использование CSS-селекторов

Вложенность селектора должна быть менее 3 уровней.

/* bad */
.page .header .login #username input {
}

/* good */
#username input {
}

Эффективное использование селекторов css, а именно:

  • Будьте проще и не используйте слишком сложные вложенные селекторы.
  • Подстановочные знаки и селекторы атрибутов наименее эффективны и должны соответствовать большинству элементов, поэтому старайтесь их избегать.
  • Не украшайте теги элементов селекторами классов и селекторами идентификаторов.
  • Не жертвуйте читабельностью и ремонтопригодностью ради скорости
  • Избегайте использования выражений CSS

Тщательно выбирайте стили с высоким потреблением

Дорогостоящие свойства требуют от браузера большого количества вычислений перед отрисовкой:

box-shadows
border-radius
transparency
transforms
CSS filters(性能杀手)

Избегайте перерисовки

Когда происходит перекомпоновка, браузеру необходимо пересчитать положение и размер макета, что не способствует оптимизации производительности.

Общие свойства и методы, вызывающие перерисовку перерисовки

  • Добавить или удалить видимыеDOMэлемент;
  • Изменения размера элемента - поля, отступы, границы, ширина и высота
  • Изменения в содержании, например, когда пользовательinputВведите текст в поле
  • Изменение размера окна браузера -resizeкогда произошло событие
  • рассчитатьoffsetWidthиoffsetHeightАтрибуты
  • настраиватьstyleстоимость имущества

Способы уменьшения перерисовки оплавления

  • использоватьtransformальтернативаtop
  • использоватьvisibilityзаменятьdisplay: none, потому что первое приведет только к перерисовке, второе вызовет перекомпоновку (изменение макета)
  • Не помещайте значение свойства узла в цикл как переменную в цикле.
  • Не используйtableмакет, небольшое изменение может привести к тому, что всеtableПереназначение
  • Выбор скорости реализации анимации, чем быстрее скорость анимации, тем больше время перекомпоновки, вы также можете использоватьrequestAnimationFrame
  • Селекторы CSS сопоставляются и ищутся справа налево, чтобы избежать слишком большого количества уровней узлов.

Javascript-статьи

О нейминге

В общем именовании используется маленький верблюжий регистр.

let userName = 'jack'

Когда имя во множественном числе, вам нужно добавить s. Например, я хочу объявить массив для представления имен многих людей.

let names = new Array()

Каждая константа должна быть названа, чтобы другим было легче понять смысл

// good
const COL_NUM = 10
let row = Math.ceil(num / COL_NUM)

// bad
let row = Math.ceil(num / 10)

Именование должно соответствовать семантике.Если функция названа, перед ней может стоять глагол:

  • может определить, может ли действие быть выполнено
  • has определяет, содержит ли он значение
  • заключается в том, чтобы определить, является ли это определенным значением
  • получить получить значение
  • установить установить значение
//是否可阅读
function canRead(){
   return true;
}
//获取姓名
function getName{
   return this.name
}

О строках

Единообразное использование одинарных кавычек вместо двойных кавычек

// bad
const name = 'jack'

// good
const name = 'jack'

Используйте шаблоны строк вместо «+» для объединения строк

function sayHi(name) {
  return 'How are you, ' + name + '?'
}

// good
function sayHi(name) {
  return `How are you, ${name}?`
}

О массивах

присваивание с литералами

// bad
const items = new Array()

// good
const items = []

Неглубокая копия массива с оператором распространения

// bad
let arr = [1, 2, 3]
const len = arr.length
const copyArr = []

for (let i = 0; i < len; i += 1) {
  copyArr[i] = arr[i]
}

// good
const copyArr = [...arr]

Используйте Array.from для преобразования объекта, подобного массиву, в массив.

const arrLike = { 0: 'foo', 1: 'bar', 2: 'baz', length: 3 }

// bad
const arr = Array.prototype.slice.call(arrLike)

// good
const arr = Array.from(arrLike)

Использовать деструктуризацию массива

const arr = [1, 2, 3, 4]

// bad
const first = arr[0]
const second = arr[1]

// good
const [first, second] = arr

Об объектах

Использование литералов рекомендуется для создания объектов и массивов, так как это не только обеспечивает лучшую производительность, но и помогает сэкономить код.

// good
let obj = {
  name: 'Tom',
  age: 15,
  sex: '男',
}

// bad
let obj = {}
obj.name = 'Tom'
obj.age = 15
obj.sex = '男'

ES6 использует сокращения значений свойств

const lukeSkywalker = 'Luke Skywalker'

// bad
const obj = {
  lukeSkywalker: lukeSkywalker,
}

// good
const obj = {
  lukeSkywalker,
}

Поместите аббревиатуру свойства в начало объявления объекта.

const anakinSkywalker = 'Anakin Skywalker'
const lukeSkywalker = 'Luke Skywalker'

// bad
const obj = {
  episodeOne: 1,
  twoJediWalkIntoACantina: 2,
  lukeSkywalker,
  episodeThree: 3,
  mayTheFourth: 4,
  anakinSkywalker,
}

// good
const obj = {
  lukeSkywalker,
  anakinSkywalker,
  episodeOne: 1,
  twoJediWalkIntoACantina: 2,
  episodeThree: 3,
  mayTheFourth: 4,
}

При поверхностном копировании объектов рекомендуется использовать оператор распространения ... вместо Object.assign. При деструктуризации присваивания для получения нескольких свойств, заданных объектом, рекомендуется использовать оператор rest, который также ....

// very bad
const original = { a: 1, b: 2 }
const copy = Object.assign(original, { c: 3 })
delete copy.a //  改变了 original

// bad
const original = { a: 1, b: 2 }
const copy = Object.assign({}, original, { c: 3 }) // copy => { a: 1, b: 2, c: 3 }

// good
const original = { a: 1, b: 2 }
const copy = { ...original, c: 3 } // copy => { a: 1, b: 2, c: 3 }

const { a, ...noA } = copy // noA => { b: 2, c: 3 }

О функциях

Параметры функции используют значения по умолчанию вместо присваивания с помощью условных операторов.

// good
function createMicrobrewery(name = 'Jack') {
   ...
}

// bad
function createMicrobrewery(name) {
  const userNameName = name || 'Jack'
   ...
}

Параметры функции используют синтаксис структуры. Чем меньше параметров функции, тем лучше. Если параметров больше двух, следует использовать синтаксис деструктурирования ES6 независимо от порядка параметров.

// good
function createMenu({ title, body, buttonText, cancellable }) {
   ...
}

createMenu({
  title: 'Foo',
  body: 'Bar',
  buttonText: 'Baz',
  cancellable: true,
})

// bad
function createMenu(title, body, buttonText, cancellable) {
  // ...
}

Предпочитать синтаксис остатка... вместо аргументов

// bad
function concatenateAll() {
  const args = Array.prototype.slice.call(arguments)
  return args.join('')
}

// good
function concatenateAll(...args) {
  return args.join('')
}

Поместите назначения параметров по умолчанию в конец

// bad
function handleThings(opts = {}, name) {
  // ...
}

// good
function handleThings(name, opts = {}) {
  // ...
}

Используйте стрелочные функции, когда это возможно

// bad
[1, 2, 3].map(function (x) {
    const y = x + 1
    return x * y
  })

// good
 [1, 2, 3].map((x) => {
    const y = x + 1
    return x * y
  })

О модулях

Использование в нестандартных модульных системах (импорт/экспорт)

// bad
const AirbnbStyleGuide = require('./AirbnbStyleGuide')
module.exports = AirbnbStyleGuide.es6

// ok
import AirbnbStyleGuide from './AirbnbStyleGuide'
export default AirbnbStyleGuide.es6

// best
import { es6 } from './AirbnbStyleGuide'
export default es6

Запись импортируется только один раз

// bad
import foo from 'foo'
// … some other imports … //
import { named1, named2 } from 'foo'

// good
import foo, { named1, named2 } from 'foo'

В модуле только с одним экспортом лучше использовать экспорт по умолчанию

// bad
export function foo() {}

// good
export default function foo() {

для цикла

В процессе использования цикла for длина массива принимается переменной, что способствует повышению эффективности выполнения кода, вместо пересчета длины массива при каждом проходе цикла.

// bad
for(var i = 0; i < arr.length; i++){

}

// good
for(var i = 0; len = arr.length; i < len; i++){

}

Vue статьи

Определения реквизита должны быть как можно более подробными.

propОпределение должно быть максимально подробным, хотя бы с указанием его типа.

// bad
props: ['status']

// good
props: {
  status: String
}

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

v-для обхода необходимо добавить ключ

Когда данные списка просматриваются и визуализируются, необходимо для каждого элементаitemустановить уникальныйkeyзначение, чтобы внутренний механизм Vue.js мог точно найти данные списка. когдаstateПри обновлении новое значение состояния сравнивается со старым значением состояния, и местоположение определяется быстрее.diff.

<!-- bad -->
<ul>
  <li v-for="todo in todos">{{ todo.text }}</li>
</ul>

<!-- good -->
<ul>
  <li v-for="todo in todos" :key="todo.id">{{ todo.text }}</li>
</ul>

Не используйте v-if и v-for для одного и того же элемента.

v-forСравниватьv-ifВысокий приоритет, если ему нужно каждый раз проходить весь массив, это повлияет на скорость, особенно когда нужно отрисовать небольшую часть.

<!-- 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>

Данные компонента должны быть функцией

Экземпляры в JS создаются с помощью конструкторов.Каждый конструктор может создавать множество новых экземпляров, и каждый экземпляр будет наследовать методы или свойства прототипа. Данные данных Vue на самом деле являются свойством прототипа Vue, и данные существуют в памяти.

Если один и тот же компонент используется несколько раз, будет создано несколько экземпляров. Эти экземпляры используют один и тот же конструктор, если данные были объектом. Тогда все компоненты совместно используют один и тот же объект. Чтобы обеспечить независимость компонентов от данных, требуется, чтобы каждый компонент возвращал объект в качестве состояния компонента через функцию данных, чтобы при каждом повторном использовании компонента возвращался новый фрагмент данных.

// bad
Vue.component('some-comp', {
  data: {
    foo: 'bar',
  },
})

// good
Vue.component('some-comp', {
  data: function () {
    return {
      foo: 'bar',
    }
  },
})

Шаблоны компонентов должны быть написаны лаконично

Шаблоны компонентов должны содержать только простые выражения, сложные выражения должны быть преобразованы в вычисляемые свойства или методы.

// bad
{{
  fullName.split(' ').map(function (word) {
    return word[0].toUpperCase() + word.slice(1)
  }).join(' ')
}}

//  good
//  在模板中
{{ normalizedFullName }}
// 复杂表达式已经移入一个计算属性
computed: {
  normalizedFullName: function () {
    return this.fullName.split(' ').map(function (word) {
      return word[0].toUpperCase() + word.slice(1)
    }).join(' ')
  }
}

аббревиатура инструкции

<!-- bad -->
<input v-bind:value="newTodoText" :placeholder="newTodoInstructions" v-on:input="onInput" />
<!-- good -->
<input :value="newTodoText" :placeholder="newTodoInstructions" @input="onInput" />

Имя компонента из нескольких слов

Имена компонентов, которые мы настраиваем во время разработки, должны состоять из нескольких слов, чтобы избежать конфликтов с существующими и будущими элементами HTML, поскольку все имена элементов HTML состоят из одного слова.

// good
Vue.component('todo-item', {
  // ...
})
export default {
  name: 'TodoItem',
  // ...
}

// bad
Vue.component('todo', {
  // ...
})

export default {
  name: 'Todo',
  // ...
}

Несколько атрибутов для ветвления

В JavaScript рекомендуется разделять несколько свойств объекта на несколько строк, потому что это легче читать.

<!-- good -->
<MyComponent 
    foo="a" 
    bar="b" 
    baz="c" 
/>

<!-- bad -->
<MyComponent foo="a" bar="b" baz="c" />

порядок свойств элемента

Собственные атрибуты располагаются впереди, инструкции — далее, а параметры и методы — последними.

  - class, id, ref
  - name, data-*, src, alt, for, type, href, value, max, min
  - title, placeholder, aria-*, role
  - required, readonly, disabled
  - v-model, v-for, key, v-if, v-show, v-bind,:
  - foo="a" bar="b" baz="c"

О стилях в компонентах

Область действия стилей компонентов

/* bad  */
<style>
.btn-close {
  background-color: red;
}
</style>

/* good  */
<style scoped>
.button-close {
  background-color: red;
}
</style>

Чтобы изменить стиль сторонней библиотеки компонентов, необходимо добавить область верхнего уровня.

/* bad */
.ivu-input {
  width: 254px !important;
}

/* good */
.customerForm .ivu-input {
  width: 254px !important;
}
/* .customerForm为当前组件的顶级dom  */

О структуре компонентов

Структура компонента повторяет структуру шаблона, скрипта, стиля сверху вниз.

<template>
  <div></div>
</template>

<script>
  export default {}
</script>

<style lang="scss" scoped></style>

Члены методов секции сценария располагаются в следующем порядке.

- name
- components
- props
- data
- methods
- computed
- watch
- created
- mounted
- update

Очистить таймер или прослушиватель событий

Потому что некоторые страницы в проекте неизбежно будут сталкиваться с таймерами или мониторингом событий. Однако при выходе с текущей страницы, если таймер не будет очищен вовремя и разумно, это вызовет путаницу в бизнес-логике или даже зависание приложения.В это время необходимо очистить прослушиватель событий таймера, то есть жизненный цикл функция выгрузки (закрытия) страницы, сброс таймера.

methods:{
  resizeFun () {
    this.tableHeight = window.innerHeight - document.getElementById('table').offsetTop - 128
  },
  setTimer() {
    this.timer = setInterval(() => { })
  },
  clearTimer() {
		clearInterval(this.timer)
    this.timer = null
	}
},
mounted() {
  this.setTimer()
  window.addEventListener('resize', this.resizeFun)
},
beforeDestroy() {
  window.removeEventListener('resize', this.resizeFun)
  this.clearTimer()
}

Отложенная загрузка маршрута

Vue является одностраничным приложением, и может быть импортировано много маршрутов.Таким образом, файл, упакованный с помощью webpcak, очень большой.При входе на домашнюю страницу загружается слишком много ресурсов, и на странице появляется белый экран, который не способствует пользовательскому опыту. Было бы более эффективно, если бы мы могли разделить компоненты, соответствующие разным маршрутам, на разные блоки кода, а затем загружать соответствующие компоненты при доступе к маршруту.

{
  path: '/Home',
  component: () => import('@/views/Home.vue')
}

единственная ответственность

В любое время пытайтесь использовать одну функцию для выполнения одной задачи вместо того, чтобы объединять все виды логики вместе, чтобы улучшить возможность повторного использования и удобочитаемость одной функции. Например: каждая страница будет запрашивать данные и отображать их на странице после завершения загрузки.

// bad
methods: {
  getList1() {
    // to do ...
  },
  getList2() {
    // to do ...
  }
},
created() {
  this.getList1()
  this.getList2()
},

// good
methods: {
  // 将全部的请求行为聚合在init函数中
  init() {
    this.getList1()
    this.getList2()
  },
  getList1() {
    // to do ...
  },
  getList2() {
    // to do ...
  }
},
created() {
  this.init();
},

Внедрение сторонних компонентов пользовательского интерфейса по запросу

Для сторонних компонентов пользовательского интерфейса, которые мы используем в проекте, если мы напрямую импортируем всю библиотеку компонентов, это приведет к тому, что проект будет слишком большим Мы можем использовать babel-plugin-component, и тогда можно будет ввести только необходимые компоненты. уменьшить объем проекта цель. Ниже приведен пример внедрения ванта в проект:

1. Сначала установите babel-plugin-component

npm install babel-plugin-component -D

2. Измените .babelrc

{
  "plugins": [
    ["import", {
      "libraryName": "vant",
      "libraryDirectory": "es",
      "style": true
    }]
  ]
}

3. Введите некоторые компоненты:

import Vue from 'vue'
import { Button } from 'vant'

Vue.use(Button)

Фотографий:

Используйте соответствующий формат изображения.

  • jpg: подходит для изображений контента, которые в основном представляют собой фотографии и тому подобное.
  • png: подходит для декоративных изображений, обычно больше подходит для сжатия без потерь.
  • gif: В основном не используйте его, за исключением анимированных GIF-файлов.
  • webP: значительно уменьшает размер изображения, но есть проблемы с совместимостью на мобильной стороне.

Использовать спрайт

карта спрайтов,CSS Sprites, также называемый CSS-спрайтом в Китае, представляет собой технологию синтеза изображений CSS, в основном используемую для отображения небольших изображений.

Преимущество карты спрайтов заключается в объединении множества маленьких картинок в одну большую картинку, используяbackround-positionЗначение атрибута используется для определения позиции рендеринга изображения, что позволяет уменьшить http-запрос и добиться эффекта оптимизации производительности.

использовать иконочный шрифт

iconfont(значок шрифта), то есть отображение значков шрифтами, которые в основном используются для рендеринга значков, простой графики, специальных шрифтов и т.д.

использоватьiconfont, поскольку необходимо импортировать только соответствующий файл шрифта, этот метод может эффективно сократить количество HTTP-запросов, и, как правило, размер шрифта невелик, поэтому объем данных, передаваемых по запросу, невелик. В отличие от прямого импорта изображений,iconfontРазмер, цвет и другие стили можно задавать так же, как шрифты без искажений.

Ленивая загрузка изображения

Принцип ленивой загрузки картинок заключается в том, чтобы временно не ставить картинкиsrcсобственность, но образurlскрыто, например, писать первымdata-srcВнутри, когда запускаются определенные события (такие как прокрутка вниз, нажатие для загрузки картинки), то картинка настоящаяurlвставитьsrcсвойства, чтобы добиться отложенной загрузки изображений.

function lazyload() {
  var images = document.getElementsByTagName('img')
  var len = images.length
  var n = 0 //存储图片加载到的位置,避免每次都从第一张图片开始遍历
  return function () {
    var seeHeight = document.documentElement.clientHeight
    for (var i = n; i < len; i++) {
      if (images[i].getBoundingClientRect().top < seeHeight) {
        //方法二: 当图片的视口top出现在视口中
        if (images[i].getAttribute('src') === 'images/default.jpg') {
          images[i].src = images[i].getAttribute('data-src')
        }
        n = n + 1
      }
    }
  }
}

Vue-проекты могутvue-lazyloadПлагин реализует ленивую загрузку изображений

main.jsПредставлено глобально:

import VueLazyLoad from 'vue-lazyload'
Vue.use(VueLazyLoad, {
  preLoad: 1,
  error: require('./assets/img/error.jpg'),
  loading: require('./assets/img/homePage_top.jpg'),
  attempt: 2,
})

используется на странице

<li v-for="(item,index) in imgList">
  <img v-lazy="item" alt="" />
</li>

рекомендуемая статья