Изоляция стилей и состояния

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

Scoped-стили

Vue предоставляет встроенный механизм для локализации CSS через атрибут scoped в <style>. При использовании:

<template>
  <div class="button">
    Нажми меня
  </div>
</template>

<script>
export default {
  name: 'MyButton'
}
</script>

<style scoped>
.button {
  background-color: #42b983;
  color: white;
  padding: 10px 20px;
  border-radius: 4px;
}
</style>

Особенности scoped:

  • Vue автоматически добавляет уникальные атрибуты к элементам компонента и селекторам CSS, что предотвращает попадание стилей в другие компоненты.
  • Не поддерживаются глобальные псевдоклассы типа :root напрямую. Для глобальных стилей используют <style> без scoped или :deep() селектор.
::v-deep(.global-class) {
  color: red;
}

Локальное состояние компонента

Каждый компонент Vue имеет собственный объект data, который создаётся при инстанциировании:

export default {
  data() {
    return {
      count: 0
    };
  },
  methods: {
    increment() {
      this.count++;
    }
  }
};

Преимущества локального состояния:

  • Изменения не влияют на другие компоненты.
  • Обеспечивает предсказуемость поведения UI.
  • Упрощает тестирование, так как компонент можно тестировать изолированно.

Props и события для управления состоянием

Изоляция состояния компонентов также поддерживается через передачу данных сверху вниз через props и событий снизу вверх через $emit.

<template>
  <ChildComponent :value="parentValue" @update="handleUpdate" />
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: { ChildComponent },
  data() {
    return { parentValue: 10 };
  },
  methods: {
    handleUpdate(newValue) {
      this.parentValue = newValue;
    }
  }
}
</script>

Основные принципы:

  • props обеспечивают передачу только нужных данных внутрь компонента.
  • $emit позволяет компоненту уведомлять родителя об изменениях, не нарушая инкапсуляцию состояния.

Использование Vuex и Pinia для изоляции глобального состояния

Когда приложение масштабируется, изоляция состояния на уровне компонентов может стать ограниченной. Vuex и Pinia позволяют создавать централизованное управление состоянием, сохраняя при этом локальные участки состояния:

// store.js
import { defineStore } from 'pinia';

export const useCounterStore = defineStore('counter', {
  state: () => ({ count: 0 }),
  actions: {
    increment() {
      this.count++;
    }
  }
});

Компоненты подключаются к хранилищу, не взаимодействуя напрямую с другими компонентами:

import { useCounterStore } from './store.js';

export default {
  setup() {
    const counter = useCounterStore();
    const incrementCounter = () => counter.increment();

    return { counter, incrementCounter };
  }
};

Преимущества:

  • Централизованное управление облегчает масштабирование.
  • Чёткая граница между локальным и глобальным состоянием.
  • Возможность изоляции отдельных модулей состояния.

CSS Modules

Vue также поддерживает CSS Modules, что позволяет полностью локализовать стили компонента с уникальными именами классов:

<template>
  <div :class="$style.button">Кнопка</div>
</template>

<style module>
.button {
  background: #42b983;
  color: white;
  padding: 10px;
}
</style>

Особенности:

  • Классы автоматически превращаются в уникальные идентификаторы.
  • Нет риска конфликта с глобальными стилями.
  • Поддерживается совместно с scoped и CSS-препроцессорами.

Практики для полной изоляции

  1. Минимизировать глобальные стили. Использовать scoped или CSS Modules.
  2. Разделять состояние на локальное и глобальное. Локальное для компонента, глобальное через Vuex/Pinia.
  3. Избегать прямого доступа к DOM и глобальным переменным. Использовать привязку данных Vue и слоты.
  4. Использовать слоты и scoped slots для кастомизации компонентов без вмешательства в внутреннюю структуру.
  5. Соблюдать принцип «один компонент — одна ответственность», чтобы каждый компонент управлял только своим состоянием и стилями.

Итоговое правило

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