оригинальный:Vue.js - Scoped Styles vs CSS Modules
автор:Михал Сайног время выдачи: 28 августа 2018 г.
переводчик: Слушайте дождь в западном зданиивремя выдачи: 2018/9/10
(Пожалуйста, укажите источник)
Переводчик прессы: в этой статье в основном объясняется сравнение между стилем Scoped и модулем CSS. Студентам, знакомым с этими двумя понятиями, также рекомендуется взглянуть, поскольку в статье также упоминаются некоторые понятия, такие как «: экспорт» модулей CSS и существование стиля Scoped.Некоторые дефекты, если вы уже знакомы с этими деталями, пожалуйста, покиньте эту страницу как можно скорее, чтобы не тратить свое время.
Развернуть оригинал
Неудивительно, что CSS в современной веб-разработке далек от совершенства.Сегодня проекты, как правило, довольно сложны, и, учитывая глобальный характер стилей, очень легко получить конфликтующие стили, которые перекрывают друг друга или неявно каскад до элементов, которые мы раньше не рассматривали.The most commonly used solution that we use to reduce the main pain points is introducing the BEM (Block Element Modifier) methodology. However, it addresses only a small part of the bigger problem.
В современной веб-разработке неудивительно, что CSS далек от совершенства. Современные проекты часто довольно сложны, а стили css по своей сути глобальны, поэтому очень легко столкнуться с конфликтами стилей — либо стили перезаписывают друг друга, либо неявно каскадируются до неизвестных ниже элементов, которые следует учитывать.
С точки зрения устранения основных болевых точек CSS, наше общее решение состоит в том, чтобы ввестиBEM(Модификатор блочного элемента). Но это решает лишь малую часть нашей большой проблемы.
Развернуть оригинал
К счастью для нас, сообщество уже разработало решения, которые могут помочь нам разобраться с проблемой более тщательно. модули), **Styled Components**, **Glamourous** или [ **JSS**](http://cssinjs.org/) — это лишь некоторые из самых популярных инструментов, которые мы можем добавить в нашу проектов сегодня. Если вам интересна эта тема, вы можете проверить [этот пост](https://hackernoon.com/all-you-need-to-know-about-css-in-js-984a72d48ebc) - [ Indrek Lasn](https://twitter.com/lasnindrek) очень подробно объясняет всю идею CSS-in-JS.Every new Vue.js application created by vue-cli comes with two great built-in solutions: Scoped CSS and CSS ModulesУ обоих есть свои плюсы и минусы, поэтому давайте рассмотрим их поближе и выясним, какое решение может лучше подойти для вашего случая.
Нам очень повезло, что сообщество разработало решения, которые могут помочь нам с этими проблемами. Может быть, вы слышалиCSS Modules,Styled Components,Glamorous,JSS- Это лишь некоторые из многих популярных инструментов. Если вам интересна эта тема, вы можете проверитьэта почта--авторIndrek LasnЯ сделал очень подробное объяснение мышления CSS-IN-JS.
В каждое приложение Vue.js, созданное с помощью vue-cli, встроено два отличных решения:Scoped CSSа такжеCSS Modules(Модульный CSS). Оба варианта имеют свои плюсы и минусы, поэтому давайте подробнее рассмотрим, какой из них лучше работает в вашем случае.
Ограниченный стиль
In order to get scoped styles working, we just have to add a scoped attribute to the **<style>**
tag:
нам просто нужно<style>
добавить тегscopedсвойство, чтобы включить стили с областью видимости:
<template>
<button class=”button” />
</template>
<style scoped>
.button {
color: red;
}
</style>
It will apply our styles only to elements in the same component by using PostCSS and transforming the above example to the following:
Это приведет к тому, что наши стили будут применяться только к элементам в этом компоненте. Это достигается с помощью PostCSS, который преобразует приведенный выше код в следующий:
<style>
.button[data-v-f61kqi1] {
color: red;
}
</style>
<button class=”button” data-v-f61kqi1></button>
As you can see, it requires no effort at all to have nicely scoped styles, and it also обрабатывает стили тегов области видимости in the same way.
Как видите, весь процесс ничего не должен делать для достижения хорошего эффекта стиля с ограниченной областью видимости.
Теперь, если вам нужно, скажем, изменить ширину компонента в определенном представлении, вы можете применить к нему дополнительный класс и стилизовать его, как обычно, со всеми преимуществами стилей с областью действия:
Теперь предположим, что вам нужно настроить ширину компонента в представлении, тогда вы можете сделать как обычно: добавить к компоненту дополнительный класс для его стилизации.
<template>
<BasePanel class=”pricing-panel”>
content
</BasePanel>
</template>
<style scoped>
.pricing-panel {
width: 300px;
margin-bottom: 30px;
}
</style>
После преобразования:
<style>
.base-panel[data-v-d17eko1] {
...
}
.pricing-panel[data-v-b52c41] {
width: 300px;
margin-bottom: 30px;
}
</style>
<div class=”base-panel pricing-panel” data-v-d17eko1 data-v-b52c41>
content
</div>
Развернуть оригинал
Еще раз - без лишних усилий вы получаете полный контроль над макетом.However, be aware that this feature was introduced with one drawback - if your child component's root element has a class that also exists in the parent component, the parent component's styles will leak to the child. You can check out this CodeSandbox to get a better understanding of the problem.
Хотя этого не рекомендуется и следует избегать — бывают случаи, когда нам нужно стилизовать что-то глубоко внутри нашего дочернего компонента.Для простоты предположим, что наш родительский компонент должен отвечать за стилизацию заголовка компонента BasePanel. стили с ограниченной областью действия,>>>
combinator (also known as /deep/
) comes in at this point.
На этот раз то же самое, не нужно ничего делать, чтобы получить полный контроль над макетом.
Но обратите внимание: У этой функции есть недостаток, то есть, если у вас есть класс в корневом элементе вашего дочернего компонента, который был определен в родительском компоненте, стили родительского компонента будут просачиваться в дочерний компонент. Если вы хотите лучше понять проблему, вы можете проверить этоCodeSandboxпример.
Есть также случаи, когда нам нужно стилизовать глубокую структуру наших дочерних компонентов, хотя это не рекомендуется, и его следует избегать. Для краткости предположим, что наш родительский компонент теперь хочет стилизовать заголовок BasePanel в стилях с ограниченной областью действия, это можно сделать с помощью>>>
разъем (или/deep/
)выполнить.
<style scoped>
.pricing-panel >>> .title {
font-size: 24px;
}
</style>
После преобразования:
.pricing-panel[data-v-b52c41] .title {
font-size: 24px;
}
Plain and simple, huh? But be aware that we just lost the encapsulation. Any .title
class that will be used inside this component (even implicitly by a grandchild) will be affected by these styles.
Очень просто, правда?Но не забывайте, мы потеряли эффект инкапсуляции компонента из-за этого. Все в этом компоненте.title
Этими стилями будут пропитаны стили класса - даже внуки.
Модульный CSS
CSS Modules gained their popularity due to the React community that quickly adopted this technology. Vue.js takes it to another level by combining its power with simplicity of use and out-of-the-box support by using vue-cli.
Популярность модульного CSS связана с сообществом React, где он получил быстрое распространение. Vue.js даже более того, с его мощными и простыми функциями в сочетании сvue-cliПоднимите его на новый уровень благодаря готовой поддержке.
Теперь давайте посмотрим, как мы можем его использовать:
Теперь давайте посмотрим, как его использовать:
<style module>
.button {
color: red
}
</style>
What makes it so special and different from scoped styles is that all the created classes are accessible via the $style
object inside the component. So in order to apply this class we have to use class binding:
На этот раз мы используем неscoped
свойства, ноmodule
. это как сказатьvue-template-compilerи конфигурация веб-пакета vue-cli для использования соответствующих загрузчиков для этой части для создания CSS, как показано ниже:
.ComponentName__button__2Kxy {
color: red;
}
What makes it so special and different from scoped styles is that all the created classes are accessible via the $style
object inside the component. So in order to apply this class we have to use class binding:
Что делает его особенным и отличным от стиля с областью действия, так это то, что ко всем созданным классам можно получить доступ через интерфейс компонента.$style
приобретение объекта. Итак, чтобы применить этот класс, нам нужно сделать привязку класса следующим образом:
<template>
<button :class="$style.button" />
</template>
<style module>
.button {
color: red
}
</style>
Этот код сгенерирует следующий HTML и связанные стили:
<style>
.ComponentName__button__2Kxy {
color: red;
}
</style>
<button class=”ComponentName__button__2Kxy”></button>
Развернуть оригинал
The first benefit is that by looking at this element in our HTML we immediately know which component it belongs to. Secondly, everything becomes very explicit and we have full control - no magic whatsoever. However, we have to be careful while styling HTML tags, as they land in the final CSS as-is, as opposed to scoped styles, where even plain tags are scoped by the unique data attribute.
Как и во втором примере из стилей с областью действия, давайте посмотрим, как мы можем стилизовать компонент в определенном контексте:
Первое преимущество заключается в том, что когда мы смотрим на элемент в HMTL, мы можем сразу узнать, к какому компоненту он принадлежит; второе преимущество заключается в том, что все становится явным, и у нас есть полный контроль — больше не будет странных явлений. В отличие от стиля с заданной областью, который добавляет эти атрибуты данных к обычным тегам, эти обычные теги остаются прежними после преобразования.
Сравнивая второй пример со стилями с ограниченной областью действия, давайте посмотрим, как мы можем стилизовать этот компонент:
<template>
<BasePanel :class="$style['pricing-panel']">
content
</BasePanel>
</template>
<style module>
.pricing-panel {
width: 300px;
margin-bottom: 30px;
}
</style>
После его преобразования:
<style>
.BasePanel__d17eko1 {
/* some styles */
}
.ComponentName__pricing-panel__a81Kj {
width: 300px;
margin-bottom: 30px;
}
</style>
<div class="BasePanel__d17eko1 ComponentName__pricing-panel__a81Kj">
content
</div>
It simply gets the job done, without any surprises! Moreover, because all classes are available through the $style
object we can now pass them however deep we want using props, making it super easy to use a class in any place of the child component:
Никаких сюрпризов, как мы и ожидали. Кроме того, поскольку все классы CSS могут быть$style
object, поэтому мы можем передавать эти классы на любую глубину через реквизиты, что делает чрезвычайно простым использование этих классов в любом месте дочернего компонента:
<template>
<BasePanel
title="Lorem ipsum"
:titleClass="$style.title"
>
Content
</BasePanel>
</template>
CSS Modules have great interoperability with JS, and they do not limit you to classes. Using :export
keyword, we can also export additional things to our $style
object.
Модульный CSS хорошо совместим с JS, а не только с классами CSS. мы также можем использовать:export
ключевое слово для экспорта других вещей в$style
на объекте.
Imagine you have a chart to develop - you can keep your colour variables in CSS, and additionally export them for use in your component:
Например, представьте, что вам нужно разработать диаграмму — вы можете определить свои цветовые переменные в CSS и экспортировать их для использования в своих компонентах:
<template>
<div>{{ $style.primaryColor }}</div> <!-- #B4DC47 -->
</template>
<style module lang="scss">
$primary-color: #B4DC47;
:export {
primaryColor: $primary-color
}
</style>
I only scratched the surface here - the CSS Modules concept is much broader and I encourage you to check out the full specification to know more.
дляМодульный CSSконцепт, здесь я говорил только о его мехе, на самом деле он гораздо шире, предлагаю вам проверитьполная спецификацияУзнать больше.
Суммировать
Развернуть оригинал
Both solutions are very simple, easy to use and, to an extent, solve the same issue. Which one should you choose then?
Scoped styles require literally no extra knowledge to use and feel comfortable with. Their limitations also make them simple to use, and they're capable of supporting small to mid-sized applications.
Однако, когда дело доходит до более сложных сценариев и больших приложений, мы, вероятно, хотим быть более явными и иметь больший контроль над тем, что происходит в нашем CSS.$style
объект несколько раз в шаблоне может выглядеть не так привлекательно, это небольшая цена за безопасность и гибкость, которые он обеспечивает.Мы также получаем легкий доступ к нашим переменным (таким как цвета или точки останова) в JS, без необходимости хранить отдельные файлы в синхронизировать
Which one do you use? And why? Feel free to share any additional scenarios you encountered along the way!
На самом деле оба решения очень просты и удобны в использовании и в некоторой степени решают одну и ту же проблему.Так что же выбрать?
Использование стилей с ограниченной областью действия не требует дополнительных знаний и дает ощущение комфорта. Его ограничения также являются причинами его простоты использования. Его можно использовать для поддержки приложений малого и среднего размера.
В более крупных приложениях или более сложных сценариях в настоящее время для использования CSS мы хотим, чтобы он был более явным и имел больший контроль. Хотя активно используется в шаблонах$style
Это не выглядит так «привлекательно», но более безопасно и гибко по небольшой цене. Еще одно преимущество заключается в том, что мы можем использовать JS для получения некоторых определяемых нами переменных (таких как значения цвета, точки останова стиля), поэтому нам не нужно вручную синхронизировать их между несколькими файлами.