Vue root stylesheet

Vue root stylesheet Техника

Время на прочтение

Эта статья — перевод оригинальной статьи Lindsay Wardell «Styling Vue Single-File Components«

Также я веду телеграм канал “Frontend по-флотски”, где рассказываю про интересные вещи из мира разработки интерфейсов.

Содержание
  1. Вступление
  2. Scoped стили
  3. Глубокие стили
  4. Slotted стили
  5. Глобальные стили
  6. :global
  7. Несколько блоков стилей
  8. CSS модули
  9. Динамические CSS значения
  10. Заключение
  11. Указание ссылок на ресурсы
  12. Пре-процессоры
  13. Автоматические импорты
  14. PostCSS
  15. CSS-модули
  16. Передача настроек в загрузчики пре-процессоров
  17. Общий ответ на вопрос.
  18. mixins.scss
  19. Parent.vue
  20. Child.vue
  21. Мнение конкретно по Вашему случаю.
  22. # Рекомендации
  23. # Категории правил
  24. # Приоритет A: Важно
  25. # Приоритет B: Настоятельно рекомендуется
  26. # Приоритет C: Рекомендуется
  27. # Приоритет D: Используйте с осторожностью
  28. # Правила приоритета A
  29. # Имена компонентов из нескольких слов важно
  30. Плохо
  31. Хорошо
  32. # Определение входных параметров важно
  33. Плохо
  34. Хорошо
  35. # Уникальные ключи для v-for важно
  36. Плохо
  37. Хорошо
  38. # Избегайте использования v-if с v-for важно
  39. Плохо
  40. Хорошо
  41. # Локальные стили компонента важно
  42. Плохо
  43. Хорошо
  44. # Именование приватных свойств важно
  45. Плохо
  46. Хорошо
  47. Настоятельно рекомендуется
  48. # Файлы компонентов настоятельно рекомендуется
  49. Плохо
  50. Хорошо
  51. # Именование однофайловых компонентов настоятельно рекомендуется
  52. Плохо
  53. Хорошо
  54. # Именование базовых компонентов настоятельно рекомендуется
  55. Плохо
  56. Хорошо
  57. # Именование компонентов, используемых в единственном экземпляре настоятельно рекомендуется
  58. Плохо
  59. Хорошо
  60. # Именование тесно связанных компонентов настоятельно рекомендуется
  61. Плохо
  62. Хорошо
  63. # Порядок слов в именах компонентов настоятельно рекомендуется
  64. Плохо
  65. Хорошо
  66. # Самозакрывающиеся теги компонентов настоятельно рекомендуется
  67. Плохо
  68. Хорошо
  69. # Стиль именования компонентов в шаблонах настоятельно рекомендуется
  70. Плохо
  71. Хорошо
  72. # Стиль именования компонентов в JS/JSX настоятельно рекомендуется
  73. Плохо
  74. Хорошо
  75. # Использование полных слов при именовании компонентов настоятельно рекомендуется
  76. Плохо
  77. Хорошо
  78. # Стиль именования входных параметров настоятельно рекомендуется
  79. Плохо
  80. Хорошо
  81. # Элементы с несколькими атрибутами настоятельно рекомендуется
  82. Плохо
  83. Хорошо
  84. # Простые выражения в шаблонах настоятельно рекомендуется
  85. Плохо
  86. Хорошо
  87. # Простые вычисляемые свойства настоятельно рекомендуется
  88. Плохо
  89. Хорошо
  90. # Значения атрибутов в кавычках настоятельно рекомендуется
  91. Плохо
  92. Хорошо
  93. # Сокращённая запись директив настоятельно рекомендуется
  94. Плохо
  95. Хорошо
  96. # Правила приоритета C
  97. # Порядок опций компонента/экземпляра рекомендуется
  98. # Порядок атрибутов элемента рекомендуется
  99. # Пустые строки между опций компонента/экземпляра рекомендуется
  100. Хорошо
  101. # Порядок секций в однофайловых компонентах рекомендуется
  102. Плохо
  103. Хорошо
  104. Использовать с осторожностью
  105. # Селекторы элементов при использовании scoped используйте с осторожностью
  106. Плохо
  107. Хорошо
  108. # Неявная коммуникация между родительским и дочерними компонентами используйте с осторожностью
  109. Плохо
  110. Хорошо
  111. # Управление состоянием приложения без flux используйте с осторожностью
  112. Плохо
  113. Хорошо
  114. Правила рендеринга атрибутов в области видимости во Vue
  115. Используйте модули CSS во Vue
  116. Подводить итоги
  117. Использование локальных и глобальных стилей
  118. Корневой элемент дочернего компонента
  119. Глубокие селекторы
  120. Динамически генерируемый контент
  121. О чём следует помнить
  122. 2 ответа
  123. Обновленный ответ
  124. Старый ответ

Вступление

Если у вас есть опыт написания однофайловых Vue компонентов, вы, вероятно, сталкивались с написанием CSS в своем компоненте. Они позволяют разработчикам группировать код более логическими способами, а не разбивать компоненты по используемому языку (HTML, CSS или JavaScript). Возможность группировать стили компонентов непосредственно рядом с HTML-кодом, к которому он применяется, является одним из основных преимуществ Vue, включая возможность применять CSS к компоненту, чтобы он не влиял на другие части пользовательского интерфейса.

Однако есть ряд функций взаимодействия Vue с CSS, с которыми вы, возможно, не знакомы, например, применение стилей непосредственно к элементам со слотами или новейшие функции, доступные в Vue 3.2. Давайте рассмотрим некоторые из этих других способов стилизации однофайловых Vue компонентов и их преимущества для ваших приложений.

Scoped стили

Начнем с наиболее частого использования CSS в Vue: стили с ограниченными областями видимости. Одна из трудностей при написании современных приложений заключается в том, что наши CSS файлы начинают расти все больше и больше, пока никто не знает, где используются определенные стили или на что может повлиять данное изменение. Это может привести к копированию определенных CSS селекторов и простому дублированию их для каждого компонента. Для этого есть и другие решения (например, БЭМ или служебные классы), но при работе с компонентной структурой, такой как Vue, имеет смысл сгруппировать классы CSS внутри компонента.

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

