基于 Laravel + Vue 构建 API 驱动的前后端分离应用系列(十一) —— 通过 Laravel Mix 将 SASS 编译到 Vue 组件

为单页面应用配置 JavaScript 和 Sass 这篇教程中,我们已经为所有 Sass 资源构建了目录结构,我们可以将 Vue 组件的 Sass 资源放到这些目录中。

第一步:创建变量文件

由于我们使用 Foundation 组件来实现快速格栅功能,包含应用所有 Sass 变量的 _variables.scss 将成为最重要的文件,我们将这个文件放到 resources/assets/sass/abstracts 目录下,并添加一些默认的颜色:

$white: #FFFFFF;
$black: #111111;

$primary-color: #7F6D50;
$secondary-color: #FFBE54;
$highlight-color: #FFDBA0;
$dark-color: #7F5F2A;
$dull-color: #CCAF80;

现在我们拥有了一些可以在组件中使用的颜色了!如果你想要使用为非设计师提供的很酷的颜色工具,可以考虑 Adobe Color CC,当然类似的工具还有很多。

第二步:添加变量文件到 app.scss

我们需要将新创建的变量文件导入 resources/assets/sass/app.scss 文件以便在构建应用时将其编译到 CSS 里面,我们可以在 app.scss 文件中添加如下这行代码来完成导入:

@import 'abstracts/variables';

此时,app.scss 文件完整内容如下:

@charset "UTF-8";

/* ==========================================================================
    Builds our style structure
        https://sass-guidelin.es/#the-7-1-pattern
   ========================================================================== */
/**
 * Table of Contents:
 *
 *  1. Abstracts
 */
@import 'abstracts/variables';

@import 'node_modules/foundation-sites/assets/foundation.scss';

第三步:为 webpack.mix.js 添加别名

现在我们需要将 Laravel Mix、Sass 和 Vue 组件关联起来以便可以使用,大体上要做的就是定义一个包含指向 Sass 目录路径的别名或变量,这样就可以在 Vue 组件中引入对应的 Sass 资源。绝对多数时候,我们要做的就是引入变量文件,因为所有其他样式都定义在 Vue 组件自身里面。要添加别名,在 webpack.mix.js 的 webpackConfig 对象中添加代码如下:

mix.js('resources/assets/js/app.js', 'public/js')
    .webpackConfig({
        module: {
            rules: [
                {
                    test: /\.jsx?$/,
                    exclude: /node_modules(?!\/foundation-sites)|bower_components/,
                    use: [
                        {
                            loader: 'babel-loader',
                            options: Config.babel()
                        }
                    ]
                }
            ]
        },
        resolve: {
            alias: {
                '@': path.resolve('resources/assets/sass')
            }
        }
    })
    .sass('resources/assets/sass/app.scss', 'public/css');

当我们构建应用时,会将 @ 解析为 resources/assets/sass 路径别名。module 部分配置用于构建 Foundation。

第四步:添加 Navigation.vue 组件

做好以上配置之后,接下来是时候添加第一个 Vue 组件到 Roast 应用了。

首先创建 resources/assets/js/components/global/Navigation.vue 文件(同时创建 global 目录),在 Navigation.vue 文件中,添加如下代码:

<style>

</style>
<template>
    <nav class="top-navigation">

    </nav>
</template>
<script>
    export default {

    }
</script>

然后将告诉 Vue 我们要在 <style> 中使用 SCSS 而不是 CSS,只需在 <style> 标签中添加 lang="scss" 属性即可。

接下来,需要导入 SCSS 变量,由于我们之前已经定义过将 @ 解析为 SCSS 资源根目录,所以可以在 <style> 标签里面添加如下导入代码:

@import '~@/abstracts/_variables.scss';

这样,就可以将 SCSS 变量导入到 Navigation 组件了。现在 Navigation.vue 组件代码如下:

<style lang="scss">
    @import '~@/abstracts/_variables.scss';
</style>
<template>
    <nav class="top-navigation">

    </nav>
</template>
<script>
    export default {

    }
</script>

这个组件会用作应用的导航条,注意到我们还使用了 <nav> 标签,以遵循 HTML 5 语义。

下面我们继续填充 Navigation.vue 组件的样式代码和页面元素,使其具备完整的功能:

<style lang="scss">
    @import '~@/abstracts/_variables.scss';

    nav.top-navigation{
        background-color: $white;
        height: 50px;
        border-bottom: 2px solid $dark-color;

        span.logo{
            border-right: 1px solid $dark-color;
            display: block;
            float: left;
            height: 50px;
            line-height: 50px;
            padding: 0px 20px 0px 20px;
            font-family: 'Josefin Sans', sans-serif;
            font-weight: bold;
            color: $dark-color;

            &:hover{
                color: white;
                background-color: $dark-color;
            }
        }

        ul.links{
            display: block;
            float: left;

            li{
                display: inline-block;
                list-style-type: none;
                line-height: 50px;

                a{
                    font-family: 'Lato', sans-serif;
                    font-weight: bold;
                    color: $black;

                    &:hover{
                        color: $dark-color;
                    }
                }
            }
        }

        div.right{
            float: right;

            img.avatar{
                width: 40px;
                height: 40px;
                border-radius: 40px;
                margin-top: 5px;
                margin-right: 10px;
            }
        }

    }
</style>

<template>
    <nav class="top-navigation">

        <router-link :to="{ name: 'home'}">
            <span class="logo">Roast</span>
        </router-link>

        <ul class="links">
            <li>
                <router-link :to="{ name: 'cafes' }">
                    Cafes
                </router-link>
            </li>
        </ul>

        <div class="right">
            <img class="avatar" :src="user.avatar" v-show="userLoadStatus == 2"/>
        </div>

    </nav>
</template>

<script>
    export default {
        // 定义组件的计算属性
        computed: {
            // 从 Vuex 中获取用户加载状态
            userLoadStatus(){
                return this.$store.getters.getUserLoadStatus;
            },

            // 从 Vuex 中获取用户信息
            user(){
                return this.$store.getters.getUser;
            }
        }
    }
</script>

你可以在这个文件中看到 <router-link> 标签和一些 Vuex 计算属性,我们将在下一篇教程讨论这些东西。

至此我们已经在应用中添加了第一个 Vue 组件,该组件可以通过 Laravel Mix 将 Sass 资源编译进来。

项目源码位于 Github 上:nonfu/roastapp

学院君 has written 1083 articles

Laravel学院院长,终身学习者

积分:137452 等级:P12 职业:手艺人 城市:杭州

18 条回复

  1. Julian Julian says:
    @ Julian

    不好意思,我试了下,webpack配置没问题。我在layout.vue中引用的时候phpstorm将这句 @import "~@/abstracts/_variable.scss";报红,我以为报错了,不能引用,其实直接用就可以了

  2. Julian Julian says:

    在webpack.mix.js配置了别名,但是在Layout.vue组件中引入不了_varibles.scss文件

  3. 学院君 学院君 says:
    @ ManInMatrix

    弊端自然就是系统变复杂了 排查问题也更加困难 部署构建成本提升 但是就跟分布式一样 是应用逐渐变大之后的必由之路 绕不过去

登录后才能进行评论,立即登录?