函数式组件 -- 触发锁屏

函数式组件 -- 触发锁屏

1. 故事背景

在前端开发中,常常需要实现锁屏功能;最为常见的情况为点击某个按钮进入锁屏。本文从实际业务出发,从已经实现的锁屏功能中抽取出锁屏功能模板,从功能实现和注意细节两个角度进行说明,以实现后续开发过程中的复用。

2. 锁屏活动流程

    1. 点击锁屏按钮
    1. 记录锁屏前的前端路由到本地存储,方便锁屏解除之后回到当前页
    1. 关闭当前页面弹出的所有窗口
    1. 关闭锁屏期间不需要的通信服务,提升性能
    1. 使用react-router-domuseNavigate进行前端路由跳转
    1. 通知后端更新前端的锁屏信息(某些服务可以先暂停,保存时间戳等)

2.1 本地存储方法 setLock2Storage

将锁屏前地址写入本地,方便解除锁屏之后恢复

tsx 复制代码
// 将锁屏前地址写入本地,方便解除锁屏之后恢复
const setLock2Storage = (pathName: string) => {
  // store some info in storage
  sessionStorage.setItem('urlBeforeLock', pathName);
};

2.2 关闭现有弹窗方法 clearModals

父组件通过接口将回调函数队列传入此组件,在clearModals方法中依次执行这些回调函数,逐个关闭打开的Modal

tsx 复制代码
  clearModals(){
    this.props.clearModals?.forEach(cb => void cb());
  }

2.3 锁屏期间关闭和后端不必要的通信服务的方法 clearWs

clearWs方法显然需要从父组件传递过来,直接调用就可以了:this.props.clearWs();

2.4 导航到前端锁屏路由

使用钩子函数``即可完成任务,对于类组件而言,使用适配器设计模式稍微包装一下即可

tsx 复制代码
this.props.navigate("/lock");
...
// 包装组件
const withNavigation = (Component) => {
  return (props) => <Component {...props} navigate={useNavigate()} />;
};
// 暴露包装后的组件
export default withNavigation(Lock);

2.5 发送消息通知后端更新状态的方法 notify

使用的是fetch方法和URL构造函数

tsx 复制代码
// 通知后端更新锁屏状态
const notify = (apiUrl:string, pathName: string) => {
  // send some info to server
  const requestUrl = new URL('/Lock', apiUrl); 
  const requestBody = {
    params: {
      pathName: pathName
    }
  };

  const requestOptions = {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(requestBody)
  };

  fetch(requestUrl, requestOptions);
};

2.6 功能内聚方法 handleClick(按钮点击函数的回调)

tsx 复制代码
  handleClick() {
    // 将锁屏前的url存到本地,解除锁屏的时候能够恢复到锁屏之间的位置
    setLock2Storage(this.location);
    // 锁屏之前关闭当前页面上的所有弹窗
    this.clearModals();
    // 锁屏之后和有些ws的通信需要关掉,提高性能
    this.props.clearWs();
    // 导航到锁屏
    this.props.navigate("/lock");
    // 向后端发送请求,更新前端状态
    notify(this.appUri, this.location);
  }

3. Lock组件的接口 -- ILockProps

tsx 复制代码
export interface ILockProps {
  cls4style: string; // 父组件为了控制按钮样式传递过来的类名
  navigate: NavigateFunction; // withNavigation钩子函数向props中注入的方法,作用是进行前端跳转
  clearModals: Array<()=>void>; // 清除当前屏幕上的弹窗
  clearWs: ()=>void; // 关闭锁屏之后不需要通信的ws
  notify: ()=>void; // 通知后端更新前端锁屏状态
}

4. Lock组件的参数

tsx 复制代码
  private appUri = 'http://localhost:3000'; // 后端通讯基地址
  private location = location.pathname; // 当前页路由
  private copywriting = "锁屏"; // 按钮上的文案

5. Lock组件依赖库

