Данная библиотека является идеей, и носит демонстрационный характер.

События

Нативные события

В bakugan описание событий немного отличается от спецификации. Разница лишь в том, что в bakugan нужно указать только имя метода, который будет обрабатывать событие. В то время как в спецификации нужно написать вызов функции с параметрами

import { Component, Native, template } from "bakugan";

//
// как делается согласно спецификации:
// пишется функция и указывается список аргуметов
// <div onclick="handler(this, event, ...)">Hello World</div>
//
// как делается в bakugan:
// скобки не нужны, пишется только имя метода
// <div onClick="handler">Hello World</div>
//

@template({
    html: `
        <div onClick="handler">Hello World</div>
    `,
})
class App extends Component {
    public handler(component: App, event: MouseEvent, el: Native): void {
        console.log("clicked!");
    }
}

const app: App = new App();
app.bindTo(document.body);
смотреть пример: web | github

При вызове события в обработчик передается 3 параметра:
  • component: Component - компонент в котором произошло событие;
  • event: Event - нативное событие;
  • el: Native - компонент типа Native. Этот аргумент может быть равен null, если у элемента не задан ref.

import { Component, Native, template } from "bakugan";

@template({
    html: `
        <div>
            <div onClick="handler">text 1</div>
            <div ref="myDiv" onClick="handler">text 2</div>
        </div>
    `,
})
class App extends Component {
    public handler(component: App, event: MouseEvent, el: Native): void {
        console.log(this);
        console.log(component);
        console.log(event);
        console.log(el);
    }
}

const app: App = new App();
app.bindTo(document.body);
смотреть пример: web | github

При клике по первому div аргумент el будет равен null т.к. в разметке не задан ref, а при клике по второму div аргумент el уже будет известен.

В данном случае указатель this и аргумент component будут ссылаться на один и тот же компонент. Но если в экземпляре класса App задать context, то this и component будут отличаться.

import { Component, Native, template } from "bakugan";

@template({
    html: `
        <div>
            <div onClick="handler">text 1</div>
            <div ref="myDiv" onClick="handler">text 2</div>
        </div>
    `,
})
class App extends Component { }

const app: App = new App();
app.bindTo(document.body);

const context: Component = {
    handler(component: App, event: MouseEvent, el: Native) {
        console.log(this);
        console.log(component);
        console.log(event);
        console.log(el);
    },
} as any;

app.context(context);
смотреть пример: web | github

События у компонентов

Описание событий у компонентов класса Component такое же, как и у нативных компонентов. Чтобы bakugan мог понять является ли атрибут параметром или событием, имя события всегда должно начинаться с on.

Атрибут onMyEvent будет являться событием, т.к. начинается с on, а значением является имя метода handlerEvent, которое будет обрабатывать данное событие. Соответственно атрибут name является параметром.

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

import { Component, template } from "bakugan";

// component Hello

@template({
    html: `
        <div>
            Hello
            <txt ref="name"></txt>
        </div>
    `,
})
class Hello extends Component {
    public afterInit(component: Hello): void {
        this.get("name").html(` ${this.props.name}`);

        console.log(this.props);
        console.log(this.events);

        setTimeout(() => {
            this.emit("onMyEvent", this.props.name); // emit!
        }, 1000);
    }
}

// component App

@template({
    html: `
        <div>
            <b-hello onMyEvent="handlerEvent" name="props.ivan"></b-hello>
            <b-hello onMyEvent="handlerEvent" name="props.petya"></b-hello>
        </div>
    `,
    use: {
        "b-hello": Hello,
    },
})
class App extends Component {
    public handlerEvent(component: Hello, name: string): void {
        console.log(this);
        console.log(component);
        console.log(name);
    }
}

const app: App = new App({ ivan: `Ivan`, petya: `Petya` });
app.bindTo(document.body);
смотреть пример: web | github