普通视图

发现新文章,点击刷新页面。
昨天 — 2025年11月20日首页

CSS 相对颜色:告别 180 个颜色变量的设计系统噩梦

作者 大知闲闲i
2025年11月19日 15:51

当组件库中的颜色变量达到 180 个时,一次品牌色变更就成了前端开发的噩梦。CSS 相对颜色语法将彻底改变这一现状。

一个让人沉默的现实

最近在排查一个组件库的主题 BUG 时,我们发现了令人震惊的事实:这个看似成熟的设计系统中,竟然定义了 180 个颜色变量

更可怕的是,每次品牌主色调整,都需要在 3 个不同的文件中同步修改 15 种深浅变化、hover 状态、透明度变体……设计同学轻描淡写的一句"主色想从偏蓝调成更紫一点",意味着工程侧需要:

  • 手动修改 15+ 个变量

  • 反复对比 hover、active 状态是否协调

  • 仔细检查半透明背景是否漏改

  • 确保整个颜色体系保持和谐

漏改一个变量,hover 状态显得怪异;漏改两个,整套主题就开始"发脏"。

传统颜色系统的困境

当前绝大多数设计系统的配色方案可以概括为:靠人肉复制的"颜色农场"

:root {
  /* 主色系 */
  --color-primary: #3b82f6;
  --color-primary-hover: #2563eb;
  --color-primary-active: #1d4ed8;
  --color-primary-light: #93c5fd;
  --color-primary-dark: #1e40af;
  
  /* 辅助色系 */
  --color-secondary: #8b5cf6;
  --color-secondary-hover: #7c3aed;
  --color-secondary-active: #6d28d9;
  
  /* 继续衍生... */
}

这种模式的痛点显而易见:

  • 维护成本高:一个主色系需要十几二十个变量

  • 同步困难:多处定义的变量容易遗漏

  • 不可靠:手动调色依赖个人感觉,缺乏系统性

CSS 相对颜色:革命性的解决方案

CSS 相对颜色语法引入的 from 关键字,让颜色从"死值"变成"活公式"。

基础语法

color-function(from origin-color channel1 channel2 channel3 / alpha)

拆解说明:

  • color-function:输出格式,如 rgb()hsl()oklch()

  • from:关键字符,声明颜色来源

  • origin-color:基准颜色,支持 hex、RGB、HSL 等格式

  • channel1 ~ 3:可访问和修改的通道值

  • alpha:可选透明度通道

实际应用示例

:root {
  --primary: #3b82f6;
}

.button {
  background: var(--primary);
}

.button:hover {
  /* 基于主色自动计算 hover 状态 */
  background: hsl(from var(--primary) h s calc(l - 10));
}

这一行 hsl(from ...) 的改变,将 hover 效果从"写死"变成了"相对基色、自动联动"。从此,品牌色只需修改一个 --primary 变量,所有衍生状态自动跟随。

from 关键字的魔力

from 的核心作用是将颜色分解为通道值,让我们能够像搭乐高一样重新组合:

/* 将绿色分解为 RGB 通道 */
rgb(from green r g b)  /* 输出: rgb(0 128 0) */

/* 用绿色通道创建灰度 */
rgb(from green g g g)  /* 输出: rgb(128 128 128) */

/* 随意调换通道顺序 */
rgb(from green b r g)  /* 输出: rgb(0 0 128) */

跨色彩空间转换

from 自动处理色彩空间转换,让颜色格式不再成为障碍:

/* RGB 转 HSL */
hsl(from rgb(255 0 0) h s l)

/* Hex 转 OKLCH */
oklch(from #3b82f6 l c h)

这对设计系统意义重大:源头存储格式不再重要,使用端始终使用统一的可计算空间。

calc():颜色计算的引擎

真正的威力在于将 calc() 与颜色通道结合:

/* 变亮:提高亮度 */
hsl(from blue h s calc(l + 20))

/* 变暗:降低亮度 */  
hsl(from blue h s calc(l - 20))

/* 半透明:调整透明度 */
rgb(from blue r g b / calc(alpha * 0.5))

/* 调色:旋转色相 */
hsl(from blue calc(h + 180) s l)

大部分颜色衍生逻辑都可以归结为:通道 + 偏移量通道 × 系数

OKLCH:更智能的色彩空间

虽然 HSL 很流行,但它有个致命缺陷:亮度感知不均

hsl(220 80% 50%)  /* 蓝色 */
hsl(120 80% 50%)  /* 绿色 */

理论上两者亮度相同,但人眼感知中绿色明显更亮。OKLCH 解决了这个问题:

  • L(Lightness):0-1,感知亮度,更符合人眼

  • C(Chroma):0-约0.37,颜色纯度

  • H(Hue):0-360,色相角度

    oklch(0.55 0.15 260) /* 蓝色 / oklch(0.55 0.15 140) / 绿色 */

在 OKLCH 中,相同的 L 值在不同色相间具有一致的亮度感知,这让程序化调色更加可靠。

构建智能颜色系统

第一步:定义品牌基色

:root {
  /* 只用定义 4 个基础品牌色 */
  --brand-primary: oklch(0.55 0.2 265);
  --brand-success: oklch(0.65 0.18 145);
  --brand-error: oklch(0.6 0.25 25);
  --brand-warning: oklch(0.75 0.15 85);
}

第二步:按规则生成完整色板

:root {
  /* Primary 色系 - 全部从基色派生 */
  --primary: var(--brand-primary);
  --primary-hover: oklch(from var(--brand-primary) calc(l - 0.1) c h);
  --primary-active: oklch(from var(--brand-primary) calc(l - 0.15) c h);
  --primary-light: oklch(from var(--brand-primary) calc(l + 0.2) calc(c * 0.5) h);
  --primary-lighter: oklch(from var(--brand-primary) calc(l + 0.3) calc(c * 0.3) h);
  --primary-alpha-10: oklch(from var(--brand-primary) l c h / 0.1);
  --primary-alpha-20: oklch(from var(--brand-primary) l c h / 0.2);
  
  /* 其他色系采用相同模式 */
  --success: var(--brand-success);
  --success-hover: oklch(from var(--brand-success) calc(l - 0.1) c h);
  --success-light: oklch(from var(--brand-success) calc(l + 0.2) calc(c * 0.5) h);
}

四个基色变量,扩展出完整的颜色体系。品牌色调整时,只需修改四个基础值。

暗色模式的革命

传统暗色模式需要维护两套 token,现在只需一个公式:

:root {
  --surface: oklch(0.98 0.02 240);
  --text: oklch(0.25 0.03 240);
}

[data-theme="dark"] {
  /* 亮度反转实现暗色模式 */
  --surface: oklch(from var(--surface) calc(1 - l) c h);
  --text: oklch(from var(--text) calc(1 - l) c h);
}

实战高级技巧

1. 智能阴影系统

.card {
  --card-bg: var(--primary);
  background: var(--card-bg);
  box-shadow: 
    0 4px 6px oklch(from var(--card-bg) l c h / 0.2),
    0 10px 15px oklch(from var(--card-bg) l c h / 0.15);
}

阴影自动适应背景色,主题切换时自然过渡。

2. 确保可读性的文本颜色

.tag {
  --tag-bg: var(--primary);
  background: var(--tag-bg);
  /* 文本亮度比背景高 0.6,确保对比度 */
  color: oklch(from var(--tag-bg) calc(l + 0.6) c h);
}

3. 品牌化半透明遮罩

.modal-backdrop {
  background: oklch(from var(--brand-primary) l c h / 0.7);
}

浏览器支持与渐进增强

截至 2025 年,相对颜色已获得良好支持:

  • Chrome 119+ ✅

  • Firefox 128+ ✅

  • Safari 16.4+ ✅

  • Edge 119+ ✅

覆盖率约 83%,对于不支持的环境可提供静态回退:

.button {
  background: #2563eb; /* 回退值 */
  background: oklch(from var(--primary) calc(l - 0.1) c h);
}

避坑指南

  1. 避免过深派生链:从基色直接推导,最多两层

  2. 控制 Chroma 范围:OKLCH 中 Chroma 超过 0.37 可能导致颜色溢出

  3. 正确使用 Alphaoklch(0.6 0.2 265 / 0.5) 而非 oklch(0.6 0.2 265 0.5)

总结:从小升级到大变革

CSS 相对颜色解决的不仅是技术问题,更是设计系统维护的哲学变革:

  • 主题切换不再是灾难:改一个变量,全站自洽

  • 颜色 Token 真正集中管理:从分散定义到统一源头

  • 设计规则化:深浅、状态、透明度都成为可复用的公式

  • 开发体验提升:从机械调色到智能推导

下一次重构配色系统时,不妨尝试将基准色、状态色、暗色模式、半透明层全部交给相对颜色计算。那种"改一处,全局联动"的流畅体验,确实让人上头。

从 180 个颜色变量到 4 个基色变量,这不只是数量的减少,更是设计系统维护理念的质的飞跃。

前端工程化核心知识全面解析

作者 大知闲闲i
2025年11月20日 11:17

一、构建工具演进:从任务执行到模块化打包

Grunt、Gulp:基于任务运行的工具

Grunt 和 Gulp 是前端工程化早期的代表性工具,它们的工作方式类似于工厂流水线:

  • 自动化任务执行:通过配置一系列任务,自动完成代码检查、编译、压缩等操作

  • 丰富的插件生态:拥有活跃的社区支持,提供大量功能插件

  • 灵活的工作流:可以按照需求定制完整的开发工作流程

Webpack:基于模块化打包的工具

Webpack 代表了新一代构建工具的思想转变:

  • 一切皆模块:将项目中的所有资源(JS、CSS、图片等)都视为模块

  • 依赖关系管理:递归构建依赖关系图,确保模块间的正确引用

  • 打包优化:将所有模块打包成少数几个 bundle 文件,优化加载性能

现代替代方案:npm script

随着技术的发展,现在更推荐使用 npm script 来替代传统的任务运行器:

{
  "scripts": {
    "build": "webpack --mode production",
    "dev": "webpack serve --mode development",
    "lint": "eslint src/"
  }
}

二、主流打包工具对比选型

Webpack:复杂应用的优选

优势特点:

  • 功能全面,支持代码分割、懒加载等高级特性

  • 生态丰富,拥有大量 loader 和 plugin

  • 适合大型复杂的前端项目

适用场景: 企业级应用、单页面应用(SPA)、需要复杂构建流程的项目

Rollup:库开发的利器

优势特点:

  • Tree-shaking 效果出色,打包体积小

  • 配置简单,专注于 ES6 模块打包

  • 输出格式多样(ESM、CJS、UMD 等)

适用场景: Vue、React 等开源库、工具库、组件库开发

Parcel:快速原型开发

优势特点:

  • 零配置开箱即用

  • 构建速度快

  • 适合初学者

适用场景: demo 项目、实验性项目、快速原型开发

三、Webpack 核心概念深入理解

常用 Loader 详解

Loader 就像是 Webpack 的"翻译官",负责处理各种类型的文件:

Loader 名称

主要功能

使用场景

babel-loader

ES6+ 转 ES5

现代 JavaScript 兼容

css-loader

解析 CSS 文件

CSS 模块化处理

style-loader

注入 CSS 到 DOM

开发环境样式热更新

file-loader

处理文件资源

图片、字体等静态资源

url-loader

小文件转 base64

优化小资源加载

重要特性: Loader 执行顺序为从右向左,符合函数式编程的 compose 理念。

常用 Plugin 功能解析

Plugin 赋予 Webpack 更强大的扩展能力:

  • DefinePlugin:定义全局常量,常用于环境变量配置

  • HtmlWebpackPlugin:自动生成 HTML 文件并注入资源引用

  • MiniCssExtractPlugin:提取 CSS 到独立文件,支持生产环境优化

  • WebpackBundleAnalyzer:可视化分析打包体积,助力性能优化

核心概念区分

  • Module:开发中的单个模块,对应源代码文件

  • Chunk:代码块,由多个模块组成

  • Bundle:最终的输出文件,可能包含多个 Chunk

四、Loader 与 Plugin 深度对比

对比维度

Loader

Plugin

作用范围

模块级别,处理单个文件

整个构建过程

配置位置

module.rules 数组

plugins 数组

本质功能

文件转换器

生命周期钩子监听器

执行时机

模块加载阶段

整个编译周期

五、热更新机制原理剖析

Webpack Hot Module Replacement (HMR) 是现代开发体验的重要保障:

工作流程

  1. 文件监控:Webpack 在 watch 模式下监控文件变化

  2. 内存编译:将重新编译的代码保存在内存中

  3. 消息推送:通过 WebSocket 向客户端推送更新信息

  4. 模块替换:客户端动态替换变更模块,保持应用状态

核心优势

  • 保持应用状态不丢失

  • 大幅提升开发效率

  • 支持样式、组件等粒度的热更新

六、Babel 编译原理探秘

Babel 的转译过程分为三个精密阶段:

1. 解析阶段(Parse)

// 源代码
const sum = (a, b) => a + b;

// 转换为 AST
{
  type: "VariableDeclaration",
  declarations: [
    {
      type: "VariableDeclarator",
      id: { type: "Identifier", name: "sum" },
      init: {
        type: "ArrowFunctionExpression",
        params: [...],
        body: {...}
      }
    }
  ]
}

2. 转换阶段(Transform)

遍历 AST,应用各种插件进行语法转换:

  • 箭头函数转普通函数

  • const/let 转 var

  • 类语法转换等

3. 生成阶段(Generate)

将转换后的 AST 重新生成目标代码。

七、版本控制系统深度对比

Git vs SVN 架构差异

特性对比

Git(分布式)

SVN(集中式)

存储方式

元数据存储,完整版本历史

文件存储,增量记录

网络需求

支持完全离线操作

必须连接服务器

分支管理

轻量级分支,快速切换

目录拷贝,开销较大

数据安全

SHA-1 哈希保证完整性

相对较弱

Git 的核心优势

  1. 性能卓越:本地操作,速度极快

  2. 分支灵活:创建、合并分支几乎无成本

  3. 数据可靠:完整的版本历史和内容校验

八、Git 常用命令手册

基础操作命令

# 仓库初始化
git init
git clone <url>

# 提交变更
git add .
git commit -m "commit message"

# 状态查看
git status
git diff
git log --oneline

分支管理

# 分支操作
git branch feature-xxx
git checkout feature-xxx
git merge main
git branch -d feature-xxx

远程协作

# 远程仓库
git remote add origin <url>
git push -u origin main
git pull origin main

九、Git 高级操作解析

git fetch vs git pull

# 安全更新:只下载不合并
git fetch origin

# 快捷更新:下载并合并
git pull origin main

最佳实践:推荐先 git fetch 查看变更,再决定是否合并。

git rebase vs git merge

操作方式

提交历史

适用场景

merge

保留完整合并历史

团队协作,公共分支

rebase

线性整洁的历史

个人特性分支

rebase 使用注意

# 正确的 rebase 流程
git checkout feature-branch
git rebase main
git checkout main
git merge feature-branch

重要原则:不要在公共分支上执行 rebase 操作!

总结

前端工程化是一个不断演进的技术领域,从早期的任务运行器到现代的模块化打包工具,从集中式版本控制到分布式协作开发,每一次技术变革都带来了开发效率和项目质量的显著提升。掌握这些核心知识,能够帮助我们在实际项目中做出更合理的技术选型,构建更健壮的前端应用架构。

随着技术的不断发展,前端工程化将继续向着更智能、更高效的方向演进,但扎实的基础知识和核心原理将始终是我们应对技术变化的坚实基础。

昨天以前首页

这个前端工具杀疯了!发布一周狂揽 10k Star,Snapchat 开源框架重新定义跨平台

作者 大知闲闲i
2025年11月18日 14:12

跨平台开发的战场,看似格局已定,实则暗流涌动。就在大家以为创新乏力之时,Snapchat 突然抛出一枚“重磅炸弹”——开源其内部框架 Valdi,瞬间点燃了整个前端圈。

这个横空出世的框架,仅用一周时间就在 GitHub 上狂揽 10k Star,它究竟有何魔力?答案在于:它选择了一条与所有主流方案都背道而驰的道路。

当其他框架还在纠结如何优化 WebView 或精简 Electron 时,Valdi 直接颠覆了游戏规则:让你用熟悉的前端语法编写界面,最终呈现的却是纯粹的原生组件。

技术革新:前端思维,原生性能

Valdi 的核心思路堪称“工程师的浪漫”:保留开发者友好的 UI 语法,同时直通原生渲染的性能巅峰。

具体来说:

  • 你用 TSX 编写界面逻辑

  • 但渲染层完全绕过 Web 技术

  • C++ 原生引擎直接接管视图渲染

  • 无需浏览器、无需 JavaScript Core、无需桥接损耗

这种架构带来的性能提升是惊人的:iOS demo 中状态切换仅需 2ms,几乎感知不到任何掉帧。

为什么开发者如此狂热?

三大关键因素引爆关注:

  1. 极低的学习门槛

    • 无需掌握 Swift/Kotlin

    • 不用深入理解原生渲染管线

    • TS + JSX 的技能直接迁移

  2. Snapchat 的技术背书

    • Snap 在图形渲染领域积累深厚

    • 经过内部大规模应用验证

    • 开源即成熟

  3. 精准命中行业痛点

    • 解决了 WebView 的性能瓶颈

    • 平衡了开发效率与运行性能

跨平台方案对比:Valdi 的独特定位

与 Electron、Tauri 相比,Valdi 选择了完全不同的技术路径:

  • Electron:Web 技术套壳,体验一致但资源消耗大

  • Tauri:轻量 WebView + Rust 后端,平衡性能与体积

  • Valdi:前端语法 → 原生渲染,追求极致性能

如果说跨平台发展分为三代:

  • 第一代:Web 套壳(Electron)

  • 第二代:轻量 WebView + 系统集成(Tauri)

  • 第三代:前端语法 + 原生渲染(Valdi)

Valdi 无疑代表着最新的技术演进方向。

适用场景分析

✅ 推荐使用:

  • 前端背景的移动端开发新手

  • 动画交互密集的复杂界面

  • 追求 TS 代码多端复用的团队

❌ 暂不推荐:

  • 依赖丰富插件生态的项目

  • 纯桌面端应用开发

  • 重度依赖现有 Web UI 库

需要注意的是,Valdi 目前仍处于 beta 阶段,生态建设尚需时日。

结语:重新想象跨平台开发

Valdi 的迅速走红,并非因为它已经完美无缺,而是它回答了一个让无数开发者魂牵梦绕的问题:

我们能否只用 TypeScript,就打造出原生性能的应用程序?

这个愿景一旦被提出,就再也无法被忽视。无论 Valdi 最终能否成为主流,它已经为跨平台开发赛道注入了新的活力,让我们看到了更多可能性。

在这个技术快速迭代的时代,最好的方案永远在下一个。Valdi 的出现,或许正是跨平台开发新一轮变革的起点。

关于前端基础快速跨入鸿蒙HarmonyOS开发

作者 大知闲闲i
2025年11月17日 10:55

1、HarmonyOS简介

HarmonyOS(华为鸿蒙系统)是一款面向全场景的分布式操作系统。它在传统单设备系统能力基础上,提出了基于同一套系统能力、适配多种终端形态的分布式理念。

支持设备类型:

  • 移动设备:智能手机、平板电脑

  • 智能家居:智能家电、智能音响、智能门锁

  • 智能穿戴:智能手表、智能手环

  • 车载系统:车载娱乐、车载导航

  • 工业控制:工业自动化、机器人控制

2、ArkTS语言

HarmonyOS 4.0+ 支持两种开发技术:

  • ArkTS(推荐)

  • HTML + CSS + JavaScript

语言演进:

JavaScriptTypeScriptArkTS (extend TypeScript)

ArkTS在TypeScript基础上,对动态类型特性施加更严格约束,引入静态类型,提供声明式UI、状态管理等能力。

3、ArkTS项目结构

3.1、项目目录

项目根目录/
├── entry/
│   └── src/
│       ├── main/
│       │   ├── ets/           # 代码文件
│       │   ├── resources/     # 资源文件
│       │   └── module.json5   # 配置文件

3.2、基本组成要素

@Entry
@Component
struct MyComponent {
  @State message: string = 'Hello World'

  build() {
    Column() {
      Text(this.message)
        .fontSize(50)
        .fontWeight(FontWeight.Bold)
    }
    .width('100%')
    .height('100%')
  }
}

核心概念:

  • 装饰器:@Component、@Entry、@State等

  • UI描述:build()方法中的声明式UI

  • 自定义组件:可复用的UI单元

  • 系统组件:框架内置的基础组件

  • 属性方法:链式调用配置属性

  • 事件方法:设置事件响应逻辑

4、组件体系

组件是界面搭建的最小单位,分为五大类:

5、生命周期管理

5.1、应用生命周期

// src/main/ets/entryability/EntryAbility.ts
export default class EntryAbility extends UIAbility {
  onCreate(want, launchParam) {
    // 应用创建时调用
  }
  
  onForeground() {
    // 应用进入前台时调用
  }
  
  onBackground() {
    // 应用进入后台时调用
  }
  
  onWindowStageCreate() {
    // UIAbility实例创建时调用
  }
  
  onWindowStageDestroy() {
    // UIAbility实例销毁前调用
  }
  
  onDestroy() {
    // 应用销毁时调用
  }
}

5.2、页面生命周期

typescript

@Entry
@Component
struct MyPage {
  onPageShow() {
    // 页面每次显示时触发
  }
  
  onPageHide() {
    // 页面每次隐藏时触发
  }
  
  onBackPress() {
    // 点击返回按钮时触发
  }
}

5.3、组件生命周期

@Component
struct MyComponent {
  aboutToAppear() {
    // 组件创建后、build()执行前调用
  }
  
  aboutToDisappear() {
    // 组件销毁前调用
  }
}

6、条件渲染

@Entry
@Component
struct ConditionalRender {
  @State isStudy: boolean = false

  build() {
    Column() {
      Button('切换状态')
        .fontSize(50)
        .margin({ top: 20 })
        .onClick(() => {
          this.isStudy = !this.isStudy
        })
      
      if (this.isStudy) {
        Image($r("app.media.study_icon"))
          .width(28)
          .height(28)
      } else {
        Image($r("app.media.rest_icon"))
          .width(28)
          .height(28)
      }
    }
    .width('100%')
  }
}

7、列表渲染

@Entry
@Component
struct ListRender {
  @State list: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9]

  build() {
    Column() {
      List({ space: 10 }) {
        ForEach(this.list, (item: number) => {
          ListItem() {
            Text(`${item}`)
              .textAlign(TextAlign.Center)
              .width('100%')
              .height(50)
              .fontSize(20)
          }
        })
      }
      .padding(10)
      .divider({
        strokeWidth: 2,
        color: Color.Red
      })
    }
    .width('100%')
    .height('100%')
  }
}

