Пишите код, который другие поймут и полюбят

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

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

Один из основных принципов, которых я как программист люблю придерживаться, в том числе в проектах Vue.js, - это принцип DRY.

DRY означает не повторяйся, и его цель - уменьшить количество повторений.

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

Допустим, у вас есть дублированный код в двух местах в вашей кодовой базе. Что, если вы решите изменить логику или некоторые параметры? Вам придется реорганизовать код в обоих местах. Но насколько это может быть плохо?

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

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

Используйте миксины

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

Если вы повторно используете логику в разных компонентах, имеет смысл определить ее внутри миксинов, которые вы можете использовать во всем своем приложении.

Допустим, у вашего приложения есть несколько маршрутов, и, используя vue-router, вы соединяете каждый маршрут с соответствующим компонентом.

- App.vue
-- Home.vue
-- Analytics.vue
-- Reports.vue

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

Если вы не используете миксины и хотите, чтобы обзор продукта отображался на всех страницах, вам нужно будет скопировать один и тот же код в каждый mounted обратный вызов и startProductTour метод. Я написал здесь пример Home.vue, но вам понадобится тот же код внутри Analytics.vue и Reports.vue.

Home.vue

export default {
  mounted() {
    this.startProductTour();
  }.
  methods: {
    startProductTour() {
      // start product tour actions here
    }
  }
}

Но если вы определите вышеупомянутое как миксин ...

ProductTour микс

export default {
  mounted() {
    this.startProductTour();
  }.
  methods: {
    startProductTour() {
      // start product tour actions here
    }
  }
}

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

Home.vue

import ProductTourMixin from '../mixins/ProductTourMixin';
export default {
  mixins: [ProductTourMixin]
}

В этом случае ваша новая структура проекта будет выглядеть так:

- App.vue
- mixins/ProductTourMixin
-- Home.vue
-- Analytics.vue
-- Reports.vue

Используя миксины, вы экономите время и силы и избегаете головной боли - просто сохраняя вещи чистыми и СУХИМИ.

Не экономьте на компонентах

В одном из моих первых приложений Vue мои компоненты вырастали до сотен или даже тысяч строк кода. Мои компоненты Giga будут делать все внутри, включая массивный HTML <template>, множество методов и много JavaScript внутри этих методов. Проблема в том, что:

  • Все, что я создавал, нельзя было использовать повторно. Если бы я хотел повторно использовать часть моего гига-компонента, мне нужно было бы скопировать ее в новый компонент, что привело бы к дублированию.
  • Компонент Giga было трудно читать и поддерживать, и со временем он стал бы длиннее, если бы я не реорганизовал его.
  • Было сложно разделить работу между людьми, не вызывая конфликтов, в результате чего на развертывание функционального кода требовалось еще больше времени.

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

Так каковы же преимущества создания большого количества мелких компонентов вместо меньшего количества крупных?

  1. Небольшие компоненты часто можно использовать повторно, что экономит ваше время, а также защищает вас от дублирования кода.
  2. Вы по большей части разделяете логику родительского и дочернего элементов. Если вы внесете изменения в дочерний компонент, это не повлияет на родительский элемент. То же самое верно и для родительского элемента, если вы никоим образом не меняете передаваемые свойства.
  3. Компоненты меньшего размера дают преимущество в производительности в больших циклах v-for, поскольку Vue не обновляет их, пока не изменятся свойства (для свойств, не являющихся объектами).

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

Эта цитата взята из официальной документации Vue по компонентам, и в ней говорится о важности разделения вашего приложения на компоненты.

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

Подтвердите свой реквизит

Проверка ваших свойств - важная часть поддержки вашего приложения Vue.

Во-первых, давайте посмотрим на неправильный способ определения свойств в компоненте.

export default {
  props: ['myProp'],
}

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

// quick way
export default {
  props: {
    myProp: String,
  }
}
// this should be preferred
export default {
  props: {
    myProp: {
      type: String
    }
  }
}

Но лучший способ - полностью определить свои реквизиты и проверить их.

props: {
  myProp: {
    type: Number,
    required: true,
    validator: (value) => {
      return value > 0;
    }
  }
}

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

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

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

