前端成功转鸿蒙开发者真实案例,教大家如何开发鸿蒙APP-- 卡片编辑功能

大家好,我是陈杨,一名有着8 年前端开发经验、6 年技术写作积淀的鸿蒙开发者,也是鸿蒙生态里的一名极客。

曾因前端行业的危机感居安思危,果断放弃饱和的 iOS、安卓赛道,在鸿蒙 API9 发布时,凭着前端技术底子,三天吃透 ArkTS 框架 ,快速上手鸿蒙开发。三年深耕,我不仅打造了鸿蒙开源图表组件库「莓创图表」,闯进过创新赛、极客挑战赛总决赛,更带着团队实实在在做出了成果 ------ 目前已成功上架11 款鸿蒙应用 ,涵盖工具、效率、创意等多个品类,包括JLPT、REFLEX PRO、国潮纸刻、Wss 直连、ZenithDocs Pro、圣诞相册、CSS 特效等,靠这些自研产品赚到了转型后的第一桶金。

从前端转型到鸿蒙掘金,靠的不是运气,而是选对赛道的眼光和快速落地的执行力。今天这篇文章主要是给大家分享卡片怎么实现在线编辑的。我们开发的指令魔方的卡片是完全支持用户自定义编辑,自由组合。

我们前面也讲了好多知识点,没学习的同学赶快学起来,记得帮我们点赞哦:

  1. 前端成功转鸿蒙开发者真实案例,教大家如何开发鸿蒙APP--ArkTS 卡片开发完全指南

  2. 前端成功转鸿蒙开发者真实案例,教大家如何开发鸿蒙APP--ArkTS 卡片页面开发核心能力

  3. 前端成功转鸿蒙开发者真实案例,教大家如何开发鸿蒙APP--ArkTS 卡片刷新机制

  4. 前端成功转鸿蒙开发者真实案例,教大家如何开发鸿蒙APP--ArkTS 卡片事件处理

  5. 前端成功转鸿蒙开发者真实案例,教大家如何开发鸿蒙APP-- 卡片实践

一、卡片编辑交互核心原理

1. 核心组件与角色分工

卡片编辑功能的实现依赖FormEditExtensionAbility组件,这是 HarmonyOS 提供的专门用于卡片编辑的扩展能力。整个交互流程涉及三个核心角色:

  • 卡片提供方 :开发编辑页面及逻辑,通过FormEditExtensionAbility暴露编辑能力;
  • 卡片使用方(通常是桌面):提供统一的编辑入口,接收并展示提供方的编辑页面;
  • 卡片管理服务:作为中间桥梁,传递编辑页面信息,协调双方交互。

2. 完整交互流程

卡片编辑的核心流程可概括为 "触发 - 拉起 - 传递 - 编辑" 四步,如下所示:

  1. 用户点击桌面卡片的编辑入口,触发编辑事件;
  2. 卡片使用方检测到卡片提供方已继承FormEditExtensionAbility,拉起一级编辑页;
  3. 提供方在onSessionCreate回调中,通过FormEditExtensionContextstartSecondPage方法,将二级编辑页信息传递给卡片管理服务;
  4. 卡片管理服务转发信息给使用方,最终拉起二级编辑页,用户完成内容编辑。

二、分步实现卡片编辑功能

前置说明

开发环境要求:HarmonyOS SDK 9 及以上,DevEco Studio 4.0+,工程类型为 ArkTS 工程(Stage 模型)。

1. 第一步:创建 FormEditExtensionAbility 子类

首先需要创建FormEditExtensionAbility的实现类,这是卡片编辑能力的核心入口,负责加载一级编辑页并提供跳转二级编辑页的方法。

代码实现(EntryFormEditAbility.ets)

typescript 复制代码
import { FormEditExtensionAbility } from '@kit.FormKit';
import { Want, UIExtensionContentSession } from '@kit.AbilityKit';
import { ExtensionEvent } from '../pages/model/ExtensionEvent';

const TAG: string = 'FormEditDemo[EntryFormEditAbility] -->';

export default class EntryFormEditAbility extends FormEditExtensionAbility {
  // 能力创建时调用
  onCreate() {
    console.log(`${TAG} 编辑能力创建`);
  }

  // 能力切换到前台时调用
  onForeground(): void {
    console.log(`${TAG} 编辑能力切换到前台`);
  }

  // 能力切换到后台时调用
  onBackground(): void {
    console.log(`${TAG} 编辑能力切换到后台`);
  }

  // 能力销毁时调用
  onDestroy(): void {
    console.log(`${TAG} 编辑能力销毁`);
  }

