Skip to content

事件监听

SDK 提供了事件监听机制,用于监听登录状态的变化。当登录状态发生改变时(登录、登出、Token 过期等),SDK 会自动触发相应事件,方便前端应用及时响应。

登录状态自动管理

SDK 会自动管理登录状态,包括:

  1. 自动登出机制

    • 当 API 请求返回 401 错误时,SDK 会自动清除 Token 并触发 logout 事件
    • 当检测到 Token 已过期时,SDK 会自动清除 Token 并触发 logout 事件
  2. Token 自动恢复

    • 页面刷新后,SDK 会自动从 localStorage 恢复 Token
    • 如果 Token 有效,登录状态会自动恢复
  3. Token 自动保存

    • 登录成功后,Token 会自动保存到 localStorage
    • 登出时,Token 会自动从 localStorage 清除

监听事件

on(event, callback) - 监听事件

监听 SDK 事件,当事件触发时执行回调函数。

参数:

  • event: 'login' | 'logout' - 事件名称
  • callback: (data: any) => void - 回调函数

事件说明:

事件名称触发时机事件数据
login用户登录成功时{ token: TokenObject, user?: UserObject }
logout用户登出时{ reason: 'manual' | 'unauthorized' | 'token_expired' }

登出原因说明:

  • 'manual': 手动调用 logout() 方法
  • 'unauthorized': API 请求返回 401 错误
  • 'token_expired': Token 已过期

示例:

javascript
// 监听登录事件
sdk.on('login', (data) => {
  console.log('用户已登录', data.token);
  // 更新应用状态
  updateUserState(data.user);
  // 重定向到主页
  router.push('/home');
});

// 监听登出事件
sdk.on('logout', (data) => {
  console.log('用户已登出,原因:', data.reason);
  // 清除应用状态
  clearUserState();
  // 根据原因处理
  if (data.reason === 'unauthorized' || data.reason === 'token_expired') {
    // 自动登出,重定向到登录页
    router.push('/login');
  }
});

取消监听事件

off(event, callback) - 取消监听事件

取消监听指定事件。

参数:

  • event: 'login' | 'logout' - 事件名称
  • callback: (data: any) => void - 回调函数(可选,不传则移除该事件的所有监听器)

示例:

javascript
// 定义回调函数
const loginHandler = (data) => {
  console.log('登录成功', data);
};

// 监听事件
sdk.on('login', loginHandler);

// 取消监听(传入相同的回调函数)
sdk.off('login', loginHandler);

// 或者移除所有登录事件监听器
sdk.off('login');

React 示例

javascript
import { useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import DingYueSDK from 'dingyue-web-sdk';

const sdk = new DingYueSDK({
  baseUrl: 'https://mobile.dingyue.io',
  appId: 'your-app-id',
  apiKey: 'your-api-key'
});

function App() {
  const navigate = useNavigate();

  useEffect(() => {
    // 监听登录事件
    const handleLogin = (data) => {
      console.log('登录成功', data);
      // 更新应用状态
      setUser(data.user);
      setIsLoggedIn(true);
      // 重定向到主页
      navigate('/home');
    };

    // 监听登出事件
    const handleLogout = (data) => {
      console.log('登出,原因:', data.reason);
      // 清除应用状态
      setUser(null);
      setIsLoggedIn(false);
      
      // 根据原因处理
      if (data.reason === 'unauthorized' || data.reason === 'token_expired') {
        // 自动登出,重定向到登录页
        navigate('/login');
      }
    };

    // 注册事件监听器
    sdk.on('login', handleLogin);
    sdk.on('logout', handleLogout);

    // 清理函数:组件卸载时移除监听器
    return () => {
      sdk.off('login', handleLogin);
      sdk.off('logout', handleLogout);
    };
  }, [navigate]);

  // ... 其他代码
}

Vue 示例

vue
<template>
  <div>
    <!-- 应用内容 -->
  </div>
</template>

<script>
import DingYueSDK from 'dingyue-web-sdk';

const sdk = new DingYueSDK({
  baseUrl: 'https://mobile.dingyue.io',
  appId: 'your-app-id',
  apiKey: 'your-api-key'
});

export default {
  mounted() {
    // 监听登录事件
    sdk.on('login', (data) => {
      console.log('登录成功', data);
      // 更新 Vuex 状态
      this.$store.dispatch('auth/setLoggedIn', {
        token: data.token,
        user: data.user
      });
      // 重定向到主页
      this.$router.push('/home');
    });

    // 监听登出事件
    sdk.on('logout', (data) => {
      console.log('登出,原因:', data.reason);
      // 清除 Vuex 状态
      this.$store.dispatch('auth/clearAuth');
      
      // 根据原因处理
      if (data.reason === 'unauthorized' || data.reason === 'token_expired') {
        // 自动登出,重定向到登录页
        this.$router.replace({ name: 'Login' });
      }
    });
  },
  beforeDestroy() {
    // 组件销毁时移除所有事件监听器
    sdk.off('login');
    sdk.off('logout');
  }
};
</script>

在应用初始化时设置事件监听

最佳实践是在应用初始化时立即设置事件监听,确保能监听到所有状态变化。

javascript
// main.js 或 App.js
import DingYueSDK from 'dingyue-web-sdk';

const sdk = new DingYueSDK({
  baseUrl: 'https://mobile.dingyue.io',
  appId: 'your-app-id',
  apiKey: 'your-api-key'
});

// 必须在 SDK 初始化后立即设置,确保能监听到所有事件
sdk.on('logout', (data) => {
  // 处理登出
  if (data.reason === 'unauthorized' || data.reason === 'token_expired') {
    // 自动登出,重定向到登录页
    router.replace('/login');
  }
});

sdk.on('login', (data) => {
  // 处理登录
  console.log('用户已登录', data);
});

// 导出 SDK 实例供其他模块使用
export default sdk;

多标签页同步

由于 SDK 使用 localStorage 存储 Token,多个标签页之间会自动同步。你可以监听 storage 事件来实时更新 UI:

javascript
// 监听 localStorage 变化(多标签页同步)
window.addEventListener('storage', (e) => {
  if (e.key === 'dingyue_token') {
    // Token 发生变化,检查登录状态
    if (sdk.isLoggedIn()) {
      // 其他标签页登录了,更新当前页面的状态
      updateUI();
    } else {
      // 其他标签页登出了,更新当前页面的状态
      clearUI();
    }
  }
});

注意事项

  1. 事件监听器应该在 SDK 初始化后立即设置,确保能监听到所有状态变化
  2. 记得在组件卸载时移除事件监听器,避免内存泄漏
  3. 登出事件会在以下情况自动触发
    • 手动调用 logout() 方法
    • API 请求返回 401 错误
    • Token 过期时调用需要认证的 API
  4. 登录事件会在以下情况触发
    • 调用 register() 注册成功
    • 调用 login() 登录成功
    • 调用 loginWithOAuth() OAuth 登录成功
  5. 事件回调函数中的错误不会影响 SDK 的正常运行,SDK 会捕获并记录错误