Getting started with StencilJS

综合技术 2017-12-07

A few weeks ago in Polymer Summit 2017, Max Lynch and Adam Bradley introduced a new compiler which creates native Web Components. The compiler is called Stencil and it combines a lot of aspects from known libraries and frameworks such as React and Angular. In this article, we will familiarize ourselves with the basics of Stencil.

Stencil borrows a lot of concepts from existing frameworks. Some of these concepts include:

– Virtual DOM

– Reactive data-binding

– TypeScript


Experience with Angular and React is not necessary but could really go a long way when creating our Stencil Project.

This article also shows, with examples, how these concepts are applied in a Stencil component.

Creating a Stencil Project

Making sure that we already have npm installed, we execute the following in our command line:

# Clone the Github reo
    git clone my-first-stencil-project 

    # Move into the repo
    cd my-first-stencil-project

    # Remove original remote URL
    git remote rm origin

    # Install npm dependencies
    npm install

And we are good to go. Our project should look like this:

Creating a Stencil Component

Stencil components are built using JSX and TypeScript. Therefore, familiarity with these two technologies will be very important before going further. To create our first Stencil component, we add a new file with a .tsx
extension. For example, create a collapsible-panel
folder in the src/components
directory then add collapsible-panel.tsx
in the folder. Insert the following code:

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

      tag: 'collapsible-panel',
      styleUrl: 'collapsible-panel.scss'
    export class CollapsiblePanel {
      @Prop() title: string;
      @State() collapsed: boolean;

      toggle() {
          this.collapsed = !this.collapsed;

      render() {
        return (
); } }

Let’s walk through the bit of code we just wrote:

  • First of all, the file’s extension is .tsx
    which means that the code is written in TypeScript and JSX.
  • In order to create a Stencil component we use the Component
    decorator which configures the class with the selector in the DOM and with the scoped style. Decorators are basically functions that extend what is being decorated. Therefore, in this case, the Component
    decorator extends and adds more functionality to the CollapsiblePanel
    class. We will visit some of the existing decorators later in this article.

  • Then we create a class for the component and export it. In our class, we are using two other Stencil decorators — ** Prop
    and State
    . Prop
    indicates a property that the component will get as a component attribute while State
    is an inner state of the component.

  • The component gets to work in the render
    function because that is where we tell our compiler how to render the component. Similarities with other frameworks can be noticed here — such as the use of curly brackets for binding the onClick
    and hidden
    events (like JSX in React) and the slot
    element which is used to indicate that the content will be provided by the component’s user (like transclusion in Angular).

To style our component, we create a file collapsible-panel.scss
, add our style to it and insert it in our src/components/collapsible-panel

collapsible-panel {
      display: block;
      border: black dashed 1px;

    #header {
      background: red;
      color: white;
      cursor: pointer;
      padding: 2px;

We then update **our ** index.html
file with our collapsible-panel


  • Hi! I'm Stencil
  • I work with Web Components

Lastly we register our component in the stencil.config.js

exports.config = {
      bundles: [
        { components: ['collapsible-panel'] }

    exports.devServer = {
      root: 'www',
      watchGlob: '**/**'

If we run the app using the npm start
command, we should see the following web page with a collapsible bar:


Stencil is useful when it comes to building interactive components. There are a number of decorators such as Component
, Props
, State
and Event
that help achieve this. Let’s take a look at how these decorators are used.

Component Decorator

Our component must be decorated with an @Component()
decorator from the @stencil/core
package. A HTML tag
name and a styleUrl
which contains our style sheet are provided for the component. If multiple stylesheets are wanted then they can be referenced by styleUrls
instead . For our stylesheet, we use Sass. Create a file with the .``scss

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

      tag: 'shopping-list',
      styleUrl: 'shopping-list.scss'
    export class ShoppingList {

Prop Decorator

Props are custom properties that we can provide values for. These are used to pass down data from parent components to any child component. The @Prop()
decorator is used by a component to declare the Props it expects to receive. Props can be in different forms: they can be a number
, a string
, a boolean
, an Object
or an Array
. When a member decorated with the @Prop()
decorator is set, the component re-renders by default.

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

Component State

We now need to track the state of our component’s internal data. To do this we use the @State()
decorator. The @State()
decorator manages our component’s internal data. This implies that a user cannot modify the property from outside the component, but the component can modify it however it sees fit. Any changes to an @State()
property will cause the components render function to be called again.

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

    export class ShoppingList {
      @State() completedShoppings: Shopping[];

      completeShopping(shopping: Shopping) {
        // This will cause our render function to be called again
        this.completedShoppings = this.completedShoppings.filter(item => item.bought == true);

      render() {

Event Decorator

At some point in our app, our components will start emitting data and events. To achieve this, we use the Event Emitter decorator written as @Event()

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

    export class ShoppingList {

      @Event() shoppingCompleted: EventEmitter;

      shoppingCompletedHandler(shopping: Shopping) {

The code above will dispatch a custom DOM event called shoppingCompleted

To handle events dispatched from @Events
, we use the @``Listen()
decorator in the listening component. In the example below, let’s assume that a child component, ShoppingList
, emits a shoppingCompleted
event using the EventEmitter

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

    export class ShoppingBag {

      shoppingCompletedHandler(event: CustomEvent) {
        console.log('Received the custom shoppingCompleted event: ', event.detail);

Handlers can also be registered for an event on a specific element. This is good for listening to

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

    export class ShoppingList {

      handleClick(ev) {
        console.log('the button was clicked', ev);


It’s really exciting to see where the web is headed. The ability to create web components which can be shared with any framework and library is going to improve how we build for the web. For a deeper understanding of how Stencil works, especially with advanced concepts such as server side rendering and service workers, you can check out the Stencil Documentation here.

The post Getting started with StencilJS appeared first on Pusher Blog.


责编内容by:JSFeeds (源链)。感谢您的支持!


Beyond fad frameworks: which programming skills ar... Which programming skills should spend your limited time and energy on, which engineering skills are ...
Using Luxon for Date and Time in JavaScript Working with date and time can be a confusing task for developers beginning with JavaScript. In this...
How well do you know your Angular trivia? © Shutterstock / Frazao We’re celebrating the release of Angular 5 with a return to our ...
reactive forms or data driven approach in Angular Hello Readers, In this tutorial, I am talking about two approaches that angular offer. Template...
angularjs呼叫Web API 今早有分享一篇《创建Web API并使用》 接下来,我再分享一篇,怎样在angularjs去呼叫Web API...