当前位置: 首页 > 工具软件 > Stencil > 使用案例 >

Stencil笔记(3)- 装饰器

楚岳
2023-12-01

Stencil可以轻松构建丰富的交互式组件。

现在有以下几个装饰器:

1、Component装饰器:

每个组件都要用这个装饰器来装饰。
装饰器里最基本的要有一个tag元数据,当然,styleUrl也几乎是必须的。另外还有styleUrls,这个元数据可引用多个样式表。

import { Component } from '@stencil/core';
@Component({
  tag: 'todo-list',
  styleUrl: 'todo-list.scss'
})
export class TodoList {
  ...
}

此外还有可选的host元数据,它的作用是设置组件的属性或者class

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

@Component({
  tag: 'todo-list',
  styleUrl: 'todo-list.scss',
  host: {
    theme: 'todo',
    role: 'list'
  }
})

当使用组件时,它会自动添加class属性和role的值
<todo-list class='todo' role='list'></todo-list>
2、Prop Decorator(属性装饰器)

感觉和ng的@Input一样,用于自定义属性。
如:

import { Prop } from '@stencil/core';
...
export class TodoList {
  @Prop() color: string;
  @Prop() favoriteNumber: number;
  @Prop() isSelected: boolean;
  @Prop() myHttpService: MyHttpService;
}

在JSX中:

<todo-list color="blue" favoriteNumber="24" isSelected="true"></todo-list>

这些自定义属性值还可以通过js来获得:

const todoListElement = document.querySelector('todo-list');
console.log(todoListElement.myHttpService); // MyHttpService
console.log(todoListElement.color); // blue
prop值的可变性

要知道,@Prop默认情况下在组件逻辑内部不可变的。一旦设置了值,组件就不能在内部更新它。

但是,可以显示地设置@Prop从组件内部进行改变,方法是将其声明为可变的,如下例所示:

import { Prop } from '@stencil/core';
...
export class NameElement {
  @Prop({ mutable: true }) name: string = 'Stencil';

  componentDidLoad() {
    this.name = 'Stencil 0.7.0';
  }
}
Prop可以设置默认的值,以及开启验证

如下所示,name的值默认为Stencil。
要对其验证其输入,可使用@watch装饰器。

import { Prop, Watch } from '@stencil/core';
...
export class TodoList {
  @Prop() name: string = 'Stencil';

// 当值改变时,验证其是否为空,以及是否长度小于2
  @Watch('name')
  validateName(newValue: string, oldValue: string) {
    const isBlank = typeof newValue == null;
    const atLeast2chars = typeof newValue === 'string' && newValue.length >= 2;
    if (isBlank) { throw new Error('name: required') };
    if ( !atLeast2chars ) { throw new Error('name: atLeast2chars') };
  }
}

...

3、Watch 装饰器

当用户改变prop时,会触发watch的监听,并调用函数。像上面用到的那样。

4、管理组件状态的State装饰器

@State()装饰可用于为组件管理的内部数据。这意味着用户不能从组件外部修改属性。对@State()属性的任何更改都会导致再次调用组件reader函数。

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

...
export class TodoList {
  @State() completedTodos: Todo[];

  // 在这个方法里改变了State装饰的属性,那么将触发reader函数的调用
  completeTodo(todo: Todo) {
    // This will cause our render function to be called again
    this.completedTodos = [...this.completedTodos, todo];
  }

  render() {
    //
  }
}
5、方法装饰器

@Method()装饰用于定义组件的公共接口。用@Method()装饰器装饰的函数可以直接从元素中调用。

import { Method } from '@stencil/core';
...
export class TodoList {

  @Method()
  showPrompt() {
    // show a prompt
  }
}

获取到组件后便可调用其方法,很有用的样子。

const todoListElement = document.querySelector('todo-list');
todoListElement.showPrompt();
6、元素装饰器

这个不太懂,获取到HTMLElement实例?

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

...
export class TodoList {

  @Element() todoListEl: HTMLElement;

  addClass(){
    this.todoListEl.classList.add('active');
  }
}
嵌套组件

与ng或Ionic不同的是,嵌套组件时不用显示地导入子组件,因为子组件也是原生HTML标签。直接在父组件直接使用即可。

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

@Component({
  tag: 'my-parent-component'
})
export class MyParentComponent {

  render() {
    return (
      <div>
//  这是子组件,无需导入再使用
        <my-embedded-component color="red"></my-embedded-component>
      </div>
    );
  }
}
 类似资料: