函数式组件 -- 触发锁屏

函数式组件 -- 触发锁屏

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);
相关推荐
也无晴也无风雨43 分钟前
深入剖析输入URL按下回车,浏览器做了什么
前端·后端·计算机网络
Martin -Tang1 小时前
Vue 3 中,ref 和 reactive的区别
前端·javascript·vue.js
FakeOccupational3 小时前
nodejs 020: React语法规则 props和state
前端·javascript·react.js
小牛itbull3 小时前
ReactPress:构建高效、灵活、可扩展的开源发布平台
react.js·开源·reactpress
放逐者-保持本心,方可放逐3 小时前
react 组件应用
开发语言·前端·javascript·react.js·前端框架
曹天骄4 小时前
next中服务端组件共享接口数据
前端·javascript·react.js
阮少年、4 小时前
java后台生成模拟聊天截图并返回给前端
java·开发语言·前端
郝晨妤6 小时前
鸿蒙ArkTS和TS有什么区别?
前端·javascript·typescript·鸿蒙
AvatarGiser6 小时前
《ElementPlus 与 ElementUI 差异集合》Icon 图标 More 差异说明
前端·vue.js·elementui
喝旺仔la6 小时前
vue的样式知识点
前端·javascript·vue.js