# Framework Usage Examples

## General Notes

- `bindEl` 对应的 DOM 节点必须已经挂载
- 请只在客户端初始化，不要在 SSR 阶段执行 `new TAC(...)`
- 销毁页面或组件时，调用 `tac.destroyWindow()`
- React Native 需要通过 `WebView` 使用，本 SDK 不能直接运行在原生视图树里

## Next.js

### App Router

`app/layout.tsx`

```tsx
import "captcha-web-sdk/style.css";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  );
}
```

`app/components/captcha-box.tsx`

```tsx
"use client";

import { useEffect } from "react";
import TAC from "captcha-web-sdk";

export default function CaptchaBox() {
  useEffect(() => {
    const tac = new TAC({
      requestCaptchaDataUrl: "/api/captcha/gen",
      validCaptchaUrl: "/api/captcha/check",
      bindEl: "#captcha-box"
    });

    tac.init();

    return () => {
      tac.destroyWindow();
    };
  }, []);

  return <div id="captcha-box" />;
}
```

## React

```tsx
import { useEffect } from "react";
import TAC from "captcha-web-sdk";
import "captcha-web-sdk/style.css";

export default function CaptchaBox() {
  useEffect(() => {
    const tac = new TAC({
      requestCaptchaDataUrl: "/captcha/gen",
      validCaptchaUrl: "/captcha/check",
      bindEl: "#captcha-box",
      validSuccess: (res, c, tacInstance) => {
        tacInstance.destroyWindow();
        console.log("success", res);
      }
    });

    tac.init();

    return () => {
      tac.destroyWindow();
    };
  }, []);

  return <div id="captcha-box" />;
}
```

## Vue 3

```vue
<template>
  <div id="captcha-box"></div>
</template>

<script setup>
import { onMounted, onBeforeUnmount } from "vue";
import TAC from "captcha-web-sdk";
import "captcha-web-sdk/style.css";

let tac;

onMounted(() => {
  tac = new TAC({
    requestCaptchaDataUrl: "/captcha/gen",
    validCaptchaUrl: "/captcha/check",
    bindEl: "#captcha-box"
  });

  tac.init();
});

onBeforeUnmount(() => {
  tac?.destroyWindow();
});
</script>
```

## Vue 2

```vue
<template>
  <div id="captcha-box"></div>
</template>

<script>
import TAC from "captcha-web-sdk";
import "captcha-web-sdk/style.css";

export default {
  name: "CaptchaBox",
  data() {
    return {
      tac: null
    };
  },
  mounted() {
    this.tac = new TAC({
      requestCaptchaDataUrl: "/captcha/gen",
      validCaptchaUrl: "/captcha/check",
      bindEl: "#captcha-box"
    });

    this.tac.init();
  },
  beforeDestroy() {
    if (this.tac) {
      this.tac.destroyWindow();
    }
  }
};
</script>
```

## React Native

React Native 中不能直接使用 DOM 版 SDK。推荐通过 `react-native-webview` 在 WebView 中加载。

```tsx
import React from "react";
import { WebView } from "react-native-webview";

const html = `
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link rel="stylesheet" href="https://your-cdn.example.com/tac/css/tac.css" />
  </head>
  <body>
    <div id="captcha-box"></div>
    <script src="https://your-cdn.example.com/tac/js/tac.min.js"></script>
    <script>
      const tac = new window.TAC({
        requestCaptchaDataUrl: "https://your-api.example.com/captcha/gen",
        validCaptchaUrl: "https://your-api.example.com/captcha/check",
        bindEl: "#captcha-box",
        validSuccess: function (res, c, tacInstance) {
          window.ReactNativeWebView.postMessage(JSON.stringify({
            type: "captcha-success",
            payload: res
          }));
          tacInstance.destroyWindow();
        }
      });

      tac.init();
    </script>
  </body>
</html>
`;

export default function CaptchaWebView() {
  return (
    <WebView
      originWhitelist={["*"]}
      source={{ html }}
      onMessage={(event) => {
        const data = JSON.parse(event.nativeEvent.data);
        console.log(data);
      }}
    />
  );
}
```
