Так называемые неправила не образуют круг, фронтальное время в команде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>