Синтаксис и особенности

Stencil является инструментом для создания веб-компонентов, который позволяет разрабатывать на базе современных стандартов JavaScript. Он предлагает мощные возможности для работы с компонентами и шаблонами, обеспечивая поддержку различных браузеров с использованием нативного Web Components API.

Декларация компонента

В Stencil компонент создается как класс, который использует декоратор @Component. Этот декоратор определяет основной функционал компонента и его настройки. Например:

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

@Component({
  tag: 'my-component',
  styleUrl: 'my-component.css',
  shadow: true
})
export class MyComponent {
  render() {
    return <div>Hello, Stencil!</div>;
  }
}

Здесь:

  • tag — это имя тега, которое будет использоваться в HTML.
  • styleUrl — путь к файлу с CSS-стилями компонента.
  • shadow — если установлено в true, то компонент будет использовать Shadow DOM.

Визуальное представление с помощью JSX

Stencil использует JSX для описания разметки компонента. JSX — это расширение синтаксиса JavaScript, которое позволяет писать HTML-подобный код внутри JavaScript. Вместо обычных строковых шаблонов используются теги, которые компилируются в вызовы JavaScript функций. В Stencil это работает через функцию h:

render() {
  return (
    <div>
      <h1>Welcome to Stencil!</h1>
    </div>
  );
}

Функция h эквивалентна React.createElement, но с добавлением типизации для удобства работы в Stencil.

Пропсы и состояние компонента

С помощью Stencil можно создавать свойства (props) и состояние (state), которые управляют поведением и данными компонента.

  • Props передаются извне и могут быть использованы внутри компонента.
  • State используется для управления внутренним состоянием компонента.

Пример:

import { Component, Prop, State, h } from '@stencil/core';

@Component({
  tag: 'my-counter',
  styleUrl: 'my-counter.css',
  shadow: true
})
export class MyCounter {
  @Prop() start: number = 0;
  @State() count: number = this.start;

  increment() {
    this.count++;
  }

  render() {
    return (
      <div>
        <h1>{this.count}</h1>
        <button onCl ick={() => this.increment()}>Increment</button>
      </div>
    );
  }
}

Здесь:

  • @Prop() используется для свойства, которое может быть передано извне.
  • @State() используется для отслеживания внутреннего состояния компонента.

Обработчики событий

Для работы с событиями Stencil предоставляет синтаксис, который позволяет легко подписываться на события и вызывать методы компонента при их возникновении. В примере выше, событие клика на кнопке вызывает метод increment, который изменяет состояние компонента.

Также Stencil поддерживает кастомные события:

import { Component, Event, EventEmitter, h } from '@stencil/core';

@Component({
  tag: 'my-button',
  styleUrl: 'my-button.css',
  shadow: true
})
export class MyButton {
  @Event() clicked: EventEmitter;

  handleClick() {
    this.clicked.emit('Button was clicked!');
  }

  render() {
    return (
      <button onCl ick={() => this.handleClick()}>
        Click Me
      </button>
    );
  }
}

@Event() используется для создания события, которое может быть прослушано родительским компонентом. Вызов this.clicked.emit() инициирует это событие.

Стилизация компонентов

Stencil поддерживает стили, локализованные для каждого компонента, используя Shadow DOM, что гарантирует, что стили не повлияют на другие части страницы. Чтобы применить стили, достаточно указать путь к файлу стилей через styleUrl:

@Component({
  tag: 'my-component',
  styleUrl: 'my-component.css',
  shadow: true
})
export class MyComponent {}

Stencil также поддерживает использование стилизации через CSS-переменные, что позволяет улучшить кастомизацию и гибкость компонентов.

Жизненный цикл компонента

Каждый компонент в Stencil имеет несколько методов жизненного цикла, которые позволяют управлять поведением компонента на различных стадиях его существования. Среди них:

  • componentWillLoad() — вызывается перед рендером компонента, можно использовать для инициализации данных.
  • componentDidLoad() — вызывается после того, как компонент был добавлен в DOM и отрендерен.
  • componentWillUpdate() — вызывается перед тем, как компонент будет обновлен.
  • componentDidUpdate() — вызывается после обновления компонента.
  • componentDidUnload() — вызывается при удалении компонента из DOM.

Пример использования:

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

@Component({
  tag: 'my-component',
  styleUrl: 'my-component.css',
  shadow: true
})
export class MyComponent {
  componentWillLoad() {
    console.log('Component will load!');
  }

  render() {
    return <div>Component Loaded</div>;
  }
}

Методы жизненного цикла помогают контролировать поведение компонента и обеспечивать эффективную работу приложения.

Особенности синтаксиса

Декораторы и метаданные

Stencil активно использует декораторы, что позволяет не только описывать компоненты, но и автоматически генерировать метаданные для различных целей, таких как автоматическая генерация документации и поддержка TypeScript. Примеры:

  • @Component() — описывает сам компонент.
  • @Prop() — для определения входных свойств.
  • @State() — для внутренних состояний.
  • @Event() — для создания и обработки событий.

Типизация и TypeScript

Stencil полностью интегрирован с TypeScript, что дает разработчикам преимущества строгой типизации. Типы для пропсов, состояний и событий указываются с помощью TypeScript-аннотаций.

Пример с типами:

import { Component, Prop, State, h } from '@stencil/core';

@Component({
  tag: 'user-profile',
  styleUrl: 'user-profile.css',
  shadow: true
})
export class UserProfile {
  @Prop() name: string;
  @State() age: number;

  render() {
    return (
      <div>
        <h1>{this.name}</h1>
        <p>Age: {this.age}</p>
      </div>
    );
  }
}

Типизация через TypeScript позволяет избежать ошибок на этапе разработки и повышает надежность кода.

Ленивая загрузка компонентов

Stencil поддерживает ленивая загрузка компонентов, что помогает ускорить рендеринг страниц и экономит ресурсы, загружая компоненты только по мере необходимости. Для этого используется динамическая загрузка через import().

Пример использования:

const MyComponent = () => import('./my-component');

Это позволяет уменьшить первоначальный объем загружаемого кода и повысить производительность.

Переиспользуемость компонентов

Stencil компоненты можно использовать не только внутри Stencil-проектов, но и в любых других веб-приложениях, включая те, которые используют такие фреймворки, как React, Angular или Vue. Для этого Stencil компоненты компилируются в стандартные веб-компоненты, которые совместимы с любым фреймворком, поддерживающим нативные элементы HTML.

<my-component></my-component>

Заключение

Синтаксис Stencil представляет собой мощный инструмент для создания современных веб-компонентов, обеспечивая поддержку всех ключевых возможностей, включая работу с компонентами, состояние, события, стилизацию и жизненный цикл. Благодаря интеграции с TypeScript и поддержке современных стандартов веб-разработки, Stencil является отличным выбором для разработки масштабируемых и эффективных веб-приложений.