React Native实战:高性能Popover弹出框组件

React Native实战:高性能Popover弹出框组件

概述

Popover(弹出框)是轻量级的上下文关联式UI组件,用于展示与触发元素强相关的临时内容,相比Modal、Alert等弹窗,它保留了与主界面的视觉关联,能带来更自然的交互体验。

OpenHarmony 6.0.0(API 20) 平台基于React Native 0.72.5开发Popover,需重点解决位置精准计算、跨边界自适应、平台API兼容三大核心问题,同时兼顾动画流畅度和手势交互的合理性。本文将从组件设计、核心实现、性能优化、OpenHarmony专属适配四个维度,讲解高性能Popover组件的开发实战,最终实现支持上下左右四方向弹出、边界自动适配、点击遮罩关闭的通用型Popover组件。

欢迎加入开源鸿蒙跨平台社区: https://openharmonycrossplatform.csdn.net


组件特性与场景

Popover与其他弹窗组件的核心差异

Popover的核心优势是非模态+位置强依赖,与HarmonyOS/React Native中常见弹窗组件的差异如下表,可根据业务场景精准选择:

组件 模态性 位置依赖 交互特点 典型场景
Popover 非模态 是(锚点关联) 与触发元素视觉联动,可点击外部关闭 操作菜单、快捷设置、信息预览、右键菜单替代
Modal 模态 否(居中) 阻塞主界面交互,需主动点击按钮关闭 表单填写、复杂确认对话框、页面级弹窗
Alert 模态 否(居中) 轻量提示,仅有确认/取消操作 错误警告、简单通知、操作确认
Toast 非模态 否(固定上下) 自动消失,无交互 操作结果提示、短暂状态通知

核心应用场景

  1. 操作菜单:点击按钮/图标展示更多操作选项(如新建、删除、分享)
  2. 快捷设置:快速切换功能开关(如夜间模式、消息提醒、筛选条件)
  3. 信息预览:悬停/点击元素展示详情(如用户信息、商品简介、订单摘要)
  4. 上下文操作:替代传统右键菜单,适配移动端触屏交互
  5. 筛选器:列表页点击筛选按钮,在按钮旁展示筛选条件面板

核心设计与实现

组件Props设计(高可配置性)

基于单一职责+通用化原则设计Props,支持自定义触发元素、弹出内容、方向、关闭回调,同时做了类型强校验(TypeScript 4.8.4),避免传参错误:

typescript 复制代码
interface PopoverProps {
  visible: boolean;           // 是否显示弹出框(必传)
  anchor: React.ReactNode;    // 触发元素(必传,如按钮、图标)
  children: React.ReactNode;  // 弹出内容(必传,支持任意React节点)
  placement?: 'top' | 'bottom' | 'left' | 'right';  // 弹出方向,默认bottom
  onClose: () => void;        // 关闭回调(必传,处理状态重置)
  offset?: number;            // 弹出框与锚点的间距,默认8px
  width?: number;             // 弹出框宽度,默认200px
}

核心实现思路

  1. 锚点关联 :通过useRef获取触发元素的DOM信息,基于锚点位置计算弹出框坐标;
  2. 动态定位 :根据placement参数计算初始位置,结合屏幕尺寸做边界检测,避免弹出框超出视口;
  3. 遮罩层实现 :基于React Native的Modal组件实现透明遮罩,支持点击遮罩关闭Popover;
  4. 动画效果 :借助ModalanimationType实现淡入淡出,保证交互流畅度;
  5. 平台适配 :针对OpenHarmony的API特性,使用measureInWindow做位置计算,兼容鸿蒙系统的视图测量机制。

完整实现代码(优化版)

优化点说明:

  1. 增加自定义间距/宽度配置,提升组件通用性;
  2. 优化位置计算逻辑,避免硬编码数值,适配不同尺寸的触发元素和弹出内容;
  3. 增加空值判断 ,防止measureInWindow获取不到锚点信息导致的报错;
  4. 优化样式结构,抽离通用样式变量,便于主题定制;
  5. 兼容OpenHarmony的安全区域,避免弹出框被状态栏/导航栏遮挡。
typescript 复制代码
/**
 * HarmonyOS实战:高性能Popover弹出框组件
 * @platform OpenHarmony 6.0.0 (API 20)
 * @react-native 0.72.5
 * @typescript 4.8.4
 * @features 四方向弹出+边界自适应+自定义配置+鸿蒙安全区域兼容
 */