  // 编辑会话创建时调用,核心回调方法
  onSessionCreate(want: Want, session: UIExtensionContentSession) {
    console.log(`${TAG} 编辑会话创建,参数:${JSON.stringify(want)}`);
    
    // 创建本地存储,用于传递事件和数据
    let storage: LocalStorage = new LocalStorage();
    let extensionEvent: ExtensionEvent = new ExtensionEvent();
    
    // 绑定二级页面跳转方法
    extensionEvent.setStartSecondPage(() => this.startSecondPage());
    storage.setOrCreate('extensionEvent', extensionEvent);
    
    try {
      // 加载一级编辑页(Extension页面)
      session.loadContent('pages/Extension', storage);
      // 设置页面背景透明(可选,根据设计需求调整)
      session.setWindowBackgroundColor('#00000000');
    } catch (e) {
      console.log(`${TAG} 加载一级编辑页失败:${JSON.stringify(e)}`);
    }
  }

  // 编辑会话销毁时调用
  onSessionDestroy(session: UIExtensionContentSession) {
    console.log(`${TAG} 编辑会话销毁`);
  }

  // 跳转二级编辑页的核心方法
  private startSecondPage(): void {
    // 获取应用包名和二级编辑页能力名
    const bundleName: string = this.context.extensionAbilityInfo.bundleName;
    const secPageAbilityName: string = 'FormEditSecPageAbility';
    
    console.log(`${TAG} 跳转二级编辑页,包名:${bundleName},能力名:${secPageAbilityName}`);
    
    try {
      this.context.startSecondPage({
        bundleName: bundleName,
        parameters: {
          "secPageAbilityName": secPageAbilityName // 传递二级页面参数
        }
      });
    } catch (err) {
      console.log(`${TAG} 跳转二级编辑页失败:${err}`);
    }
  }
}

代码解析

  • 继承FormEditExtensionAbility是实现编辑功能的前提,系统会通过该类识别卡片的编辑能力;
  • onSessionCreate是核心回调,在编辑会话创建时触发,主要负责初始化存储、绑定跳转方法、加载一级编辑页;
  • startSecondPage方法通过FormEditExtensionContext提供的 API,将二级编辑页信息传递给系统,实现页面跳转。

2. 第二步:实现一级编辑页(Extension.ets)

一级编辑页是用户首先看到的编辑界面,通常包含编辑入口(如 "添加"、"修改" 按钮),点击后跳转至二级编辑页。

代码实现(Extension.ets)

typescript 复制代码
import { UIExtensionContentSession } from '@kit.AbilityKit';
import { ExtensionEvent } from './model/ExtensionEvent';

// 共享本地存储实例
let storage = new LocalStorage();
const TAG: string = 'FormEditDemo[Extension] -->';

@Entry(storage)
@Component
struct Extension {
  @State message: string = '卡片编辑';
  // 从存储中获取会话和事件实例
  private session: UIExtensionContentSession | undefined = storage.get<UIExtensionContentSession>('session');
  private extensionEvent: ExtensionEvent | undefined = storage.get<ExtensionEvent>('extensionEvent');

  // 页面显示时触发
  onPageShow() {
    console.log(`${TAG} 一级编辑页显示,事件实例:${JSON.stringify(this.extensionEvent)}`);
  }

  build() {
    Row() {
      Column() {
        // 编辑页标题
        Text(this.message)
          .fontSize(20)
          .fontWeight(FontWeight.Bold)
          .textAlign(TextAlign.Center)
        
        // 跳转二级编辑页的按钮
        Button("进入详细编辑")
          .width('80%')
          .type(ButtonType.Capsule)
          .margin({ top: 20 })
          .onClick(() => {
            console.log(`${TAG} 点击编辑按钮`);
            // 调用事件方法,触发二级页面跳转
            this.extensionEvent?.startFormEditSecondPage();
          })
      }
    }
    .justifyContent(FlexAlign.Center)
    .width('100%')
    .height('100%')
  }
}

代码解析

  • 页面通过@Entry(storage)绑定本地存储,实现与EntryFormEditAbility的数据共享;
  • 按钮点击事件通过extensionEvent调用startFormEditSecondPage方法,间接触发startSecondPage,实现解耦;
  • 布局采用 Flex 布局,保证页面元素居中显示,适配不同卡片尺寸。

3. 第三步:创建事件中间类(ExtensionEvent.ets)

该类作为中间桥梁,用于绑定startSecondPage方法并暴露给一级编辑页,避免直接依赖导致的耦合。

代码实现(ExtensionEvent.ets)

typescript 复制代码
const TAG: string = 'FormEditDemo[ExtensionEvent] -->';

export class ExtensionEvent {
  // 存储二级页面跳转方法
  private startSecondPage: () => void = () => {
    console.log(`${TAG} 跳转方法未绑定`);
  };

