`/deep/` 选择器无法在我的 VueJS 应用程序中使用 sass-loader

Posted

技术标签:

【中文标题】`/deep/` 选择器无法在我的 VueJS 应用程序中使用 sass-loader【英文标题】:The `/deep/` selector is not working using sass-loader in my VueJS application 【发布时间】:2021-07-25 03:17:43 【问题描述】:

在我的 Vue 2.6.10 webpack 应用程序中,我正在尝试添加 SASS,因为我们的团队希望将我们的遗留应用程序从 LESS 迁移到 SCSS。在我的package.json 中,我已将这些安装到我的devDependencies 中,每个docs:

sass (v.1.32.8) sass-loader (v10.1.1)

然后将node-sass (v5.0.0) 安装到我的dependencies

我的node 版本是:v15.4.0。根据这些docs,这是node-sass v5+ 的正确版本。

在我的 Vue 组件中,我尝试使用 /deep/::v-deep>>> 选择器。我拼凑了一个有效的playground,其中我有一个ParentComp.vue,使用/deep/ 定位ChildComp.vue 的内部样式,如下所示:

<style lang="scss" scoped>
  .parent-container 
    & /deep/ .child-comp 
      background-color: tomato;
      color: white;
    
  
</style>

耶!它在我的操场上使用我在那个操场上可以控制的相同版本的东西非常有效。

在我的应用程序中,当我尝试这个完全相同的设置时,我得到了这个编译错误:

./src/components/MenuBarComp.vue (./node_modules/css-loader/dist/cjs.js?
"sourceMap":true!./node_modules/vue-loader/lib/style-compiler?
"optionsId":"0","vue":true,"id":"data-v-4630c6ac","scoped":true,"sourceMap":true!
./node_modules/sass-loader/dist/cjs.js?
"additionalData":"/n          @import /"@/styles/_variables.scss/";/n        ","sourceMap":true!
./node_modules/vue-loader/lib/selector.js?type=styles&index=0!./src/components/MenuBarComp.vue)


Module build failed (from ./node_modules/sass-loader/dist/cjs.js):
SassError: expected selector.
   ╷
77 │   & /deep/ .child-test
   │     ^
   ╵
  src/components/MenuBarComp.vue 77:5  root stylesheet

根据我尝试过的许多其他suggestions,我应该尝试使用::v-deep&gt;&gt;&gt;。当我尝试使用这些选择器时,它编译得很好并且不再抛出异常,但没有任何反应。实际上没有 CSS 像 .parent[data-23423423] .child 那样呈现。但后来我看到 other articles 关于 SCSS 不支持此功能的原因。

然后我回去尝试找出可能导致此错误的原因,并且在几天的时间里我尝试了数十种方法来尝试解决此问题,例如:

downgrading node-sass / sass / sass-loader 版本到其他版本来尝试让事情正常工作 npm rebuild node-sass --force rimrafing node_modules 清除整个 npm cache 和许多其他内容

我的package.json 中已经有几个预先存在的 CSS 相关包:

css-loader (v.3.1.0) 更少 (v3.0.4) less-loader (v4.1.0) mini-css-extract-plugin (v0.6.0) optimize-css-assets-webpack-plugin (v5.0.3) postcss-import (v11.0.0) postcss-loader (v2.0.8) postcss-url (v7.2.1) vue-style-loader (v3.0.1)

最后是我的加载器在 webpack 中的设置方式:

  function generateLoaders(loader, loaderOptions) 
    const loaders = options.usePostCSS
      ? [cssLoader, postcssLoader]
      : [cssLoader];

    if (loader) 
      loaders.push(
        loader: loader + '-loader',
        options: Object.assign(, loaderOptions, 
          sourceMap: options.sourceMap,
        ),
      );
    

    // Extract CSS when that option is specified
    // (which is the case during production build)
    if (options.extract) 
      return [MiniCssExtractPlugin.loader].concat(loaders);
     else 
      return ['vue-style-loader'].concat(loaders);
    
  

  // https://vue-loader.vuejs.org/en/configurations/extract-css.html
  return 
    css: generateLoaders(),
    postcss: generateLoaders(),
    less: generateLoaders('less'),
    sass: generateLoaders('sass'),
    scss: generateLoaders('sass', 
      additionalData: `
          @import "@/styles/_variables.scss";
        `,
    ),
    stylus: generateLoaders('stylus'),
    styl: generateLoaders('stylus'),
  ;
;

如何让/deep/ 选择器工作?

【问题讨论】:

【参考方案1】:

这是因为sass 不支持/deep/。您需要像这样显式设置您的 sass-loader 以使用 node-sass

loader: 'sass-loader', options:  implementation: require('node-sass')

sass-loader 在their page 上有一条说明:

注意node-sass和sass安装时的情况! 由 默认 sass-loader 更喜欢 sass。 为了避免这种情况 您可以使用实现选项。

实现选项要么接受 sass (Dart Sass) 要么 node-sass 作为一个模块。

所以你的具体代码最终会像sass-loader 使用的那样:

scss: generateLoaders('sass', 
  implementation: require('node-sass'),
  additionalData: `
      @import "@/styles/_variables.scss";
    `,
),

【讨论】:

好吧。 Vuetify 使用 /deep/,建议使用 sass 代替 node-sass... 依赖地狱

以上是关于`/deep/` 选择器无法在我的 VueJS 应用程序中使用 sass-loader的主要内容,如果未能解决你的问题,请参考以下文章

如何样式化 ng-bootstrap - 替代 /deep/

深度选择器

scss文件中使用深度选择器/deep/报错 Expected selector

vuejs在选择后获取日期选择器的值

尝试在我的应用程序中打开苹果地图应用程序时发送到实例的无法识别的选择器

/deep/ 和 ::shadow 在 CSS 选择器中是啥意思?