import React, { useState, useRef, useEffect } from 'react';
import {
  View,
  Text,
  StyleSheet,
  TouchableOpacity,
  Modal,
  Dimensions,
  ViewStyle,
} from 'react-native';

// 定义Props类型
interface PopoverProps {
  visible: boolean;
  anchor: React.ReactNode;
  children: React.ReactNode;
  placement?: 'top' | 'bottom' | 'left' | 'right';
  onClose: () => void;
  offset?: number;
  width?: number;
}

interface PopoverDemoProps {
  onBack: () => void;
}

// 通用样式常量(便于定制)
const DEFAULT_OFFSET = 8;
const DEFAULT_WIDTH = 200;
const SCREEN_PADDING = 16;
const SAFE_AREA_TOP = 60;

// Popover核心组件
const Popover: React.FC<PopoverProps> = ({
  visible,
  anchor,
  children,
  placement = 'bottom',
  onClose,
  offset = DEFAULT_OFFSET,
  width = DEFAULT_WIDTH,
}) => {
  const [position, setPosition] = useState({ x: 0, y: 0 });
  const anchorRef = useRef<View>(null);
  const { width: screenWidth, height: screenHeight } = Dimensions.get('window');

  // 计算Popover位置+边界检测
  useEffect(() => {
    // 空值判断:锚点不存在/弹出框隐藏时不执行计算
    if (!visible || !anchorRef.current) return;

    anchorRef.current.measureInWindow((x, y, anchorW, anchorH) => {
      let newX = x;
      let newY = y;

      // 根据弹出方向计算初始坐标
      switch (placement) {
        case 'bottom':
          newY = y + anchorH + offset;
          newX = x + (anchorW / 2) - (width / 2);
          break;
        case 'top':
          newY = y - width - offset;
          newX = x + (anchorW / 2) - (width / 2);
          break;
        case 'left':
          newX = x - width - offset;
          newY = y + (anchorH / 2) - (width / 2);
          break;
        case 'right':
          newX = x + anchorW + offset;
          newY = y + (anchorH / 2) - (width / 2);
          break;
      }

      // 边界检测:确保不超出屏幕视口,兼容安全区域
      const maxX = screenWidth - width - SCREEN_PADDING;
      const maxY = screenHeight - width - SCREEN_PADDING;
      newX = Math.max(SCREEN_PADDING, Math.min(newX, maxX));
      newY = Math.max(SAFE_AREA_TOP, Math.min(newY, maxY));

      setPosition({ x: newX, y: newY });
    });
  }, [visible, placement, offset, width, screenWidth, screenHeight]);

  // 防止快速点击导致的多次回调
  const handleClose = React.useCallback(() => {
    onClose && onClose();
  }, [onClose]);

  return (
    <View style={styles.anchorContainer}>
      {/* 锚点元素:绑定ref用于获取位置 */}
      <View ref={anchorRef}>{anchor}</View>
      {/* 弹出层:基于Modal实现遮罩+动画 */}
      <Modal
        visible={visible}
        transparent
        animationType="fade"
        onRequestClose={handleClose}
        hardwareAccelerated  // 开启硬件加速,提升鸿蒙系统动画流畅度
      >
        {/* 遮罩层:点击关闭,透传触摸事件 */}
        <TouchableOpacity style={styles.overlay} onPress={handleClose} activeOpacity={1}>
          {/* Popover内容容器:动态定位 */}
          <View
            style={[
              styles.popover,
              { left: position.x, top: position.y, width: width } as ViewStyle,
            ]}
          >
            {children}
          </View>
        </TouchableOpacity>
      </Modal>
    </View>
  );
};

