React Native for Harmony 任务表「删除 / 完成任务 - 划线置灰效果」
核心 API / 组件 / Hook核心作用鸿蒙端特性【核心】实现文字划线效果,任务删除 / 完成的核心样式鸿蒙端完美支持所有取值,无样式兼容差异,划线粗细 / 颜色可自定义useState管理任务列表数据、任务完成 / 删除状态,驱动视图更新响应式更新无延迟,鸿蒙低端机型也能流畅刷新列表FlatList高性能渲染任务列表,支持长列表懒加载鸿蒙手机端优化滚动阻尼,滑动无卡顿,远优于map循环渲染任
目录
一、核心知识点:任务表划线效果 完整技术体系
1、核心内置 API / 组件 / Hook 介绍
本次实现任务表划线效果用到的能力均为 RN 原生自带,完美适配鸿蒙手机端,无任何兼容问题,也是鸿蒙端任务类 APP 的标准技术选型:
| 核心 API / 组件 / Hook | 核心作用 | 鸿蒙端特性 |
|---|---|---|
textDecorationLine |
【核心】实现文字划线效果,任务删除 / 完成的核心样式 | 鸿蒙端完美支持所有取值,无样式兼容差异,划线粗细 / 颜色可自定义 |
useState |
管理任务列表数据、任务完成 / 删除状态,驱动视图更新 | 响应式更新无延迟,鸿蒙低端机型也能流畅刷新列表 |
FlatList |
高性能渲染任务列表,支持长列表懒加载 | 鸿蒙手机端优化滚动阻尼,滑动无卡顿,远优于map循环渲染 |
TouchableOpacity |
任务项 / 按钮点击交互,实现完成 / 删除操作 | 鸿蒙原生按压透明反馈,符合鸿蒙交互规范,无点击失效问题 |
StyleSheet.create |
抽离样式常量,区分「正常态 / 完成态 / 删除态」样式 | 鸿蒙端样式引擎原生解析,样式优先级清晰,无错乱问题 |
useCallback |
缓存点击事件回调函数,避免任务列表频繁重渲染 | 鸿蒙手机端性能优化关键,列表数据越多优化越明显 |
2、任务划线效果 核心实现原理
任务表删除 / 完成后的划线置灰效果,本质是 「状态驱动样式变更」,也是 React 的核心开发思想,逻辑极简无复杂封装,这是鸿蒙端实现该效果的唯一最优解:
- 给任务对象新增状态字段:在每一条任务数据中,添加
isCompleted: boolean(是否完成)/isDeleted: boolean(是否删除) 布尔属性,默认值false; - 绑定样式条件判断:给任务的文字、容器添加「条件样式」,当
isCompleted/isDeleted = true时,自动触发 文字划线 + 整体透明度降低(置灰); - 点击事件修改状态:点击「完成 / 删除」按钮时,通过不可变数据的方式修改对应任务的状态值,状态变更后 React 自动触发组件重渲染,划线效果立即生效;
- 样式解耦管理:将「正常样式、完成样式、删除样式」抽离为独立常量,一处修改全局生效,符合鸿蒙端样式设计规范。
3、鸿蒙端任务表 划线效果 官方设计 & 交互规范
鸿蒙系统对任务类 APP 的「完成 / 删除」交互有统一的设计标准,遵循该规范开发的任务表,体验和鸿蒙原生应用一致,无违和感,也是企业级鸿蒙 RN 项目的必备规范:
样式规范(核心)
- 完成 / 删除态:文字添加 中划线(line-through) + 文字颜色改为浅灰
#999999+ 整体透明度opacity:0.7,这是鸿蒙端「已失效内容」的标准视觉表达; - 正常态:文字颜色为深灰
#333333,无划线,透明度opacity:1,对比度清晰; - 任务项样式:圆角
12px、上下间距6px、轻微内边距,避免内容拥挤,贴合手机端窄屏显示; - 按钮样式:完成按钮用鸿蒙主题蓝
#007DFF,删除按钮用鸿蒙警示红#FF4D4F,图标 / 文字极简,无多余装饰。
交互规范
- 点击反馈:所有按钮必须添加
activeOpacity={0.8},提供鸿蒙原生的按压透明反馈; - 完成逻辑:点击完成按钮后,任务划线置灰,保留在列表中(用户可二次点击取消完成);
- 删除逻辑:点击删除按钮后,任务划线置灰 + 透明度更低,可选择保留 / 移除列表(软删除 / 硬删除均可);
- 滑动逻辑:支持列表项左右滑动触发删除,滑动时伴随划线效果预览,符合鸿蒙端滑动交互习惯。
二、核心样式:实现「划线 + 置灰」的关键 CSS 属性
本次实现任务划线效果的核心核心,就是 RN 的textDecorationLine文本样式属性,这是原生支持的样式,无需任何复杂逻辑,鸿蒙端完美适配,所有取值如下,开发中按需使用即可:
// 任务完成/删除 核心划线样式
textDecorationLine: 'none' // 默认值:无划线(正常任务)
textDecorationLine: 'line-through'// 核心取值:文字中划线(完成/删除任务必用)
textDecorationLine: 'underline' // 下划线(极少用)
textDecorationLine: 'overline' // 上划线(极少用)
鸿蒙端最优组合样式(任务完成 / 删除标准)
// 正常态样式
taskText: {
fontSize: 16,
color: '#333333',
textDecorationLine: 'none', // 无划线
opacity: 1,
},
// 完成/删除态样式
taskTextCompleted: {
textDecorationLine: 'line-through', // 文字中划线
color: '#999999', // 置灰
opacity: 0.7, // 透明度降低,视觉更柔和
},
三、实战: 鸿蒙手机端 任务表(带删除 / 完成划线效果)
import React, { useState, useCallback } from 'react';
import {
View, Text, StyleSheet, FlatList, TouchableOpacity,
SafeAreaView, ListRenderItemInfo, Alert
} from 'react-native';
interface TaskItem {
id: string;
title: string;
desc: string;
time: string;
isCompleted: boolean; // 任务是否完成(核心:控制划线效果)
}
const { width } = Dimensions.get('window');
const TASK_LIST: TaskItem[] = [
{ id: '1', title: '学习React Native', desc: '完成鸿蒙端任务表开发', time: '09:30', isCompleted: false },
{ id: '2', title: '完成工作周报', desc: '整理本周开发进度', time: '14:00', isCompleted: false },
{ id: '3', title: '健身打卡', desc: '跑步30分钟+拉伸', time: '19:00', isCompleted: false },
{ id: '4', title: '阅读技术文档', desc: '鸿蒙RN官方适配指南', time: '21:00', isCompleted: false },
{ id: '5', title: '编写笔记', desc: '任务表划线效果核心知识点', time: '22:00', isCompleted: false },
];
const HarmonyTaskList: React.FC = () => {
const [taskData, setTaskData] = useState<TaskItem[]>(TASK_LIST);
const handleTaskComplete = useCallback((taskId: string) => {
const newTaskData = taskData.map(task => {
if (task.id === taskId) {
return { ...task, isCompleted: !task.isCompleted }; // 切换完成状态,不可变更新
}
return task;
});
setTaskData(newTaskData);
}, [taskData]);
const handleTaskDelete = useCallback((taskId: string) => {
// 方案1 仅标记状态,任务保留在列表(鸿蒙端主流交互)
const newTaskData = taskData.map(task => {
if (task.id === taskId) {
return { ...task, isCompleted: true }; // 标记为完成态 → 触发划线置灰
}
return task;
});
setTaskData(newTaskData);
// 方案2 弹窗确认后删除任务,无划线(注释掉方案1即可启用)
// Alert.alert('提示', '确定删除该任务吗?', [
// { text: '取消', style: 'cancel' },
// { text: '删除', onPress: () => {
// const newTaskData = taskData.filter(task => task.id !== taskId);
// setTaskData(newTaskData);
// }}
// ]);
}, [taskData]);
const renderTaskItem = ({ item }: ListRenderItemInfo<TaskItem>) => (
<TouchableOpacity
style={styles.taskItem}
activeOpacity={0.9}
onPress={() => handleTaskComplete(item.id)}
>
<Text style={[styles.taskTitle, item.isCompleted && styles.taskCompleted]}>
{item.title}
</Text>
<Text style={[styles.taskDesc, item.isCompleted && styles.taskTextGray]}>
{item.desc}
</Text>
<Text style={[styles.taskTime, item.isCompleted && styles.taskTextGray]}>
{item.time}
</Text>
<View style={styles.taskBtnGroup}>
<TouchableOpacity
style={styles.completeBtn}
onPress={() => handleTaskComplete(item.id)}
activeOpacity={0.8}
>
<Text style={styles.btnText}>{item.isCompleted ? '取消' : '完成'}</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.deleteBtn}
onPress={() => handleTaskDelete(item.id)}
activeOpacity={0.8}
>
<Text style={styles.btnText}>删除</Text>
</TouchableOpacity>
</View>
</TouchableOpacity>
);
return (
<SafeAreaView style={styles.container}>
<Text style={styles.pageTitle}>我的任务列表</Text>
<FlatList
data={taskData}
renderItem={renderTaskItem}
keyExtractor={item => item.id}
style={styles.taskList}
showsVerticalScrollIndicator={false}
contentContainerStyle={styles.taskListContent}
/>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#F5F5F5',
paddingHorizontal: 15,
},
pageTitle: {
fontSize: 20,
color: '#333333',
fontWeight: '600',
marginTop: 20,
marginBottom: 15,
},
taskList: {
flex: 1,
width: '100%',
},
taskListContent: {
paddingBottom: 30,
},
// 任务项容器样式
taskItem: {
backgroundColor: '#FFFFFF',
borderRadius: 12,
padding: 15,
marginBottom: 8,
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.05,
shadowRadius: 2,
elevation: 1,
},
// 任务标题-正常态
taskTitle: {
fontSize: 17,
color: '#333333',
fontWeight: '500',
marginBottom: 5,
textDecorationLine: 'none', // 默认无划线
},
// 任务描述-正常态
taskDesc: {
fontSize: 14,
color: '#666666',
marginBottom: 8,
},
// 任务时间-正常态
taskTime: {
fontSize: 12,
color: '#999999',
marginBottom: 12,
},
taskCompleted: {
textDecorationLine: 'line-through', // 文字中划线(核心)
color: '#999999',
opacity: 0.7,
},
// 仅置灰,无划线(描述/时间使用)
taskTextGray: {
color: '#999999',
opacity: 0.7,
},
// 按钮组样式
taskBtnGroup: {
flexDirection: 'row',
justifyContent: 'flex-end',
gap: 10,
},
completeBtn: {
backgroundColor: '#007DFF',
borderRadius: 8,
paddingHorizontal: 15,
paddingVertical: 6,
},
deleteBtn: {
backgroundColor: '#FF4D4F',
borderRadius: 8,
paddingHorizontal: 15,
paddingVertical: 6,
},
btnText: {
color: '#FFFFFF',
fontSize: 13,
fontWeight: '500',
},
});
export default HarmonyTaskList;

