> For the complete documentation index, see [llms.txt](https://developers-apps-in-toss.toss.im/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developers-apps-in-toss.toss.im/documentation/api-and-sdk-zh/common/screen/event.md).

# 控制事件

本文档将介绍如何检测和控制应用运行过程中发生的主要事件。典型地 **返回按钮事件**和 **应用进入完成事件**可以处理。

### 1. 检测返回按钮事件

控制返回按钮事件可以防止用户误关闭页面。例如，在支付中或填写表单时，可以阻止按下返回键后关闭界面。

**主要功能**

| 功能                                                    | 说明                   |
| ----------------------------------------------------- | -------------------- |
| `backEvent`                                           | 这是在按下返回按钮时发生的事件。     |
| `graniteEvent.addEventListener('backEvent', { ... })` | 订阅事件。                |
| `onEvent`                                             | 在按下返回按钮时调用。默认返回会被阻止。 |
| `onError`                                             | 在处理事件时发生错误时调用。       |
| `unsubscription()`                                    | 可以取消已注册的事件监听器。       |

在 React Native 中， `useBackEvent()` 可以通过 Hook 实现相同的逻辑。

**示例**

下面的示例是在用户按下返回键时弹出确认框，并在点击“确认”后允许跳转的示例。

{% tabs %}
{% tab title="js" %}

```js
import { graniteEvent } from '@apps-in-toss/web-framework';

const unsubscription = graniteEvent.addEventListener('backEvent', {
  onEvent: () => {
    const shouldLeave = window.confirm('正在编写的内容不会保存。要离开吗？');
    if (shouldLeave) {
      // 编写离开的代码。
    }
  },
  onError: (error) => {
    console.error(`发生了错误：${error}`);
  },
});

window.addEventListener('pagehide', () => {
  unsubscription();
});
```

{% endtab %}

{% tab title="React" %}

```tsx
import { graniteEvent } from '@apps-in-toss/web-framework';
import { useEffect, useState } from 'react';

function ConfirmBackNavigation() {
  const [formValue, setFormValue] = useState('');

  useEffect(() => {
    const unsubscription = graniteEvent.addEventListener('backEvent', {
      onEvent: () => {
        const shouldLeave = window.confirm('正在编写的内容不会保存。要离开吗？');
        if (shouldLeave) {
          // 编写离开的代码。
        }
      },
      onError: (error) => {
        alert(`发生了错误：${error}`);
      },
    });

    return unsubscription;
  }, []);

  return (
    <div>
      <h2>输入表单</h2>
      <textarea
        value={formValue}
        onChange={(e) => setFormValue(e.target.value)}
        placeholder="请在这里输入内容"
        rows={5}
        style={{ width: '100%' }}
      />

  );
}
```

{% endtab %}

{% tab title="React Native" %}

```tsx
import { useEffect, useState } from 'react';
import { Alert, Button, View } from 'react-native';
import { useBackEvent } from '@granite-js/react-native';

function UseBackEventExample() {
  const backEvent = useBackEvent();

  const [handler, setHandler] = useState<{ callback: () => void } | undefined>(undefined);

  useEffect(() => {
    const callback = handler?.callback;

    if (callback != null) {
      backEvent.addEventListener(callback);

      return () => {
        backEvent.removeEventListener(callback);
      };
    }

    return;
  }, [backEvent, handler]);

  return (
    <View>
      <Button
        title="添加 BackEvent"
        onPress={() => {
          setHandler({ callback: () => Alert.alert('back') });
        }}
      />
      <Button
        title="移除 BackEvent"
        onPress={() => {
          setHandler(undefined);
        }}
      />
    </View>
  );
}
```

{% endtab %}
{% endtabs %}

***

### 2. 控制主页按钮事件

当用户按下主页按钮时，可以执行所需的操作。

**主要功能**

| 功能                                                    | 说明                   |
| ----------------------------------------------------- | -------------------- |
| `homeEvent`                                           | 这是在按下主页按钮时发生的事件。     |
| `graniteEvent.addEventListener('homeEvent', { ... })` | (Web) 订阅事件。          |
| `homeEvent.subscribe(callback)`                       | (React Native) 订阅事件。 |
| `onEvent`                                             | 在按下主页按钮时调用。          |
| `onError`                                             | 在处理事件时发生错误时调用。       |
| `unsubscribe()`                                       | 可以取消已注册的事件监听器。       |

在 React Native 中， `homeEvent.subscribe()`可以使用它实现相同的逻辑。

**示例**

{% tabs %}
{% tab title="js" %}

```js
import { graniteEvent } from '@apps-in-toss/web-framework';

const unsubscribe = graniteEvent.addEventListener('homeEvent', {
  onEvent: () => {
    console.log('主页按钮已点击');
  },
});

unsubscribe(); // 删除处理器
```

{% endtab %}

{% tab title="React" %}

```tsx
import { graniteEvent } from '@apps-in-toss/web-framework';

const unsubscribe = graniteEvent.addEventListener('homeEvent', {
  onEvent: () => {
    window.alert('主页按钮已点击');
  },
});
```

{% endtab %}

{% tab title="React Native" %}

```tsx
import { homeEvent } from '@apps-in-toss/framework';

const unsubscribe = homeEvent.subscribe(() => {
  console.log('主页按钮已点击');
});

unsubscribe();
```

{% endtab %}
{% endtabs %}

***

### 参考事项

* `graniteEvent`用于原生事件（返回等）， `appsInTossEvent`用于检测 Toss 应用内部状态变化。
* 已注册的事件监听器必须 **在组件卸载时解除**。
* 对于基于事件执行的操作，务必 **添加错误处理器（onError）** 以应对异常情况。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://developers-apps-in-toss.toss.im/documentation/api-and-sdk-zh/common/screen/event.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