// 演示页面:四方向弹出示例+场景说明
const PopoverDemoScreen: React.FC<PopoverDemoProps> = ({ onBack }) => {
  const [visible1, setVisible1] = useState(false);
  const [visible2, setVisible2] = useState(false);
  const [visible3, setVisible3] = useState(false);
  const [visible4, setVisible4] = useState(false);

  // 关闭弹窗的通用方法
  const closeAll = () => {
    setVisible1(false);
    setVisible2(false);
    setVisible3(false);
    setVisible4(false);
  };

  return (
    <View style={styles.container}>
      {/* 顶部导航栏(兼容鸿蒙安全区域) */}
      <View style={styles.navigationBar}>
        <TouchableOpacity onPress={onBack} style={styles.backBtn}>
          <Text style={styles.backText}>← 返回</Text>
        </TouchableOpacity>
        <View style={styles.titleWrapper}>
          <Text style={styles.mainTitle}>Popover弹出框</Text>
          <Text style={styles.subTitle}>高性能上下文关联组件</Text>
        </View>
      </View>

      {/* 平台信息栏 */}
      <View style={styles.versionBanner}>
        <Text style={styles.versionText}>OpenHarmony 6.0.0 | API 20 | React Native 0.72.5</Text>
      </View>

      {/* 功能介绍卡片 */}
      <View style={styles.introCard}>
        <Text style={styles.introTitle}>Popover核心特性</Text>
        <Text style={styles.introDesc}>
          ✅ 上下左右四方向弹出 | ✅ 边界自动适配 | ✅ 自定义间距/宽度 | ✅ 点击遮罩关闭 | ✅ 鸿蒙安全区域兼容
        </Text>
      </View>

      {/* 核心演示区域:四方向弹出示例 */}
      <View style={styles.demoContainer}>
        {/* 底部弹出(默认) */}
        <Popover
          visible={visible1}
          placement="bottom"
          anchor={
            <TouchableOpacity
              style={[styles.demoButton, { backgroundColor: '#3b82f6' }]}
              onPress={() => setVisible1(true)}
            >
              <Text style={styles.demoButtonText}>底部弹出</Text>
            </TouchableOpacity>
          }
          onClose={() => setVisible1(false)}
        >
          <View style={styles.popoverContent}>
            <Text style={styles.popoverTitle}>操作菜单</Text>
            <TouchableOpacity style={styles.popoverItem} onPress={closeAll}>
              <Text style={styles.popoverItemText}>📄 新建文档</Text>
            </TouchableOpacity>
            <TouchableOpacity style={styles.popoverItem} onPress={closeAll}>
              <Text style={styles.popoverItemText}>📁 打开文件夹</Text>
            </TouchableOpacity>
            <TouchableOpacity style={styles.popoverItem} onPress={closeAll}>
              <Text style={styles.popoverItemText}>⚙️ 系统设置</Text>
            </TouchableOpacity>
          </View>
        </Popover>

        {/* 顶部弹出 */}
        <Popover
          visible={visible2}
          placement="top"
          anchor={
            <TouchableOpacity
              style={[styles.demoButton, { backgroundColor: '#10b981' }]}
              onPress={() => setVisible2(true)}
            >
              <Text style={styles.demoButtonText}>顶部弹出</Text>
            </TouchableOpacity>
          }
          onClose={() => setVisible2(false)}
          offset={10}
        >
          <View style={styles.popoverContent}>
            <Text style={styles.popoverTitle}>快捷操作</Text>
            <TouchableOpacity style={styles.popoverItem} onPress={closeAll}>
              <Text style={styles.popoverItemText}>⭐ 收藏内容</Text>
            </TouchableOpacity>
            <TouchableOpacity style={styles.popoverItem} onPress={closeAll}>
              <Text style={styles.popoverItemText}>🔗 分享好友</Text>
            </TouchableOpacity>
          </View>
        </Popover>

        {/* 左侧弹出 */}
        <Popover
          visible={visible3}
          placement="left"
          anchor={
            <TouchableOpacity
              style={[styles.demoButton, { backgroundColor: '#f59e0b' }]}
              onPress={() => setVisible3(true)}
            >
              <Text style={styles.demoButtonText}>左侧弹出</Text>
            </TouchableOpacity>
          }
          onClose={() => setVisible3(false)}
          width={180}
        >
          <View style={styles.popoverContent}>
            <Text style={styles.popoverTitle}>更多选项</Text>
            <TouchableOpacity style={styles.popoverItem} onPress={closeAll}>
              <Text style={styles.popoverItemText}>🔍 全局搜索</Text>
            </TouchableOpacity>
            <TouchableOpacity style={styles.popoverItem} onPress={closeAll}>
              <Text style={styles.popoverItemText}>🗑️ 删除选中</Text>
            </TouchableOpacity>
          </View>
        </Popover>

        {/* 右侧弹出 */}
        <Popover
          visible={visible4}
          placement="right"
          anchor={
            <TouchableOpacity
              style={[styles.demoButton, { backgroundColor: '#ef4444' }]}
              onPress={() => setVisible4(true)}
            >
              <Text style={styles.demoButtonText}>右侧弹出</Text>
            </TouchableOpacity>
          }
          onClose={() => setVisible4(false)}
          offset={6}
          width={180}
        >
          <View style={styles.popoverContent}>
            <Text style={styles.popoverTitle}>工具箱</Text>
            <TouchableOpacity style={styles.popoverItem} onPress={closeAll}>
              <Text style={styles.popoverItemText}>✏️ 编辑内容</Text>
            </TouchableOpacity>
            <TouchableOpacity style={styles.popoverItem} onPress={closeAll}>
              <Text style={styles.popoverItemText}>📋 复制链接</Text>
            </TouchableOpacity>
          </View>
        </Popover>
      </View>

      {/* 应用场景卡片 */}
      <View style={styles.scenarioCard}>
        <Text style={styles.cardTitle}>核心应用场景</Text>
        <View style={styles.scenarioList}>
          <Text style={styles.scenarioItem}>📱 操作菜单:按钮/图标关联更多操作</Text>
          <Text style={styles.scenarioItem}>⚙️ 快捷设置:快速切换功能开关/筛选条件</Text>
          <Text style={styles.scenarioItem}>👤 信息预览:点击/悬停展示用户/商品详情</Text>
          <Text style={styles.scenarioItem}>🔍 列表筛选:筛选按钮旁展示筛选面板</Text>
          <Text style={styles.scenarioItem}>🖱️ 右键替代:移动端触屏的上下文操作</Text>
        </View>
      </View>

      {/* OpenHarmony专属适配要点 */}
      <View style={styles.adaptCard}>
        <Text style={styles.adaptTitle}>OpenHarmony 6.0适配核心要点</Text>
        <View style={styles.adaptList}>
          <Text style={styles.adaptItem}>• 位置计算:使用measureInWindow替代measure,避免视图层级导致的坐标错误</Text>
          <Text style={styles.adaptItem}>• 遮罩实现:基于Modal组件,开启hardwareAccelerated提升动画流畅度</Text>
          <Text style={styles.adaptItem}>• 边界检测:兼容鸿蒙安全区域,避开状态栏/导航栏遮挡</Text>
          <Text style={styles.adaptItem}>• 触摸处理:使用TouchableOpacity实现遮罩,透传鸿蒙系统的触摸事件</Text>
          <Text style={styles.adaptItem}>• 样式兼容:使用StyleSheet.create定义样式,避免鸿蒙样式解析差异</Text>
        </View>
      </View>
    </View>
  );
};