8、Image图片组件

8.1、网络图片

Image('https://example.com/image.png')
  .width(100)
  .height(100)

权限配置:

{
  "requestPermissions": [
    {
      "name": "ohos.permission.INTERNET"
    }
  ]
}

8.2、本地图片

Image("/images/local.jpg")
  .width(100)
  .height(100)

8.3、Resource资源

// media资源
Image($r('app.media.icon'))
  .width(100)
  .height(100)

// rawfile资源
Image($rawfile('icon.png'))
  .width(100)
  .height(100)

// Base64
Image("data:image/png;base64,[base64 data]")
  .width(100)
  .height(100)

9、页面路由

9.1、基本路由跳转

import router from '@ohos.router';

// 跳转页面(保留当前页)
Button("跳转到首页")
  .onClick(() => {
    router.pushUrl({
      url: 'pages/index'
    })
  })

// 跳转页面(替换当前页)
Button("替换当前页")
  .onClick(() => {
    router.replaceUrl({
      url: 'pages/index'
    })
  })

9.2、路由传参

// 发送参数
Button("跳转到详情页")
  .onClick(() => {
    router.pushUrl({
      url: 'pages/detail',
      params: {
        id: 123,
        title: '文章标题'
      }
    })
  })

// 接收参数
@Component
struct DetailPage {
  aboutToAppear() {
    const params = router.getParams();
    const id = params['id'];
    const title = params['title'];
  }
}

