> 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="Add BackEvent"
        onPress={() => {
          setHandler({ callback: () => Alert.alert('back') });
        }}
      />
      <Button
        title="Remove 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 app 内部状态变化。
* 已注册的事件监听器必须 **在组件卸载时解除**。
* 对于基于事件执行的操作，必须 **添加错误处理器（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.