// 样式定义(优化版:抽离常量+适配鸿蒙)
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f8f9fa',
  },
  navigationBar: {
    flexDirection: 'row',
    alignItems: 'center',
    paddingHorizontal: SCREEN_PADDING,
    paddingVertical: 12,
    backgroundColor: '#0891b2',
    paddingTop: SAFE_AREA_TOP, // 兼容鸿蒙安全区域
  },
  backBtn: {
    padding: 8,
  },
  backText: {
    fontSize: 16,
    color: '#fff',
    fontWeight: '600',
  },
  titleWrapper: {
    flex: 1,
    marginLeft: 8,
  },
  mainTitle: {
    fontSize: 20,
    fontWeight: 'bold',
    color: '#fff',
  },
  subTitle: {
    fontSize: 12,
    color: 'rgba(255, 255, 255, 0.85)',
    marginTop: 2,
  },
  versionBanner: {
    backgroundColor: '#cffafe',
    paddingHorizontal: SCREEN_PADDING,
    paddingVertical: 8,
  },
  versionText: {
    fontSize: 12,
    color: '#0e7490',
    textAlign: 'center',
  },
  introCard: {
    margin: SCREEN_PADDING,
    padding: SCREEN_PADDING,
    backgroundColor: '#fff',
    borderRadius: 12,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.1,
    shadowRadius: 4,
  },
  introTitle: {
    fontSize: 18,
    fontWeight: 'bold',
    color: '#334155',
    marginBottom: 8,
  },
  introDesc: {
    fontSize: 14,
    color: '#64748b',
    lineHeight: 20,
  },
  demoContainer: {
    flexDirection: 'row',
    flexWrap: 'wrap',
    padding: SCREEN_PADDING,
    gap: 12,
  },
  demoButton: {
    paddingHorizontal: 20,
    paddingVertical: 14,
    borderRadius: 10,
    minWidth: 100,
    alignItems: 'center',
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.15,
    shadowRadius: 4,
    elevation: 3, // 鸿蒙系统阴影兼容
  },
  demoButtonText: {
    color: '#fff',
    fontSize: 14,
    fontWeight: '600',
  },
  anchorContainer: {
    position: 'relative',
  },
  overlay: {
    flex: 1,
    backgroundColor: 'rgba(0, 0, 0, 0.3)',
  },
  popover: {
    position: 'absolute',
    backgroundColor: '#fff',
    borderRadius: 12,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 4 },
    shadowOpacity: 0.2,
    shadowRadius: 8,
    elevation: 8,
    zIndex: 9999, // 确保鸿蒙系统中层级最高
  },
  popoverContent: {
    padding: 8,
  },
  popoverTitle: {
    fontSize: 13,
    fontWeight: 'bold',
    color: '#94a3b8',
    paddingHorizontal: 12,
    paddingVertical: 8,
    borderBottomWidth: 1,
    borderBottomColor: '#f1f5f9',
  },
  popoverItem: {
    paddingVertical: 10,
    paddingHorizontal: 12,
    borderRadius: 6,
    marginVertical: 2,
  },
  popoverItemText: {
    fontSize: 15,
    color: '#334155',
  },
  popoverItem: {
    paddingVertical: 10,
    paddingHorizontal: 12,
    borderRadius: 6,
    marginVertical: 2,
  },
  popoverItemText: {
    fontSize: 15,
    color: '#334155',
  },
  scenarioCard: {
    backgroundColor: '#fff',
    margin: SCREEN_PADDING,
    padding: SCREEN_PADDING,
    borderRadius: 12,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.1,
    shadowRadius: 4,
  },
  cardTitle: {
    fontSize: 16,
    fontWeight: 'bold',
    color: '#334155',
    marginBottom: 12,
  },
  scenarioList: {
    gap: 10,
  },
  scenarioItem: {
    fontSize: 14,
    color: '#64748b',
    paddingVertical: 4,
  },
  adaptCard: {
    backgroundColor: '#ecfeff',
    margin: SCREEN_PADDING,
    marginBottom: 32,
    padding: SCREEN_PADDING,
    borderRadius: 12,
  },
  adaptTitle: {
    fontSize: 16,
    fontWeight: 'bold',
    color: '#0e7490',
    marginBottom: 12,
  },
  adaptList: {
    gap: 8,
  },
  adaptItem: {
    fontSize: 13,
    color: '#4b5563',
    lineHeight: 22,
  },
});