9.3、页面返回

// 返回上一页
router.back();

// 返回到指定页面
router.back({ url: 'pages/Home' });

// 返回并传递参数
router.back({ 
  url: 'pages/Home', 
  params: { 
    message: '来自详情页的数据'
  }
});

// 接收返回参数
onPageShow() {
  const params = router.getParams();
  const message = params['message'];
}

9.4、返回确认对话框

function onBackClick(): void {
  try {
    router.showAlertBeforeBackPage({
      message: '确定要返回吗?未保存的数据将会丢失。'
    });
  } catch (err) {
    console.error(`显示返回确认框失败: ${err.message}`);
  }
  
  router.back();
}

10、自定义组件

10.1、基本结构

@Component
struct MyComponent {
  build() {
    // UI描述
  }
}

10.2、参数传递

@Component
struct ChildComponent {
  private title: string = '默认标题';
  private count: number = 0;

  build() {
    Text(this.title)
      .fontSize(20)
  }
}

@Entry
@Component
struct ParentComponent {
  build() {
    Column() {
      // 传递参数给子组件
      ChildComponent({ title: '自定义标题', count: 10 })
    }
  }
}

10.3、完整示例

@Entry
@Component
struct PoemApp {
  @State message: string = '诗词学习'

  build() {
    Column() {
      Text(this.message)
        .fontSize(50)
        .fontWeight(FontWeight.Bold)

      // 使用自定义组件
      PoemItem()
      PoemItem({ content: '二十四桥明月夜,玉人何处教吹箫?' })
      PoemItem({ content: '荷尽已无擎雨盖,菊残犹有傲霜枝。' })
      PoemItem({ content: '一年好景君须记,最是橙黄橘绿时。' })
    }
    .width('100%')
    .height('100%')
  }
}

@Component
struct PoemItem {
  // 组件参数
  content: string = '青山隐隐水迢迢,秋尽江南草未凋。'
  
  // 状态变量
  @State isDone: boolean = false

  build() {
    Row() {
      // 条件渲染图标
      Image(this.isDone ? $r('app.media.todo_ok') : $r('app.media.todo_default'))
        .width(20)
        .height(20)
        .margin(15)
      
      // 文本内容
      Text(this.content)
        .decoration({ 
          type: this.isDone ? TextDecorationType.LineThrough : TextDecorationType.None 
        })
    }
    .backgroundColor(Color.Pink)
    .borderRadius(25)
    .margin({ top: 15 })
    .onClick(() => {
      // 状态更新驱动UI刷新
      this.isDone = !this.isDone
    })
  }
}

总结

本文涵盖了HarmonyOS应用开发的核心概念:

  • ArkTS语言基础与项目结构

  • 组件化开发思想

  • 完整的生命周期管理

  • 条件渲染与列表渲染

  • 多种图片资源的使用

  • 页面路由与导航

  • 自定义组件开发

通过这些基础知识的学习,有前端基础的开发者可以快速上手HarmonyOS应用开发,构建丰富的跨设备应用体验。

❌
❌