Home

Documentation versions (currently viewingVaadin 24)
Documentation translations (currently viewingChinese)

Polymer支持已被弃用。请改用Lit templates

处理用户事件

如何通过Element API使用组件API和DOM事件。
Warning

自 Vaadin 18(于2020年11月发布)起,Polymer 支持已弃用,转而支持更快速、更简单的Lit templates。Polymer模板的内置支持已被移除,现在仅作为商业插件提供。不过,提供了一个免费的转换工具,来帮助用户将Polymer模板转换为Lit模板。

有关如何设置商业版Polymer模板插件的更多信息,请参阅升级指南

Lit模板不支持事件处理机制。但您仍然可以通过 Element API直接使用组件API和DOM事件实现类似的功能。

定义客户端事件处理程序

PolymerTemplate 提供了为元素绑定客户端事件处理程序的方法。

使用 on-eventname="methodName" 这种语法定义事件处理器。方法名称不应该带任何参数或括号。

以下示例在JavaScript Polymer模板[classname]`EventHandlerDemo`中定义了一个事件处理程序:

Source code
JavaScript
class EventHandlerDemo extends PolymerElement {
  static get template() {
    return html`<button on-click="handleClick">Say hello</button>`;
  }

  static get is() {
    return 'event-handler-demo'
  }

  handleClick() {
    console.log('Button was clicked.');
    window.alert('Hello');
  }
}

customElements.define(EventHandlerDemo.is, EventHandlerDemo);

此代码定义了一个`<button>`点击事件,在浏览器中显示提示框。

您可以使用 on-eventname 语法监听内置的浏览器事件以及自定义事件(例如Web Component中定义的)。您通常可以在组件的文档中找到可用的事件信息。

在服务器端处理事件

您可以使用 @EventHandler 注解来处理在Polymer模板中定义的DOM事件。

以下示例展示了一个JavaScript Polymer模板,其中定义了[methodname]`handleClick()`方法:

Source code
JavaScript
class EventHandler extends PolymerElement {
  static get template() {
    return html`<button on-click="handleClick">Click me</button>`;
  }

  static get is() {
    return 'event-handler';
  }
}

customElements.define(EventHandler.is, EventHandler);

此示例展示了如何使用`@EventHandler`注解引用此[methodname]`handleClick()`方法:

Source code
Java
@Tag("event-handler")
@JsModule("./com/example/event-handler.js")
public class EventHandlerPolymerTemplate extends PolymerTemplate<TemplateModel> {

    @EventHandler
    private void handleClick() {
        System.out.println("Received a handle click event");
    }
}

您在[methodname]handleClick()`方法上添加@EventHandler`注解后,Vaadin会自动将此处理程序与客户端事件绑定。

Note
如果同时添加了客户端和服务器端的事件监听器,客户端事件处理器会先于服务器端处理器被调用。

向服务器端事件添加事件数据

事件可以包括额外的信息,例如点击使用的鼠标按钮。当您使用`@EventHandler`注解时,您可以为每个方法参数定义一个`@EventData`注解。这个注解用于告诉Vaadin应该向服务器端发送何种数据。

任何存在于客户端事件对象中的可序列化数据都可以发送。具体可用的数据取决于具体的事件类型。

以下示例展示了如何在JavaScript Polymer模板中定义[methodname]`handleClick()`方法:

Source code
JavaScript
// 相同的模板,用于服务器端事件处理器
static get template() {
    return html`<button on-click="handleClick">Click me</button>`;
}

下面的示例演示如何在Java模板类中使用`@EventData`注解获取额外的数据:

Source code
Java
@Tag("event-handler")
@JsModule("./com/example/event-handler.js")
public class EventDataHandlerPolymerTemplate extends PolymerTemplate<TemplateModel> {

    @EventHandler
    private void handleClick(@EventData("event.altKey") boolean altPressed,
            @EventData("event.srcElement.tagName") String tag,
            @EventData("event.offsetX") int offsetX,
            @EventData("event.offsetY") int offsetY) {
        System.out.println("Event alt pressed: " + altPressed);
        System.out.println("Event tag: " + tag.toLowerCase(Locale.ENGLISH));
        System.out.println("Click position on element: [" + offsetX + ", "+ offsetY +"]");
    }
}

客户端解析事件数据并将额外信息发送到服务器,如 event.typeevent.srcElement.tagNameevent.offset[X/Y]

Note
如果`EventData`无法被转换成期望的格式,服务器可能抛出异常。例如 java.lang.ClassCastException: Cannot cast elemental.json.impl.JreJsonNumber to elemental.json.JsonObject。如果用于`EventData`的值无法执行或转换为JSON,客户端也可能抛出异常。

使用模板重复器获取模型特定事件数据

只要您使用bean定义模型类,即可使用http://polymer-library.polymer-project.org/3.0/docs/devguide/templates#dom-repeat>[<dom-repeat> 辅助元素] 以对象形式在事件处理程序中获得模型特定条目。有关详细信息,请参阅使用Beans与PolymerTemplate的模型

以下示例创建[classname]`ModelItemHandlerPolymerTemplate`模板和对应的模型类:

Source code
Java
@Tag("model-item-handler")
@JsModule("./com/example/model-item-handler.js")
public class ModelItemHandlerPolymerTemplate
            extends PolymerTemplate<MessagesModel> {

    public static class Message {
        private String text;

        public Message() {
        }

        public Message(String text) {
            this.text = text;
        }

        public String getText() {
            return text;
        }

        public void setText(String text) {
            this.text = text;
        }
    }

    public interface MessagesModel extends TemplateModel {
        void setMessages(List<Message> messages);
    }

    @EventHandler
    private void handleClick(@ModelItem Message message) {
        System.out.println("Received a message: " + message.getText());
    }
}

现在您可以使用[classname]`Message`参数类型在服务器端处理点击事件。

例如,使用JavaScript Polymer模板中的`<dom-repeat>`(模板重复器)如下所示:

Source code
JavaScript
class ModelItemHandler extends PolymerElement {
  static get template() {
    return html`
      <dom-repeat items="[[messages]]">
        <template>
          <div class='msg' on-click="handleClick">[[item.text]]</div>
        </template>
      </dom-repeat>
    `;
  }

  static get is() {
    return 'model-item-handler';
  }
}

customElements.define(ModelItemHandler.is, ModelItemHandler);

点击条目时,会调用服务器端的[methodname]`handleClick()`方法,所关联的数据通过`event.model.item`来识别。

Note
您可以在任意定义的数据路径上使用`@ModelItem`注解。默认数据路径为`event.model.item`。但是,您应该以某种方式声明数据类型,以便通过模型定义参考。

事件发生前修改模型条目

`@ModelItem`注解只是访问模型数据的便利工具。您在事件处理回调中接收的参数是您通过模型实例直接访问的模型数据。这意味着服务器并不会以任何形式更新该模型条目。因此,在客户端创建的有数据的自定义事件会被服务器完整忽略,而使用的是当前服务器端模型数据。您应通过正确更新其数据始终保持模型同步。

(因内容过长,已省略之后的段落……)