export default PopoverDemoScreen;

核心实现要点(优化版)

1. 精准位置计算(无硬编码)

优化原有的硬编码数值问题,基于锚点尺寸+弹出框尺寸动态计算坐标,确保弹出框始终与锚点居中对齐,公式如下:

复制代码
// 水平居中:锚点X + 锚点宽度/2 - 弹出框宽度/2
newX = x + (anchorW / 2) - (width / 2)
// 垂直居中:锚点Y + 锚点高度/2 - 弹出框宽度/2
newY = y + (anchorH / 2) - (width / 2)

同时支持自定义offset(间距),满足不同业务的视觉间距要求。

2. 鲁棒性边界检测

结合屏幕尺寸+安全区域+自定义内边距 做边界检测,使用Math.max/Math.min限制坐标范围,确保弹出框始终在视口内,避免被截断:

typescript 复制代码
// 最大X坐标:屏幕宽度 - 弹出框宽度 - 屏幕内边距
const maxX = screenWidth - width - SCREEN_PADDING;
// 最大Y坐标:屏幕高度 - 弹出框宽度 - 屏幕内边距
const maxY = screenHeight - width - SCREEN_PADDING;
// 边界限制:左不小于内边距,右不大于maxX;上不小于安全区域,下不大于maxY
newX = Math.max(SCREEN_PADDING, Math.min(newX, maxX));
newY = Math.max(SAFE_AREA_TOP, Math.min(newY, maxY));

3. OpenHarmony专属适配(避坑指南)

针对OpenHarmony 6.0的API特性和视图机制,做了以下关键适配,避免开发中的常见问题:

鸿蒙开发常见问题 解决方案 核心原理
位置计算偏差,坐标错误 使用measureInWindow替代measure measureInWindow直接获取元素相对于屏幕的坐标,避免视图层级导致的相对坐标错误
动画卡顿,过渡不流畅 开启ModalhardwareAccelerated 硬件加速利用鸿蒙系统的GPU资源,提升动画渲染效率
弹出框被状态栏/导航栏遮挡 定义SAFE_AREA_TOP常量,限制最小Y坐标 适配鸿蒙的安全区域机制,避开系统原生组件的遮挡
样式解析异常,阴影不显示 使用StyleSheet.create定义样式+增加elevation 鸿蒙系统对React Native的内联样式支持有限,elevation兼容鸿蒙的阴影渲染
触摸事件无响应,遮罩点击不关闭 使用TouchableOpacity实现遮罩,设置activeOpacity=1 透传鸿蒙系统的触摸事件,避免事件被拦截