四、本次开发 核心修复 & 避坑指南
鸿蒙端任务表 高频踩坑点 & 最优解决方案
| 问题现象 | 问题根源 | 鸿蒙端一行代码解决方案 |
|---|---|---|
| 任务完成后,文字划线样式不生效 | 错误使用textDecoration: 'line-through',RN 中正确属性是textDecorationLine |
改为 textDecorationLine: 'line-through' |
TS 报错:Property 'isCompleted' does not exist on type 'object' |
未声明任务数据的接口类型,TS 无法推断属性 | 声明interface TaskItem { isCompleted: boolean }并指定状态类型 |
| 点击完成按钮,任务状态变更但划线效果不刷新 | 直接修改原数组的item.isCompleted,React 无法监听不可变数据 |
用map生成新数组:const newData = taskData.map(task => ({...task})) |
| 任务列表滑动卡顿,划线效果延迟显示 | 用map循环渲染长列表,未使用 FlatList 高性能组件 |
强制使用FlatList替代map渲染任务列表 |
| 鸿蒙端按钮点击无反馈,操作体验差 | 用View封装按钮,未使用TouchableOpacity |
所有按钮用TouchableOpacity包裹,并设置activeOpacity={0.8} |
| 划线颜色与文字颜色一致,视觉不明显 | 仅设置划线样式,未修改文字颜色和透明度 | 组合样式:textDecorationLine: 'line-through', color: '#999999', opacity:0.7 |
| 软删除后,任务无法恢复原状 | 仅设置isCompleted=true,未做状态切换逻辑 |
点击完成按钮时执行:isCompleted: !task.isCompleted 实现状态切换 |
五、✅ 扩展用法:任务表划线效果 高频进阶功能(
✅ 扩展 1:滑动删除任务(鸿蒙端主流交互)
在 FlatList 中添加swipeEnabled={true}和renderItem的滑动侧滑布局,实现「左滑显示删除按钮,点击删除后划线置灰」,这是鸿蒙端任务类 APP 的标准交互,体验远超点击删除。
✅ 扩展 2:任务完成 划线 + 打勾图标
在任务标题左侧添加<Icon>组件,任务完成后显示「对勾图标」+ 文字划线,视觉反馈更明显,鸿蒙端可使用 RN 原生的Ionicons图标库,无兼容问题。
✅ 扩展 3:划线效果 渐隐动画
结合 RN 的Animated组件,给任务完成后的opacity添加渐变动画,从 1→0.7 的过渡效果,让划线置灰更丝滑,贴合鸿蒙端的流畅交互体验。
✅ 扩展 4:批量完成 / 删除任务
在页面顶部添加「全选 / 批量完成 / 批量删除」按钮,点击后修改所有任务的isCompleted状态,实现批量划线置灰,适合多任务管理场景。
✅ 扩展 5:任务完成后 自动置顶 / 置底
修改 FlatList 的数据源排序逻辑,任务完成后自动将其移到列表底部(或顶部),未完成任务置顶显示,提升任务管理效率。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
更多推荐



所有评论(0)