<style scoped>
.example { color: red;
}
</style>
<template> <div class="example">hi</div>
</template>

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

Глубокие стили

Это приводит к интересной проблеме. Если стили нашего компонента имеют ограниченную область видимости, как насчет дочерних компонентов? По умолчанию они не получат стили родительского компонента. Однако Vue предоставляет способ сделать это. Давайте посмотрим на пример ниже.

<!-- Card.vue -->
<template> <div> <header> <Title> <slot name="title">Card Title</slot> </Title> </header> <section> <slot>Lorum ipsum dolor sit amet</slot> </section> </div>
</template>
<style scoped>
header :deep(.card-title) { font-weight: bold;
}
section { padding 2rem;
}
</style>
<!-- Title.vue -->
<template> <div class="card-title"><slot>Title</slot></div>
</template>

Используя псевдокласс :deep(), мы можем сообщить Vue, что этот конкретный класс (.card-title) не должен иметь области видимости. Поскольку специальный идентификатор по-прежнему применяется к корневому элементу (заголовку), стиль по-прежнему ограничен, но доступен для любого дочернего компонента ниже него.

Slotted стили

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

<!-- Card.vue -->
<template> <div> <header> <Title> <slot name="title">Card Title</slot> </Title> </header> <section> <slot>Lorum ipsum dolor sit amet</slot> </section> </div>
</template>
<style scoped>
header :deep(.card-title) { font-weight: bold;
}
section { padding 2rem;
}
</style>
<!-- Title.vue -->
<template> <div class="card-title"> <slot>Title</slot> </div>
</template>
<style scoped>
:slotted(h1) { font-size: 3rem;
}
</style>

Здесь мы добавили псевдокласс :slotted, чтобы к любым тегам h1 со слотами применялся правильный стиль. Это может быть надуманный пример, но подумайте о необходимости иметь разные стили заголовка для каждого тега заголовка (или эквивалентного класса CSS). Компонент Title.vue может управлять всеми этими стилями, а не полагаться на то, что тот, кто будет использовать этот компонент передаст правильный класс или стиль.

Глобальные стили

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

:global

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

<style scoped>
:global(.red) { color: red;
}
</style>

Несколько блоков стилей

Также ничто не мешает вам иметь несколько блоков стилей в вашем компоненте. Просто создайте еще один тег <style> и поместите туда свои глобальные стили.

<style>
/* global styles */
</style>
<style scoped>
/* local styles */
</style>

CSS модули

Если вы работали с React, вероятно, вы более знакомы с CSS модулями, в которых вы импортируете CSS файл и получаете доступ к его классам как к JavaScript объекту. То же самое можно сделать в Vue, используя <style module> вместо <style scoped>. Вот пример из документации Vue:

<template> <p :class="$style.red"> This should be red </p>
</template>
<style module>
.red { color: red;
}
</style>

С этим может быть особенно приятно работать, так как вам не придётся использовать строки в своих классах (которые подвержены ошибкам и опечаткам). Vue также позволяет вам переименовывать объект, так что вам не нужно обращаться к ним с помощью $style в вашем шаблоне, если вы этого не хотите.

Динамические CSS значения

Последняя функция Vue — это динамические CSS значения, управляемые состоянием. В современном CSS есть тенденция использовать кастомные свойства как способ динамического обновления значения некоторых CSS свойств. Это может сделать наш CSS более гибким и хорошо взаимодействовать с другим кодом нашего приложения. Давайте посмотрим на пример компонента, который отображает индикатор выполнения:

<template>	<div>	<strong>	Progress	</strong>	<div>{{ progress }}%</div>	<div class="progress-bar">	<div></div>	</div>	</div>
</template>
<script setup>
import { watch } from 'vue'
const props = defineProps({ progress: { type: Number, required: true }
})
watch(props.progress, (value) => document .documentElement .style .setProperty('--complete-percentage', value + '%'), { immediate: true })
</script>
<style scoped>
.progress-bar {	background-color: #ccc;	border-radius: 13px;	padding: 3px;
}
.progress-bar > div { background-color: #000; width: var(--complete-percentage); height: 8px; border-radius: 10px; transition-property: width; transition-duration: 150ms;
}
</style>

Этот компонент принимает число (progress), затем отображает это число и обновляет кастомное CSS свойство. По мере изменения хода выполнения CSS свойство постоянно обновляется, чтобы оставаться в синхронизации с JavaScript значением.

Однако в Vue 3.2 нам предоставляется специальная CSS функция, которая делает все это за нас! Взгляните на обновленный код:

<template>	<div>	<strong>	Progress	</strong>	<div>{{ progress }}%</div>	<div class="progress-bar">	<div></div>	</div>	</div>
</template>
<script setup>
const props = defineProps({ progress: { type: Number, required: true }
})
</script>
<style scoped>
.progress-bar {	background-color: #ccc;	border-radius: 13px;	padding: 3px;
}
.progress-bar > div { background-color: #000; width: v-bind(props.progress); height: 8px; border-radius: 10px; transition-property: width; transition-duration: 150ms;
}
</style>

Используя v-bind (props.progress), мы устранили необходимость в нашем наблюдателе, и теперь стал ясно, что наш CSS синхронизируется со значением props.progress. Под капотом Vue делает для нас то же самое с кастомным свойством, но это намного приятнее, чем писать его самостоятельно.

Заключение

На практике CSS — сложный язык, и его смешивание с JavaScript еще более усложняет задачу. Vue предоставляет разработчикам инструменты для надежной и предсказуемой обработки CSS, что способствует построению компонентной архитектуры. В следующий раз, когда у вас возникнут проблемы с CSS во Vue, посмотрите, может ли вам пригодиться один из этих методов!

Проекты Vue CLI предоставляют поддержку для PostCSS, CSS-модулей, а также пре-процессоров, включая Sass, Less и Stylus.

Указание ссылок на ресурсы

