样式组件

在使用 Vue 组件时,webpack 编译器允许您使用几乎任何您喜欢的前端模板语言风格。例如,有几种方法可以直接或通过预处理来编译 CSS。在 Vue 模板中启用这些表达式语言的最简单方法,就是在使用 Vue CLI 提前设置项目时安装它们。

在 Vue 组件中使用样式(style)标签时,只要安装了相应的 webpack 加载器,就可以选择指定语言。在 Exercise 1.01 中,如果选择安装 SCSS 预处理器,就可以在样式标签中添加 lang="scss" 属性,开始使用 SCSS。

例如,如果您选择安装 Stylus 预处理器,则可以在样式标记中添加 lang="stylus" 属性,开始使用 Stylus:

<style lang="stylus">
ul
    color: #2c3e50;
    > h2
    color: #22cc33;
</style>

Vue 范围(scoping)是一种方便的方法,可以阻止单个组件从虚拟 DOM 头继承样式。将 scoped 属性添加到样式(style)标签中,然后编写一些特定于组件的样式,这些样式将覆盖全局表中的任何其它 CSS 规则。一般规则是不对全局样式设范围。定义全局样式的常用方法是将这些样式分离到另一个样式表中,然后导入到您的 App.vue 中。

练习 1.03:将 SCSS 导入到作用域组件中

在本练习中,我们将利用样式(style)标签将 SCSS 预处理样式添加到组件并导入外部样式表。

要访问本练习的代码文件,请参阅 https://packt.live/3nBBZyl

  1. 打开命令行终端并导航到 Exercise1.03 文件夹并按顺序运行以下命令:

    > cd Exercise1.03/
    > code .
    > yarn
    > yarn serve
  2. 在练习文件中,我们编写一些可以使用 SCSS 设置样式的 HTML。我们继续练习一下插值方法:

    // src/components/Exercise1-03.vue
    <template>
      <div>
        <h1>{{ title }}</h1>
        <h2>{{ subtitle }}</h2>
        <ul>
          <li>{{ items[0] }}</li>
          <li>{{ items[1] }}</li>
          <li>{{ items[2] }}</li>
        </ul>
      </div>
    </template>
    
    <script>
    export default {
      data() {
        return {
          title: 'My list component!',
          subtitle: 'Vue JS basics',
          items: ['Item 1', 'Item 2', 'Item 3']
        }
      },
    }
    </script>
  3. lang 属性添加到样式(style)标记并添加值 scss 以在样式块内启用 SCSS 语法:

    <style lang="scss"></style>
  4. src/ 目录中创建一个名为 styles 的文件夹。在这个新文件夹中创建一个名为 typography.scss 的文件:

    src/styles/typography.scss
  5. 在 typography.scss 中,为您在组件中编写的模板添加一些样式:

    /* typography.scss */
    $color-green: #4fc08d;
    $color-grey: #2c3e50;
    $color-blue: #003366;
    h1 {
        margin-top: 60px;
        text-align: center;
        color: $color-grey;
        + h2 {
            text-align: center;
            color: $color-green;
        }
    }
    ul {
        display: block;
        margin: 0 auto;
        max-width: 400px;
        padding: 30px;
        border: 1px solid rgba(0,0,0,0.25);
        > li {
            color: $color-grey;
            margin-bottom: 4px;
        }
    }

    在 SCSS 中,您可以使用标准 CSS 选择器来选择组件中的元素。

    ul > li 将选择 <ul> 元素内的每个 <li> 元素进行样式设置。类似地,使用加法符号 + 意味着放置在第一个元素之后的元素如果符合条件则将被设置样式。例如,h1 + h2 将指示 H1 之后的所有 H2 元素都将以某种方式设置样式,但 H3 不会。通过下面的例子你可以更好地理解这一点。

    在 CSS 中,您将按如下方式呈现此代码:

    h1 + h2 {
      /* Add styling */
    }
    ul > li {
      /* Add styling */
    }

    在 SCSS 中,相同的代码可以表示如下:

    h1 {
        + h2 {
          // Add styling
        }
    }
    ul {
        > li {
          // Add styling
        }
    }
  6. 在您的组件中,使用 SCSS @import 方法导入这些样式:

    <style lang="scss">
    @import '../styles/typography';
    </style>

    这将生成如下输出:

    image 2023 10 10 22 22 40 920
    Figure 1. Figure 1.10: When you save and reload, your project should have the style imported
  7. scoped 属性添加到 <style> 标记中,以仅将这些样式应用于此组件实例。使用导入样式表 $color-blue 中的变量:

    <style lang="scss" scoped>
    @import '../styles/typography';
    h1 {
        font-size: 50px;
        color: $color-blue; // Use variables from imported stylesheets
    }
    </style>

    上述代码的输出如下:

    image 2023 10 10 22 26 21 170
    Figure 2. Figure 1.11: The outcome of scoping styles

    检查文档的 DOM,您会注意到在运行时,作用域已将 v-data-* 属性应用于指定这些特定规则的 DOM 元素。我们的 typography.scss(我们将其范围限定为组件)引用了不在组件范围内的 HTML 标记。当 Vue 将数据属性添加到作用域组件时,如果组件中存在 <body> 标签,它会生成样式。在我们的例子中,事实并非如此。

    展开 <head><style> 标签后,浏览器开发工具的 Elements 选项卡将显示以下内容:

    image 2023 10 10 22 29 47 197
    Figure 3. Figure 1.12: Observe how the virtual DOM uses data attributes to assign scoped styles
  8. styles 文件夹中创建一个名为 global.scss 的新样式表:

    /* /src/styles/global.scss */
    body {
        font-family: 'Avenir', Helvetica, Arial, sans-serif;
        margin: 0;
    }
  9. 将此样式表导入到您的 App.vue 中:

    <style lang="scss">
    @import './styles/global';
    </style>

    我们的应用程序现在应该恢复正常,该组件混合了全局定义的样式和适当范围的样式,如下所示:

    image 2023 10 10 22 32 29 899
    Figure 4. Figure 1.13: Properly scoped styles for Exercise 1.03

    在本练习中,我们插入了源自数组的数据,然后使用范围 SCSS 的形式设置组件的样式,这些形式既可以存在于 <style> 标记内,也可以从项目中的另一个目录导入。