函数式组件 -- 触发锁屏

函数式组件 -- 触发锁屏

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);
相关推荐
大橙子额7 分钟前
【解决报错】Cannot assign to read only property ‘exports‘ of object ‘#<Object>‘
前端·javascript·vue.js
LYFlied1 小时前
从 Vue 到 React,再到 React Native:资深前端开发者的平滑过渡指南
vue.js·react native·react.js
爱喝白开水a2 小时前
前端AI自动化测试:brower-use调研让大模型帮你做网页交互与测试
前端·人工智能·大模型·prompt·交互·agent·rag
董世昌412 小时前
深度解析ES6 Set与Map:相同点、核心差异及实战选型
前端·javascript·es6
吃杠碰小鸡3 小时前
高中数学-数列-导数证明
前端·数学·算法
kingwebo'sZone3 小时前
C#使用Aspose.Words把 word转成图片
前端·c#·word
xjt_09013 小时前
基于 Vue 3 构建企业级 Web Components 组件库
前端·javascript·vue.js
我是伪码农3 小时前
Vue 2.3
前端·javascript·vue.js
夜郎king4 小时前
HTML5 SVG 实现日出日落动画与实时天气可视化
前端·html5·svg 日出日落
夏幻灵5 小时前
HTML5里最常用的十大标签
前端·html·html5