tsx 复制代码
import React from "react";
import { Tooltip } from "antd"; // 组件
import { useNavigate } from "react-router-dom"; // 前端路由钩子
import { NavigateFunction } from "react-router/dist/lib/hooks"; // 类型约束

6. Lock组件内容 render函数的返回值

tsx 复制代码
  render() {
    return (
      <Tooltip
        title={this.copywriting}
        placement="top"
      >
        <span
          className={this.props.cls4style}
          onClick={this.handleClick}
          style={{width: 100}}
        >
          {this.copywriting}
        </span>
      </Tooltip>
    );
  }

7. Lock组件全部内容

tsx 复制代码
import React from "react";
import { Tooltip } from "antd";
import { useNavigate } from "react-router-dom";
import { NavigateFunction } from "react-router/dist/lib/hooks";

const withNavigation = (Component) => {
  return (props) => <Component {...props} navigate={useNavigate()} />;
};

export interface ILockProps {
  cls4style: string; // 父组件为了控制按钮样式传递过来的类名
  navigate: NavigateFunction; // withNavigation钩子函数向props中注入的方法,作用是进行前端跳转
  clearModals: Array<()=>void>; // 清除当前屏幕上的弹窗
  clearWs: ()=>void; // 关闭锁屏之后不需要通信的ws
  notify: ()=>void; // 通知后端更新前端锁屏状态
}

// 将锁屏前地址写入本地,方便解除锁屏之后恢复
const setLock2Storage = (pathName: string) => {
  // store some info in storage
  sessionStorage.setItem('urlBeforeLock', pathName);
};

// 通知后端更新锁屏状态
const notify = (apiUrl:string, pathName: string) => {
  // send some info to server
  const requestUrl = new URL('/Lock', apiUrl); 
  const requestBody = {
    params: {
      pathName: pathName
    }
  };

  const requestOptions = {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(requestBody)
  };

  fetch(requestUrl, requestOptions);
};
class Lock extends React.Component<ILockProps, undefined> {
  private appUri = 'http://localhost:3000'; // 后端通讯基地址
  private location = location.pathname; // 当前页路由
  private copywriting = "锁屏"; // 按钮上的文案
  
  handleClick() {
    // 将锁屏前的url存到本地,解除锁屏的时候能够恢复到锁屏之间的位置
    setLock2Storage(this.location);
    // 锁屏之前关闭当前页面上的所有弹窗
    this.clearModals();
    // 锁屏之后和有些ws的通信需要关掉,提高性能
    this.props.clearWs();
    // 导航到锁屏
    this.props.navigate("/lock");
    // 向后端发送请求,更新前端状态
    notify(this.appUri, this.location);
  }

  clearModals(){
    this.props.clearModals?.forEach(cb => void cb());
  }
  render() {
    return (
      <Tooltip
        title={this.copywriting}
        placement="top"
      >
        <span
          className={this.props.cls4style}
          onClick={this.handleClick}
          style={{display: 'inline-block',  width: '126px'}}
        >
          {this.copywriting}
        </span>
      </Tooltip>
    );
  }
}

export default withNavigation(Lock);
相关推荐
明君879972 分钟前
Flutter 如何给图片添加多行文字水印
前端·flutter
leolee1832 分钟前
Redux Toolkit 实战使用指南
前端·react.js·redux
bluceli35 分钟前
React Hooks最佳实践:写出优雅高效的组件代码
前端·react.js
IT_陈寒44 分钟前
JavaScript代码效率提升50%?这5个优化技巧你必须知道!
前端·人工智能·后端
IT_陈寒1 小时前
Java开发必知的5个性能优化黑科技,提升50%效率不是梦!
前端·人工智能·后端
LDX前端校草1 小时前
前端开发规则配置
前端
代码老中医1 小时前
2026前端工程化新范式:如何用AI驱动你的设计系统?
前端
用户11481867894841 小时前
Vite项目中的SVG雪碧图
前端·面试
ZengLiangYi1 小时前
并发 401 下的 Token 刷新竞态:一个被低估的 Bug
typescript
这个实现不了1 小时前
vue写一些进度条样式1
前端