Весь скомпилированный CSS обрабатывается css-loader, который будет парсить url() и разрешать их как зависимостями модуля. Это означает, что вы можете ссылаться на ресурсы, используя относительные пути на основе локальной файловой структуры. Обратите внимание, что если вы хотите ссылаться на файл внутри npm-зависимости или через псевдоним webpack, путь должен начинаться с префикса ~ для избежания двусмысленности. Подробнее в разделе Обработка статических ресурсов.

Пре-процессоры

Вы можете выбрать пре-процессоры (Sass/Less/Stylus) при создании проекта. Если вы этого не сделали, то внутренняя конфигурация webpack всё равно настроена для их использования. Вам лишь требуется вручную доустановить соответствующие загрузчики для webpack:

Теперь вы можете импортировать соответствующие типы файлов, или использовать их синтаксис внутри файлов *.vue с помощью:

Автоматические импорты

Вы также можете использовать vue-cli-plugin-style-resources-loader.

PostCSS

Vue CLI использует PostCSS внутри себя.

Вы можете настроить PostCSS через .postcssrc или любую другую конфигурацию, которая поддерживается postcss-load-config, а также настраивать postcss-loader через опцию css.loaderOptions.postcss в файле vue.config.js.

Плагин autoprefixer включён по умолчанию. Чтобы определить целевые браузеры используйте поле browserslist в файле package.json.

Примечание о префиксных CSS правилах

В сборке для production Vue CLI оптимизирует ваш CSS и удаляет ненужные префиксные правила CSS, основываясь на целевых браузерах. С autoprefixer включённым по умолчанию, вы должны всегда использовать только CSS-правила без префиксов.

CSS-модули

CSS-модули в файлах *.vue доступны из коробки с помощью <style module>.

Если вы не хотите указывать .module в именах файлов, установите css.modules в true внутри файла vue.config.js:

Если вы хотите настроить генерируемые имена классов для CSS-модулей, вы можете сделать это с помощью опции css.loaderOptions.css в vue.config.js. Все настройки css-loader поддерживаются, например localIdentName и camelCase:

Передача настроек в загрузчики пре-процессоров

Иногда может возникнуть необходимость передать настройки в загрузчик пре-процессора для webpack. Вы можете сделать это с помощью опции css.loaderOptions в vue.config.js. Например, для передачи глобальных переменных во все стили Sass/Less:

Загрузчики которые можно настраивать с помощью опции loaderOptions:

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

Общий ответ на вопрос.

mixins.scss

@mixin roboto-text { font-family: Roboto; font-style: normal; font-weight: 500;
}

Parent.vue

<style scoped lang="scss"> @import "mixins.scss"; .some-class { @include roboto-text; }
</style>

Child.vue

<style scoped lang="scss"> @import "mixins.scss"; .other-class { @include roboto-text; }
</style>

mixins.scss можно импортировать глобально. Это скорее всего будет масимально не очевидно для вашей IDE но вы сможете использовать миксины не импортируя их.

Для этого нужно создать vue.config.js файл.