  // 绑定跳转方法(由EntryFormEditAbility调用)
  public setStartSecondPage(startSecondPage: () => void) {
    console.log(`${TAG} 绑定二级页面跳转方法`);
    this.startSecondPage = startSecondPage;
  }

  // 暴露给一级编辑页的跳转接口
  public startFormEditSecondPage(): void {
    console.log(`${TAG} 触发二级页面跳转`);
    this.startSecondPage();
  }
}

代码解析

  • 通过setStartSecondPage方法接收EntryFormEditAbility中的startSecondPage实现;
  • startFormEditSecondPage方法提供给一级编辑页调用,实现间接跳转,降低组件间耦合。

4. 第四步:配置文件修改

开发完核心代码后,需要修改工程配置文件,让系统识别卡片的编辑能力。

(1)module.json5 配置

entry模块的module.json5中添加extensionAbilities配置,声明编辑能力:

json 复制代码
{
  "extensionAbilities": [
    {
      "name": "EntryFormEditAbility",
      "srcEntry": "./ets/entryformeditability/EntryFormEditAbility.ets",
      "type": "formEdit" // 类型必须为formEdit
    }
  ]
}

(2)form_config.json 配置

在卡片配置文件中添加formConfigAbility,关联编辑能力:

kotlin 复制代码
{
  "forms": [
    {
      "name": "widget",
      "displayName": "$string:widget_display_name",
      "description": "$string:widget_desc",
      "src": "./ets/widget/pages/WidgetCard.ets",
      "uiSyntax": "arkts",
      "formConfigAbility": "ability://EntryFormEditAbility", // 关联编辑能力
      "window": {
        "designWidth": 720,
        "autoDesignWidth": true
      },
      "colorMode": "auto",
      "isDynamic": true,
      "isDefault": true,
      "updateEnabled": false,
      "scheduledUpdateTime": "10:30",
      "updateDuration": 1,
      "defaultDimension": "1*2",
      "supportDimensions": ["1*2", "2*2", "2*4", "4*4"]
    }
  ]
}

(3)main_pages.json 配置

在页面注册文件中添加一级编辑页(Extension.ets):

json 复制代码
{
  "src": [
    "pages/Index",
    "pages/Extension" // 注册一级编辑页
  ]
}

三、关键注意事项

  1. 依赖导入 :确保导入@kit.FormKit@kit.AbilityKit相关模块,避免编译错误;
  2. 页面权限 :二级编辑页需配置正确的bundleNameabilityName,否则跳转失败;
  3. 存储共享LocalStorage是页面与能力间数据传递的核心,需确保实例共享正确;
  4. 错误处理:代码中添加了完善的异常捕获,实际开发中可根据需求扩展错误处理逻辑;
  5. 适配性:编辑页布局需适配不同卡片尺寸,建议使用弹性布局(Flex)和自适应单位。

四、功能验证

  1. 编译运行工程,将卡片添加到桌面;
  2. 长按卡片,点击 "编辑" 按钮,触发一级编辑页显示;
  3. 点击一级编辑页的 "进入详细编辑" 按钮,验证是否成功跳转至二级编辑页;
  4. 查看 DevEco Studio 的 Logcat 日志,确认各回调方法正常触发(过滤 TAG 为FormEditDemo的日志)。

五、总结

通过以上步骤,即可完成卡片编辑功能的开发。我们严格遵循官方推荐的开发规范,实现了编辑页面的分层设计,具有良好的可扩展性和维护性,可根据实际业务需求扩展编辑页的内容和交互逻辑。

大家有什么不懂的可以在评论区留言,也可以私聊我,咱们下篇文章再见!!

相关推荐
Swift社区2 小时前
Flutter 的异步问题,为什么和前端 Promise 问题高度相似?
前端·flutter
程序员Agions2 小时前
AI 编程的"效率幻觉":为什么用了 Cursor 之后,你反而更累了?
前端·ai编程
lili-felicity2 小时前
React Native for Harmony 分类筛选页面多级菜单开发
react native·react.js·harmonyos
Android技术之家2 小时前
在手机上跑大模型?Google AI Edge Gallery 开源项目深度解析
前端·人工智能·edge·开源
DEMO派2 小时前
CSS优先级规则以及如何提升优先级方案详解
前端·javascript·css·vue.js·reactjs·html5·angular.js
hhcccchh2 小时前
学习vue第十一天 Vue3组件化开发指南:搭积木的艺术
前端·vue.js·学习
AntoineGriezmann2 小时前
基于 Unocss 的后台系统 SVG 图标方案实践
前端
小夏卷编程2 小时前
ant-design-vue 2.0 a-table 中实现特殊行样式,选中样式,鼠标悬浮样式不一样
前端·javascript·vue.js
wulijuan8886662 小时前
前端性能优化之图片webp
前端