Взаимодействие с API с помощью сервисов

У Vue нет таких сервисов, как Angular, который позволяет создавать сервисы для взаимодействия с API и построения общей логики приложения.

По моему опыту, стоит максимально отделить логику представления от логики приложения.

Чтобы лучше проиллюстрировать свою идею, приведу пример. Допустим, у вас есть Reports компонент, который включает три дочерних компонента: ReportTable, ReportChart и ReportStats.

Reports.vue

<!-- This example is intentionally kept simple -->
<template>
  <report-stats :stats="stats" />
  <report-chart :chartData="chartData" />
  <report-table :breakdown="breakdown" />
</template>
<script>
export default {
  data() {
    return {
      stats: null,
      chartData: null,
      breakdown: null
    }
  }
}
</script>

Это основа вашего Reports компонента. Теперь вам понадобится способ получить данные из вашего API, поэтому у вас будет что-то вроде этого:

mounted() {
  this.getStats();
}

И тогда получится что-то вроде этого:

methods: {
  getStats() {
    axios.get('/api/to-get/the-data')
      .then(response => {
        this.stats = response.data.stats
      });
  }
}

Это определенно неплохо, а для небольших приложений это может быть нормально. Но отделение логики приложения от логики представления имеет несколько преимуществ:

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

Так как же превратить наш пример в сервис?

ReportsService.js

const ReportsService = {
  stats: {
    index: async (/* params */) => {
      const response = await axios.get('/api-link');
      return response.data;
    }
  }
}
export default ReportsService;

Reports.vue

import ReportsService from '../services/ReportsService';
export default {
  methods: {
    async getStats() {
      this.stats = await ReportsService.stats.index(/* params */);
    }
  }
}

Используя простую логику, мы создали сервис, который может взаимодействовать с нашим серверным API или реализовывать логику приложения. Таким образом, наш компонент Vue может взаимодействовать с нашей службой, получать необходимые данные и передавать их компоненту, без каких-либо дополнительных сведений о нашем API или логике приложения.

Следуйте руководству по стилю

Подробное описание руководства по стилю Vue выходит за рамки данной статьи. В общем, важно знать, как устроены используемые вами фреймворки и как они ожидают, что вы с ними будете работать.

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

Вот некоторые из наиболее важных правил руководства по стилю:

Используйте функцию data () вместо объекта данных

Это неправильный способ делать что-то:

export default {
  data: {
    value: 1,
  }
}

И это правильный способ:

export default {
  data() {
    return {
      value: 1,
    }
  }
}

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

Всегда ключевые v-fors

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

<my-item
  v-for="item in items"
  :key="item.id"
  :item="item" />
<!-- or with HTMl elements -->
<div
  v-for="item in items"
  :key="item.id"
>
  {{ item.value }}
</div>

Не используйте v-if в том же элементе, что и v-for

Документация довольно ясно объясняет, почему это плохая идея. Несоблюдение этого правила отрицательно сказывается на производительности - Vue потребуется повторно отрендерить весь список, даже если массив items не изменился.

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

Вместо того…

<div v-for="item in items" v-if="item.shouldShow()">
  {{ item.value }}
</div>

… Вам следует сделать следующее:

<div v-for="item in visibleItems">
    {{ item.value }}
</div>

И добавьте это в свои computed свойства:

visibleItems() {
  return this.items.filter(item => {
    return item.shouldShow();
  });
}

Преимущества этого заключаются в следующем:

  1. Вычисленное свойство visibleItems переоценивается только при изменениях в массиве items.
  2. v-for должен обрабатывать только массив visibleItems, а не весь массив items, что делает рендеринг более эффективным.
  3. Вы поддерживаете более чистый шаблон с меньшим количеством внутренней логики, что всегда хорошо. Помните, что отсоединение логики от уровня представления обеспечивает чистоту и удобство обслуживания.

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

Заключение

Написание чистого и поддерживаемого кода облегчит жизнь тем, кто с вами работает. Но это также сделает вашу жизнь лучше, поскольку вам придется иметь дело с меньшим количеством беспорядков, связанных со спагетти-кодом.

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

Спасибо, что дочитали до этого места!