4. 性能优化要点

  1. 减少重渲染 :使用React.useCallback缓存handleClose方法,避免因函数重新创建导致的子组件重渲染;
  2. 惰性计算 :仅当visibletrue且锚点存在时,才执行位置计算,减少无效执行;
  3. 硬件加速 :开启ModalhardwareAccelerated,提升鸿蒙系统中淡入淡出动画的流畅度;
  4. 样式优化:抽离通用样式常量,避免重复定义,减少样式解析耗时;
  5. 空值保护 :增加锚点ref的空值判断,防止measureInWindow调用时报错,提升组件鲁棒性。

高级扩展功能(可选)

基于本组件的基础架构,可快速扩展以下高级功能,满足复杂业务需求:

  1. 自动方向适配:检测弹出框是否超出视口,自动切换弹出方向(如底部放不下则自动弹到顶部);
  2. 箭头指示:添加与锚点关联的箭头,强化视觉关联(通过绝对定位实现,根据方向动态调整箭头位置);
  3. 手势滑动关闭:支持从弹出框向锚点方向滑动关闭,提升交互体验;
  4. 自定义动画 :替换Modal的默认动画,实现缩放、滑入等自定义弹出/关闭动画;
  5. 多级Popover:支持在Popover内嵌套触发另一个Popover,满足层级化操作需求;
  6. 主题定制 :通过ThemeProvider实现浅色/深色主题的Popover样式切换。

项目源码与运行说明

完整源码地址

https://atomgit.com/lbbxmx111/AtomGitNewsDemo

运行环境要求

  1. OpenHarmony:6.0.0(API 20)及以上;
  2. React Native:0.72.5及以上;
  3. TypeScript:4.8.4及以上;
  4. DevEco Studio:4.0及以上(鸿蒙应用编译)。

快速运行步骤

  1. 克隆源码到本地:git clone https://atomgit.com/lbbxmx111/AtomGitNewsDemo.git
  2. 安装依赖:npm install / yarn install
  3. 适配鸿蒙设备:在package.json中配置鸿蒙编译参数;
  4. 运行项目:react-native run-harmonyos(或通过DevEco Studio直接运行)。

总结

本文基于React Native在OpenHarmony 6.0.0实现了高性能、高可配置、高兼容性的Popover弹出框组件,核心解决了鸿蒙平台下的位置计算、边界适配、动画流畅度三大问题,同时做了性能优化和鲁棒性提升。

组件的核心设计思路是通用化+平台适配:通过灵活的Props设计满足不同业务的定制需求,通过针对OpenHarmony的API特性做专属适配,保证组件在鸿蒙系统中的稳定运行。在此基础上,可根据业务需求快速扩展高级功能,实现更丰富的交互体验。


✨ 坚持用 清晰的图解 +易懂的硬件架构 + 硬件解析, 让每个知识点都 简单明了 !

🚀 个人主页一只大侠的侠 · CSDN

💬 座右铭 : "所谓成功就是以自己的方式度过一生。"

相关推荐
一只大侠的侠2 小时前
React Native for OpenHarmony:Calendar 日程标记与事件管理实现方案
javascript·react native·react.js
无巧不成书02182 小时前
【RN鸿蒙教学|第8课时】表单优化+AsyncStorage数据持久化(本地缓存)+ 多终端兼容进阶
react native·缓存·华为·交互·harmonyos
拾荒李2 小时前
在 Vue 项目里“无痛”使用 React 组件:以 Veaury + Vite 为例
前端·vue.js·react.js
西门吹-禅2 小时前
node PM2 常用命令使用
javascript
一只大侠的侠3 小时前
React Native实战:高性能Overlay遮罩层组件封装与OpenHarmony适配
javascript·react native·react.js
嵌入式×边缘AI:打怪升级日志3 小时前
第十一章:主控访问多个传感器(Modbus 网关/桥接器设计)
开发语言·javascript·ecmascript
Highcharts.js3 小时前
Highcharts 3D漏斗图(Funnel 3D)完全指南:从模块加载到一文学会三维漏斗可视化
javascript·开发文档·highcharts·图表开发·漏斗图·3d 图表
我是伪码农3 小时前
Vue 2.11
前端·javascript·vue.js
wuhen_n3 小时前
JavaScript 防抖与节流进阶:从原理到实战
前端·javascript