8

我正在使用 stenciljs 构建一个 Web 组件,我希望能够基于名为主题的属性加载 css 主题文件。

@Component({
  tag: 'pm-header',
  styleUrl: 'pm-header.scss',
  shadow: true
})

export class PmHeader {

  @Prop() theme: string = 'default';

  ...

  render() {
    return (<nav class={this.theme}></nav>)
  }
}
4

3 回答 3

18

我知道这已经晚了,但这应该希望能对其他人有所帮助,因为它没有记录在案,我只是花了很多时间来弄清楚。以下代码允许您的自定义组件使用“模式”属性来确定加载哪种样式。

第 1 步:在组件定义中定义多个 styleUrls(又名“模式”)。我使用的是“dark”和“default”——但您可以根据需要定义任意数量。例如,ionic 使用“ios”和“md”。

@Component({
    tag: 'my-component',
    styleUrls: {
        default: 'my-component.default.pcss',
        dark: 'my-component.dark.pcss',
    },
})
export class MyComponent { ... }

第 2 步:创建样式文件(通常使用共享的通用样式):

  • 我的组件.common.css

      :host { display: block }
    
  • 我的组件.default.css

      @import './my-component.common.css';
      :host { color: black }
    
  • 我的组件.dark.css

      @import './my-component.common.css';
      :host { background: black; color: white }
    

第 3 步:更新您的 stencil.config.ts 以使用 globalScript:

export const config: Config = {
    namespace: 'mycomponent',
    globalScript: './src/globals/global.ts',
    ...
}

第 4 步:创建全局脚本并定义一个“setMode”函数,如下所示:

import { setMode } from '@stencil/core';

setMode(elm => {
    // NOTE: you can write whatever you want here - it's up to you. This
    // function must return one of the style "modes" defined in step 1.
    return (elm as any).mode || elm.getAttribute('mode') || 'default';
});

第 5 步:使用您的自定义组件,如下所示:

<!-- default mode -->
<my-component />
<my-component mode="default" />

<!-- dark mode -->
<my-component mode="dark" />

您可以自定义setMode用于确定模式的函数 - 例如,您可以在 上查找属性window,或检查元素上的 className。由你决定。以上只是一个简单的示例,它允许您在元素上使用“模式”属性......如果未指定任何内容,则返回“默认”。

于 2019-06-10T17:16:41.220 回答
3

请看下面的例子。即使阴影设置为true,它也会起作用

@Component({
  tag: 'my-component',
  styleUrls: [
    'my-component.scss'
  ],
  shadow: true
})

export class MyComponent{

  @State() theme: string // when theme changes render needs to be called again

  render () {
      return (
        <div>

          { 
            this.theme &&
            <link rel="stylesheet" href={`path_to_css/${this.theme}.css`} />
          }

          <p>{this.text}</p>
        </div>
      )
    }
}
于 2019-03-06T10:02:03.940 回答
1

在这种情况下,您的组件将始终加载在pm-header.scss.

要根据主题自定义样式,我认为您有两种选择:

1 - 将所有主题放入pm-header.scss其中并使用 Sass 保护每个主题:

nav.foo {
  // foo theme goes in here
}

nav.bar {
  // bar theme goes in here
}

2 - Stencil 确实提供了一个styleUrls道具,表面上可以让您在加载时在多个 Sass 文件之间进行选择。这是 Ionic 4 采用的方法(在 ios 和材料设计之间;这里有一个例子),但我不相信它在如何实现它方面有很好的记录。您可能必须深入研究 Ionic 代码才能走这条路。

于 2018-09-26T22:47:56.273 回答