// vue.config.js
module.exports = { css: { loaderOptions: { // передать параметры для sass-loader sass: { // @/ алиас для src/ // строка ниже будет интерпритированна как `src/variables.scss` // при сборке проекта, вначале эта строка будет добавлена во // все style в SFC (Single File Component). А затем скомпилированна SCSS. data: `@import "@/mixins.scss";` } } }
}

Мнение конкретно по Вашему случаю.

Для глобальных настроек (например основной шрифт). Можно поместить в не scoped стили в App.vue.

<style lang="scss"> // стили которые будут доступны во всем проекте.
</style>
<style scoped lang="scss"> // стили которые будут доступны только внутри данного компонента.
</style>

# Рекомендации

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

Дополнительно:  Три нудных гудка при старте и компьютер не включается ( ): ru_mac — LiveJournal

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

Наконец, мы разделили правила на четыре категории:

# Категории правил

# Приоритет A: Важно

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

# Приоритет B: Настоятельно рекомендуется

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

# Приоритет C: Рекомендуется

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

  1. тренировать свой мозг, чтобы легче разбираться в большинстве кода сообщества, с которым придётся столкнуться
  2. иметь возможность копировать и использовать большинство примеров кода сообщества без изменений
  3. чаще находить новых сотрудников, уже знакомых с предпочитаемым стилем кода, по крайней мере, в отношении Vue

# Приоритет D: Используйте с осторожностью

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

# Правила приоритета A

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

Имена компонентов должны всегда состоять из нескольких слов, за исключением корневого компонента App и встроенных компонентов самого Vue, например, <transition> или <component>.

Это предотвращает конфликты (opens new window) с существующими или будущими HTML-элементами, поскольку все HTML-элементы именуются одним словом.

Плохо

app 
 name 

Хорошо

app 
 name 

# Определение входных параметров важно

Входные параметры должны быть определены как можно более подробно.

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

Подробное объяснение

Подробное определение входных параметров имеет два преимущества:

  • Документирование API компонента, что позволит легко понимать, как этот компонент должен использоваться.
  • При разработке, Vue будет предупреждать вас, если компоненту были переданы входные параметры неправильного формата, позволяя вам отловить и исправить потенциальные источники ошибок.

Плохо

// Этого достаточно лишь для прототипаprops 

Хорошо

props status String
// Ещё лучше!props status type String required value 

# Уникальные ключи для v-for важно

Всегда используйте key с v-for.

key с v-for всегда обязателен для компонентов, для поддержания внутреннего состояния компонента и его поддерева. Даже для элементов это хорошая практика для поддержания предсказуемого поведения, такого как консистентности объекта (opens new window) в анимации.

Подробное объяснение

Представим, что у нас есть список различных todo:

 todos id text 'Изучить, как использовать v-for' id text 'Изучить, как использовать key' 

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

Проблема в том, что бывают случаи, когда важно не удалять элементы, которые останутся в DOM. Например, вы можете использовать <transition-group> для анимации сортировки списка, или удержании фокуса, если отображаемый элемент является <input>. В этих случаях добавление уникального ключа для каждого элемента (например, :key="todo.id") подскажет Vue, как вести себя более предсказуемо.

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

Плохо

  todo in todos {{ todo.text }} 

Хорошо

  todo in todos  {{ todo.text }} 

# Избегайте использования v-if с v-for важно

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

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

Подробное объяснение

Когда Vue обрабатывает директивы, v-if имеет более высокий приоритет, чем v-for, поэтому такой шаблон:

 {{ user.name }} 

Это легко исправить используя вычисляемое свойство, например так:

computed users userisActive 

 {{ user.name }} 

В качестве альтернативы, можно использовать тег <template> с v-for для оборачивания элемента <li>:

 {{ user.name }} 

Плохо

 {{ user.name }} 

Хорошо

 {{ user.name }} 
 {{ user.name }} 

# Локальные стили компонента важно

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

Это относится только к однофайловым компонентам. Это не требует использования атрибута scoped (opens new window). Область действия стилей может ограничиваться через CSS-модули (opens new window), стратегию на основе именования классов, такой как БЭМ (opens new window), или другой библиотекой/соглашением.

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

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

Подробное объяснение

Если вы разрабатываете большой проект, работая совместно с другими разработчиками или иногда используете сторонний HTML/CSS (например, от Auth0), консистентное ограничение области позволит гарантировать, что ваши стили применяются только к компонентам, для которых они предназначены.

Помимо атрибута scoped, использование уникальных имён классов может помочь гарантировать, что сторонний CSS не применяется к вашему собственному HTML. Например, многие проекты используют классы button, btn или icon, поэтому даже если вы не используете стратегию, такую как БЭМ, то добавление префикса приложения и/или компонента (например, ButtonClose-icon) может обеспечить некоторую защиту.

Плохо

  ×

Хорошо

  ×<!-- Использование атрибута `scoped` -->
 ×<!-- Использование CSS-модулей -->
  ×<!-- Использование методологии БЭМ -->

# Именование приватных свойств важно

Используйте область видимости модуля, чтобы приватные функции были недоступны извне. Если это невозможно, всегда используйте префикс $_ для пользовательских приватных свойств в плагине, примеси и т.п. Таким образом, они не рассматриваться как публичный API-интерфейс. Затем, чтобы избежать конфликтов с кодом других авторов, также включайте именованную область (например, $_yourPluginName_).

Подробное объяснение

Vue использует префикс _ для определения собственных приватных свойств, поэтому использование одного и того же префикса (например, _update) может привести к перезаписи свойства экземпляра. Даже если вы проверяете и Vue в настоящее время не использует определённое имя свойства, нет гарантий, что конфликт не возникнет в более поздних версиях.

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

Вместо этого мы рекомендуем комбинировать два префикса в $_, как соглашение для пользовательских приватных свойств, которые гарантируют отсутствие конфликтов с Vue.

Плохо

 myGreatMixin methods 
 myGreatMixin methods 
 myGreatMixin methods 
 myGreatMixin methods 

Хорошо

 myGreatMixin methods 
// Ещё лучше! myGreatMixin methods myGreatMixin

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

# Файлы компонентов настоятельно рекомендуется

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

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

Плохо

app
app 

Хорошо

components/
|- TodoList.js
|- TodoItem.js
components/
|- TodoList.vue
|- TodoItem.vue

# Именование однофайловых компонентов настоятельно рекомендуется

Имена файлов однофайловых компонентов должны быть всегда в PascalCase или всегда в kebab-case.

PascalCase лучше всего работает с автодополнением в редакторах кода, поскольку он согласуется с тем, как мы ссылаемся на компоненты в JS(X) и шаблонах. Тем не менее, смешанные имена файлов иногда могут создавать проблемы для нечувствительных к регистру файловых систем, поэтому kebab-case также вполне приемлем.

Плохо

components/
|- mycomponent.vue
components/
|- myComponent.vue

Хорошо

components/
|- MyComponent.vue
components/
|- my-component.vue

# Именование базовых компонентов настоятельно рекомендуется

Базовые компоненты (известные как презентационные, глупые или чистые компоненты) которые применяют специфичные для вашего приложения стили или соглашения должны начинаться с определённого префикса, такого как Base, App или V.

Подробное объяснение

Эти компоненты закладывают основу для консистентности стилей и поведения в вашем приложении. Они могут содержать только:

  • HTML-элементы,
  • другие базовые компоненты
  • сторонние UI-компоненты.

Но они никогда не содержат глобальное состояние (например, из хранилища Vuex).

Их имена зачастую содержат название элемента, который они оборачивают (например, BaseButton, BaseTable), если не существует элемента для этих конкретных целей (например, BaseIcon). Если вы создадите похожие компоненты для более специфичного контекста, они почти всегда будут поглощать эти компоненты (например, BaseButton может использоваться в ButtonSubmit).

Некоторые преимущества этого соглашения:

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

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

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

     requireComponent require
    requireComponent baseComponentConfig fileName baseComponentConfig baseComponentConfigdefault baseComponentConfig baseComponentName baseComponentConfigname fileName appbaseComponentName baseComponentConfig

Плохо

components/
|- MyButton.vue
|- VueTable.vue
|- Icon.vue

Хорошо

components/
|- BaseButton.vue
|- BaseTable.vue
|- BaseIcon.vue
components/
|- AppButton.vue
|- AppTable.vue
|- AppIcon.vue
components/
|- VButton.vue
|- VTable.vue
|- VIcon.vue

# Именование компонентов, используемых в единственном экземпляре настоятельно рекомендуется

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

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

Плохо

components/
|- Heading.vue
|- MySidebar.vue

Хорошо

components/
|- TheHeading.vue
|- TheSidebar.vue

# Именование тесно связанных компонентов настоятельно рекомендуется

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

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

Дополнительно:  Система охлаждения ноутбука – проблемы, решения и модернизация
Подробное объяснение

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

components/
|- TodoList/ |- Item/ |- index.vue |- Button.vue |- index.vue

components/
|- TodoList/ |- Item/ |- Button.vue |- Item.vue
|- TodoList.vue

Это не рекомендуется, так как это приводит к:

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

Плохо

components/
|- TodoList.vue
|- TodoItem.vue
|- TodoButton.vue
components/
|- SearchSidebar.vue
|- NavigationForSearchSidebar.vue

Хорошо

components/
|- TodoList.vue
|- TodoListItem.vue
|- TodoListItemButton.vue
components/
|- SearchSidebar.vue
|- SearchSidebarNavigation.vue

# Порядок слов в именах компонентов настоятельно рекомендуется

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

Подробное объяснение

Вам может быть интересно:

«Почему мы заставляем называть компоненты менее естественным языком?»

На естественном английском прилагательные и другие дескрипторы обычно располагаются перед существительными, в то время как исключения требуют слов-соединителей. Например:

  • Coffee with milk
  • Soup of the day
  • Visitor to the museum

Вы определённо можете включать эти слова-соединители в именах компонентах если хотите, но порядок всё ещё важен.

Также обратите внимание, то что считается «высоким уровнем» будет относиться к вашему приложению. Например, представьте приложение с формой для поиска. Оно может содержать компоненты наподобие таких:

components/
|- ClearSearchButton.vue
|- ExcludeFromSearchInput.vue
|- LaunchOnStartupCheckbox.vue
|- RunSearchButton.vue
|- SearchInput.vue
|- TermsCheckbox.vue

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

components/
|- SearchButtonClear.vue
|- SearchButtonRun.vue
|- SearchInputExcludeGlob.vue
|- SearchInputQuery.vue
|- SettingsCheckboxLaunchOnStartup.vue
|- SettingsCheckboxTerms.vue

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

Возможно вы захотите решить эту проблему по-другому, переместив все компоненты поиска в отдельный каталог «search», а потом все компоненты параметров в каталог «settings». Мы рекомендуем применять этот подход только в очень больших приложениях (например, из более 100 компонентов) по следующим причинам:

  • Обычно требуется больше времени для навигации по вложенным подкаталогам, чем прокрутка одного каталога components.
  • Конфликты имён (например, многочисленные компоненты ButtonDelete.vue) затрудняют быстрый переход к определённому компоненту в редакторе кода.
  • Рефакторинг становится более сложным, потому что поиска с заменой часто будет недостаточно, чтобы обновить относительные ссылки на перемещённый компонент.

Плохо

components/
|- ClearSearchButton.vue
|- ExcludeFromSearchInput.vue
|- LaunchOnStartupCheckbox.vue
|- RunSearchButton.vue
|- SearchInput.vue
|- TermsCheckbox.vue

Хорошо

components/
|- SearchButtonClear.vue
|- SearchButtonRun.vue
|- SearchInputQuery.vue
|- SearchInputExcludeGlob.vue
|- SettingsCheckboxTerms.vue
|- SettingsCheckboxLaunchOnStartup.vue

# Самозакрывающиеся теги компонентов настоятельно рекомендуется

Компоненты без содержимого должны быть самозакрывающимися тегами в однофайловых компонентах, строковых шаблонах и JSX — но никогда в DOM-шаблонах.

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

К сожалению, HTML не разрешает пользовательским элементам быть самозакрывающимися — только официальные «void» элементы (opens new window). Вот почему эта стратегия возможна только тогда, когда компилятор шаблонов Vue может достичь шаблона перед DOM, а затем предоставить DOM-совместимый HTML.

Плохо

<!-- В однофайловых компонентах, строковых шаблонах и JSX -->
<!-- В DOM-шаблонах -->

Хорошо

<!-- В однофайловых компонентах, строковых шаблонах и JSX -->
<!-- В DOM-шаблонах -->

# Стиль именования компонентов в шаблонах настоятельно рекомендуется

В большинстве проектов имена компонентов всегда должны быть в PascalCase в однофайловых компонентах и строковых шаблонах — но в kebab-case в случае DOM-шаблонов.

PascalCase имеет следующие преимущества перед kebab-case:

  • Редакторы могут автодополнять имена компонентов в шаблонах, потому что PascalCase также используется в JavaScript.
  • <MyComponent> более визуально отличается от элемента HTML из одного слова, нежели <my-component>, потому что есть две заметных разницы в символах (две заглавных), а не только одна (дефис).
  • Если вы используете какие-либо пользовательские элементы, отличные от Vue, в ваших шаблонах, например, веб-компонент, PascalCase гарантирует, что ваши компоненты Vue остаются отчётливо видимыми.

К сожалению, из-за нечувствительности HTML к регистру, DOM-шаблоны должны по-прежнему использовать kebab-case.

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

Плохо

<!-- В однофайловых компонентах и строковых шаблонах -->
<!-- В однофайловых компонентах и строковых шаблонах -->
<!-- В DOM-шаблонах -->

Хорошо

<!-- В однофайловых компонентах и строковых шаблонах -->
<!-- В DOM-шаблонах -->
<!-- Везде -->

# Стиль именования компонентов в JS/JSX настоятельно рекомендуется

Стиль именования компонентов в JS/JSX всегда должен быть PascalCase, хотя они могут быть в kebab-case внутри строк для простых приложений, которые используют только глобальную регистрацию компонентов через app.component.

Подробное объяснение

В JavaScript PascalCase — это соглашение для классов и конструкторов прототипов — по существу всё, что может иметь разные экземпляры. Компоненты Vue также могут иметь экземпляры, поэтому также имеет смысл использовать PascalCase. В качестве дополнительного преимущества, использование PascalCase в JSX (и шаблонах) позволяет изучающим код легче различать компоненты от HTML-элементов.

Однако, для приложений, которые используют только глобальные определения компонентов через app.component, мы рекомендуем вместо него использовать kebab-case. Причины:

  • Редкость, когда на глобальные компоненты ссылаются в JavaScript, поэтому следование соглашению для JavaScript имеет меньше смысла.
  • Эти приложения всегда включают в себе множество шаблонов внутри DOM, где kebab-case должен быть использован.

Плохо

app 
 myComponent 
 name 
 name 

Хорошо

app 
app 
 MyComponent 
 name 

# Использование полных слов при именовании компонентов настоятельно рекомендуется

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

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

Плохо

components/
|- SdSettings.vue
|- UProfOpts.vue

Хорошо

components/
|- StudentDashboardSettings.vue
|- UserProfileOptions.vue

# Стиль именования входных параметров настоятельно рекомендуется

Входные параметры должны всегда использовать camelCase при определении, но kebab-case в шаблонах и JSX.

Мы просто придерживаемся соглашений каждого языка. Для JavaScript использовать camelCase является более естественным. Для HTML — kebab-case.

Плохо

props String

Хорошо

props greetingText String

# Элементы с несколькими атрибутами настоятельно рекомендуется

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

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

Плохо

 
 

Хорошо

 
 

# Простые выражения в шаблонах настоятельно рекомендуется

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

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

Плохо

{{ fullName.split(' ').map(word => { return word[0].toUpperCase() + word.slice(1) }).join(' ')
}}

Хорошо

<!-- В шаблоне -->{{ normalizedFullName }}
// Комплексное выражение было вынесено в вычисляемое свойствоcomputed fullName word word 

# Простые вычисляемые свойства настоятельно рекомендуется

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

Подробное объяснение

Проще говоря, хорошие вычисляемые свойства будет:

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

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

  • Лучше приспособлены к изменяющимся требованиям

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

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

Плохо

computed basePrice manufactureCost profitMargin basePrice basePrice discountPercent 

Хорошо

computed manufactureCost profitMargin basePrice discountPercent basePrice discount 

# Значения атрибутов в кавычках настоятельно рекомендуется

Непустые значения HTML-атрибутов должны быть обрамлены кавычками (одинарными или двойными, в зависимости от того, что не используется в JS).

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

Плохо

<AppSidebar :style={width:sidebarWidth+'px'}>

Хорошо

# Сокращённая запись директив настоятельно рекомендуется

Плохо

 
 Здесь может быть заголовок страницы Здесь контактная информация

Хорошо

 
 
 
 Здесь может быть заголовок страницы Здесь контактная информация
 Здесь может быть заголовок страницы Здесь контактная информация

# Правила приоритета C

# Порядок опций компонента/экземпляра рекомендуется

Опции компонента/экземпляра должны быть упорядочены консистентно.

Это порядок по умолчанию, который мы рекомендуем для опций компонентов. Они разделены на категории, поэтому вы поймёте, где добавлять новые свойства из плагинов.

# Порядок атрибутов элемента рекомендуется

Атрибуты элементов (в том числе компонентов) должны быть упорядочены консистентно.

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

# Пустые строки между опций компонента/экземпляра рекомендуется

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

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

Хорошо

props value type String required focused type Boolean label String icon String
computed 
// Отсутствие пробелов не мешает, если компонент// всё ещё легко читать и перемещаться по нему.props value type String required focused type Boolean label String icon String
computed 

# Порядок секций в однофайловых компонентах рекомендуется

Однофайловые компоненты должны всегда использовать один порядок для корневых тегов секций <script>, <template> и <style>, заканчиваясь <style>, потому что всегда требуется хотя бы одна из двух других.

Плохо

...
<!-- ComponentA.vue -->...<!-- ComponentB.vue -->...

Хорошо

<!-- ComponentA.vue -->...<!-- ComponentB.vue -->...
<!-- ComponentA.vue -->...<!-- ComponentB.vue -->...

Использовать с осторожностью

# Селекторы элементов при использовании scoped используйте с осторожностью

Селекторов элементов следует избегать при использовании scoped.

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

Подробное объяснение

Плохо

 ×

Хорошо

  ×

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

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

В идеальном Vue приложении входные параметры передаются вниз, события всплывают наверх. Придерживаясь этого соглашения ваши компоненты будет намного легче понять. Тем не менее, есть крайние случаи, когда изменения входных параметров или использование this.$parent могут упростить два компонента, которые уже глубоко связаны между собой.

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

Плохо

app props todo type Object required template 
app props todo type Object required methods $parenttodos $parenttodos todoid vmtodoid template 

Хорошо

app props todo type Object required emits template 
app props todo type Object required emits template 

# Управление состоянием приложения без flux используйте с осторожностью

Vuex (opens new window) должен быть предпочтительным способом для глобального управления состоянием приложения вместо использования this.$root или глобальной шины событий.

Дополнительно:  Ошибка 0xc000000f: что делать, как исправить при запуске Windows на компьютере и ноутбуке

Управление состоянием через this.$root и/или использование глобальной шины событий может быть удобным для очень простых случаев, но не подходит для большинства приложений.

Vuex — официальная flux-подобная реализация для Vue, и предлагает не только централизованное место для управления состоянием, а также инструменты организации, отслеживания и отладки изменений состояния. Она хорошо интегрируется в экосистему Vue (включая полную поддержку Vue DevTools).

Плохо

 createApp mitt app todos emitter emitter removeTodo methods todoIdToRemove todoid todos todos todoid todoIdToRemove 

Хорошо

 state list mutations statelist statelist todoid todoId actions todoid 
<!-- TodoItem.vue --> {{ todo.text }} X 

Правила рендеринга атрибутов в области видимости во Vue

  1. Добавьте уникальный атрибут данных (например, data-v-7ba5bd90) к узлу DOM, чтобы указать его уникальность.
  2. Добавьте селектор атрибутов данных текущего компонента (например, [data-v-7ba5bd90]) в конце каждого селектора CSS (CSS, созданный после компиляции), чтобы приватизировать стиль. Атрибут данных в конце селектора соответствует атрибуту данных в соответствующей модели DOM.
  3. На самой внешней метке дочернего компонента есть класс, который был определен в родительском компоненте, тогда стиль родительского компонента также будет применен к дочернему компоненту. Просто его вес не такой тяжелый, как одноименный подкомпонент.
  4. Если компонент содержит другие компоненты, только атрибут данных текущего компонента будет добавлен к самой внешней метке другого компонента.
  5. Если родительский компонент хочет изменить стиль метки в дочернем компоненте, вы можете использовать соединитель >>> или / deep /, чтобы решить эту проблему.
<!-- Button.vue --> <template> <button class="btn"> <span> <slot></slot> </span> </button> </template> <style scoped> .btn { color: red; } </style>
<!-- App.vue -->
<template>	<div id="app">	<Button class="btn-lg">click</Button> </div>
</template>
<script>	import Button from "./components/Button";	export default {	name: "App",	components: {	Button	}	};
</script>
<style scoped>	.btn>>> span {	color: green;	font-weight: bold;	border: 1px solid green;	padding: 10px;	}
</style>
  1. Подкомпонент (‘button class =» btn «’) Внутренний стиль метки в v-html не действует. Принцип и решение те же, что и в 4 и 5.

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

<style lang="scss" type="text/scss" rel="stylesheet/scss" scoped> // Здесь вы можете написать стиль родительского компонента и стиль самого внешнего элемента дочернего компонента
</style>
<style lang="scss" type="text/scss" rel="stylesheet/scss"> // Здесь вы можете записать стиль в дочернем компоненте, но это должен быть уникальный идентификатор родительского компонента, указывающий, что этот стиль изменяется только во внутреннем стиле компонента под конкретным родительским компонентом #Parent component id { .Sub-component style { Стиль заголовка субкомпонента	}	}
</style>

Но независимо от того, используется ли выше >>> connector или / deep / для решения, или мой глупый метод фактически уничтожает стиль в упакованном компоненте, но это также теряет эффект инкапсуляции компонента. Вернемся к предыдущей головной боли в CSS: область видимости CSS.

Используйте модули CSS во Vue

Вот лишь краткое описание, потому что я не использовал модули CSS и у меня много контактов с областями действия, и я лично считаю, что использование модулей CSS слишком громоздко, а области действия достаточно, чтобы решить проблему управления стилями Css. Вышесказанное является лишь небольшим личным мнением. Если есть Просветите меня, если что не так!
1. Основное использование

Добавьте атрибут модуля к тегу стиля, чтобы указать, что включен модульный режим CSS-загрузчика

<style module>	.btn { color: red; }
</style>

Используйте динамическую привязку класса: class в шаблоне и добавьте «$ style.» Перед именем класса.

<template> <button :class="$style.btn">{{msg}}</button> </template>

Эффект будет следующим:: class = «$ style.btn» будет скомпилировано в имя класса .Button_btn_3ykLd, и селектор стиля автоматически изменится соответственно.
Vue root stylesheet
На заметку:

  • Если имя класса содержит среднюю линию или имя класса имеет верблюжий регистр, используйте синтаксис скобок.
<h4: class = "$ style ['header-tit']"> Рекомендация категории </h4>
  • Вы также можете использовать синтаксис массива или объекта
<p :class="{ [$style.red]: isRed }"> Am I red? </p> <p :class="[$style.red, $style.bold]"> Red and bold </p>
  • Более сложный синтаксис объекта
<ul
    :class="{ [$style.panelBox]:true, [$style.transitionByPanelBox]:needTransition }"> </ul>

Его непросто использовать, scss нельзя использовать, и нельзя выбрать стиль вложения второго уровня, чтобы он вступил в силу.

<template>	<div class="warp">	<div :class="$style['aa']">	123	<div :class="$style['bb']">	ffff	</div>	</div>	<div :class="$style['bb']">	ddddddd	</div>	</div>
</template>
<script>
</script>
// Пример ошибки
<style module lang="scss">	.aa{	background-color: #00B43C;	.bb{	border: 1px solid #66512C;	}	}	/*.aa*/
</style> Правильный пример:
<style module>	.aa{	background-color: #00B43C;	}	.aa .bb{	border: 1px solid #66512C;	}
</style>

2. Дочерний компонент вызывает стиль родительского компонента.

<!-- Button.vue -->
<template> <button :class="[$style.btn, primaryClass]">{{msg}}</button> </template>
<script>	export default {	name: 'Button',	props: {	msg: String,	primaryClass: ''	}	}
</script>
<style module>	.btn {	border: 1px solid #ccc;	border-radius: 3px;	padding: 5px 15px;	background: #fefefe;	margin: 5px;	}
</style>
<!-- App.vue -->
<template>	<div id="app">	<Button msg="Default Button" />	<Button :class="{[$style['btn-lg']]: isLg}" msg="Larger Button" />	<Button :class="{[$style['btn-sm']]: isSm}" msg="Smaller Button" />	<Button msg="Primary Button" :primaryClass="$style['btn-primary']" /> </div>
</template>
<script>	import Button from './components/Button'	export default {	name: 'app',	components: {	Button	},	data() {	return {	isLg: true,	isSm: false	}	}	}
</script>
<style module>	.btn-lg {	padding: 15px 30px;	}	.btn-sm {	padding: 5px;	}	.btn-primary {	background: rgb(54, 152, 244);	border-color: rgb(32, 108, 221);	color: #fff;	}
</style>

Схема эффекта выглядит следующим образом:
Vue root stylesheet
(Хотя вышеупомянутый метод может реализовать стиль дочернего компонента, вызывающего родительский компонент, я все же хочу пожаловаться, не следует ли писать стиль дочернего компонента в стиле дочернего компонента? Нарушило ли это первоначальное намерение инкапсуляции стиля компонента? Если вы действительно хотите изменить стиль субкомпонента, например, стиль инкапсулированного компонента element-ui в проекте vue, обнаруженный в апелляции, вы не очень довольны и не можете пойти, если хотите его изменить. Передайте реквизиты компоненту, инкапсулированному element-ui, чтобы изменить стиль ???)
3. Конфигурация
Официальная конфигурация:

// webpack.config.js
{ module: { rules: [ // ... остальные правила опущены { test: /\.css$/, use: [ 'vue-style-loader', { loader: 'css-loader', options: { // Открываем модули CSS modules: true, // Настроить имя сгенерированного класса localIdentName: '[local]_[hash:base64:8]' } } ] } ] }
}

Есть другой способ: добавить следующую конфигурацию в vue.config.js

css: { loaderOptions: { css: { localIdentName: '[name]__[local]-[hash:base64:5]', camelCase: true } } } // localIdentName - это форматированное имя класса: name - это имя текущего файла, local - это имя текущего определенного имени класса, hash - это строка, сгенерированная хешем, а длина - 5 // camelCase: когда в имени класса есть горизонтальная линия, "only" поддерживает только большой горб при привязке имени класса к этикетке, true: поддерживает именование большого горба и скобок.

В любом случае, ни один из этих методов у меня не преуспел, пожалуйста, попросите совета у Бога! Стиль такой
Vue root stylesheet

Подводить итоги

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

  1. CSS должен иметь логотип: чтобы облегчить изменение стиля и поиск.

Vue root stylesheetVue root stylesheet
2. Используйте область видимости для регионализации стиля CSS
3. Если вы хотите изменить инкапсулированный стиль субкомпонента, вы должны четко указать на внешнем слое стиль субкомпонента, под которым находится родительский компонент, чтобы не изменять глобальный стиль.

<style lang="scss" type="text/scss" rel="stylesheet/scss" scoped> // Здесь вы можете написать стиль родительского компонента и стиль самого внешнего элемента дочернего компонента
</style>
<style lang="scss" type="text/scss" rel="stylesheet/scss"> // Здесь вы можете записать стиль в дочернем компоненте, но это должен быть уникальный идентификатор родительского компонента, указывающий, что этот стиль изменяется только во внутреннем стиле компонента под конкретным родительским компонентом #Parent component id { .Sub-component style { Стиль заголовка субкомпонента	} }
</style>

Когда у тега <style> есть атрибут scoped, то его CSS будет применяться только к элементам текущего компонента. Это похоже на инкапсуляцию стилей в Shadow DOM. Пользоваться ими можно с некоторыми оговорками, но зато не требуется никаких полифиллов. Это достигается за счёт использования PostCSS для преобразования следующего:

В что-то подобное:

Использование локальных и глобальных стилей

Вы можете использовать в компоненте локальные и глобальные стилей одновременно:

Корневой элемент дочернего компонента

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

Глубокие селекторы

Если вы хотите, чтобы селектор в scoped стилях был «глубоким», т.е. влиял на дочерние компоненты, вы можете использовать комбинатор >>>:

Указанное выше будет скомпилируется в подобный селектор:

Некоторые пре-процессоры, такие как SASS, не могут правильно обработать >>>. В таких случаях используйте комбинатор /deep/ — это псевдоним для >>> работающий аналогично.

Динамически генерируемый контент

DOM-содержимое, создаваемое с помощью v-html не попадает под область действия локальных стилей, но вы всё равно можете его стилизовать с помощью глубоких селекторов.

О чём следует помнить

  • Будьте внимательны с селекторами потомков в рекурсивных компонентах! Для CSS-правила с селектором .a .b, если элемент, который соответствует .a содержит рекурсивный компонент потомок, тогда все .b в этом компоненте потомке будут также соответствовать правилу.

Я создаю приложение Vue 3 с помощью scss. У меня есть 3 файла таблиц стилей — _mixins.scss, _variables.scss и base.scss. Я импортирую файлы миксинов и переменных в vue.config.js, когда читаю здесь, поэтому я могу использовать эти миксины и переменные во всех других моих компонентах, не импортируя их вручную во все компоненты.

К сожалению, в обоих случаях компилятор Sass выдает эту ошибку:

Syntax Error: SassError: @use rules must be written before any other rules. ╷
6 │ @use "styles/base"; │ ^^^^^^^^^^^^^^^^^^ ╵ D:\PWND\pwnd_ui_poc_js\src\App.vue 6:1 root stylesheet

Я действительно не знаю, как мне это правильно делать. Для полноты картины я включаю базовую структуру своих файлов:

// _variables.scss
$baseGreen: #24ff00;
// _mixins.scss
@forward "variables";
@mixin section-heading { color: $baseGreen;
}
// base.scss
@forward "mixins";
@forward "variables";
.section { color: $baseGreen; &-heading { @include section-heading(); }
}

Если у вас есть идеи, как мне это сделать правильно, я был бы очень признателен за вашу помощь. Спасибо! 🙂

В проекте Nuxt я создал компонент кнопки со следующим стилем:

<style lang="scss"> .my-button { // lots of cool styles and stuff here $height: 28px; height: $height; border-radius: $height / 2; } </style>

Проблема в том, что строка border-radius: $height / 2; дает следующее предупреждение:

 ╷
182 │ border-radius: $height / 2; │ ^^^^^^^^^^^ ╵ components/MyButton.vue 182:20 button-size() components/MyButton.vue 186:5 root stylesheet
: Using / for division is deprecated and will be removed in Dart Sass
2.0.0.
Recommendation: math.div($height, 2)

Он также ссылается на эту страницу с описанием прекращения поддержки.

 <style lang="scss"> @use "sass:math"; //Cool styles and stuff $height: 28px; height: $height; border-radius: math.div($height, 2); </style>

Я получаю такую ​​ошибку:

 [Vue warn]: Error in render: "Error: Module build failed (from ./node_modules/sass-loader/dist/cjs.js): 12:13:59
SassError: @use rules must be written before any other rules. ╷
102 │ @use "sass:math"; │ ^^^^^^^^^^^^^^^^ ╵ components/MyButton.vue 102:1 root stylesheet"

Блоки, связанные с css, в моем nuxt.config.js в настоящее время выглядят так:

 build: { postcss: { plugins: { 'postcss-easing-gradients': {}, }, }, }, styleResources: { scss: [ '~/assets/global-inject.scss', ], }, css: [ '~/assets/base.scss', '~/assets/reset.scss', ],

2 ответа

Я изменил объект styleResources в nuxt.config.js на:

styleResources: { scss: [ '~/assets/global-inject.scss', ], hoistUseStatements: true, },

14 Сен 2021 в 11:40

Обновленный ответ

Что, если вы попробуете это в своем файле nuxt.config.js?

{ build: { loaders: { scss: { additionalData: ` @use "@/styles/colors.scss" as *; @use "@/styles/overrides.scss" as *; `, }, }, ...
}

Или вы можете попробовать одно из многочисленных решений здесь: https: // github.com/nuxt-community/style-resources-module/issues/143


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


Кроме того, если это предупреждение, оно пока не блокируется или каким-то образом нарушает работу вашего приложения?


Старый ответ

Мой ответ здесь, вероятно, может вам помочь: https://stackoverflow.com/a/68648204/8816585

Это вопрос обновления до последней версии и устранения этих предупреждений.

13 Сен 2021 в 15:47

Оцените статью
Master Hi-technology