mcpField
J
jaspr-fundamentals

jaspr-fundamentals

github.com/rodydavis开发82439 次安装12 周前更新
代码仓库

关于 jaspr-fundamentals

jaspr-fundamentals 是介绍 Jaspr 组件模型和核心界面开发实践的技能。它指导开发者处理组件状态、类型化 HTML 元素、浏览器 API 和事件。

主要功能

  1. 01无状态与有状态组件
  2. 02上下文与状态向下传递
  3. 03类型化 HTML 组件用法
  4. 04浏览器 API 与事件处理

适用场景

  1. 01组织 Jaspr 组件树
  2. 02实现可交互的 HTML 元素
  3. 03在不同渲染模式下访问浏览器 API

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/rodydavis/signals.dart --skill jaspr-fundamentals

安装后在 Claude Code 中输入/jaspr-fundamentals确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/html/
a.md
article.md
aside.md
audio.md
b.md
blockquote.md
body.md
br.md
button.md
caption.md
circle.md
code.md
col.md
colgroup.md
datalist.md
dd.md
details.md
dialog.md
div.md
dl.md
dt.md
ellipse.md
em.md
embed.md
fieldset.md
figcaption.md
figure.md
footer.md
form.md
h1.md

详细介绍

组件

Jaspr 采用基于组件的架构,与 Flutter 的 widget 非常相似。UI 组合、架构和状态管理等概念都可以迁移使用。

  • StatelessComponent:用于不需要可变状态的组件。必须重写 Component build(BuildContext context)。
  • StatefulComponent:用于具有可变状态的组件。需要关联一个 State 类。该状态类包含 initState() 和 dispose() 等生命周期方法。必须在状态类中重写 Component build(BuildContext context)。
  • InheritedComponent:用于在组件树中高效地向下传递上下文或状态。
从 build 返回组件

在 Jaspr 中构建 UI 时,必须从 build() 返回单个 Component。

  • **规则 1:**不得使用 Iterable<Component> build(BuildContext context) sync*。这是旧式代码。
  • **规则 2:**对于片段、文本和空节点,必须使用点简写,而不是首字母大写的组件名称。
    • 使用 .fragment([...])(不要使用 Fragment([...]) 或 fragment([...]))。
    • 使用 .text('...')(不要使用 Text('...') 或 text('...'))。
    • 使用 .empty() 安全地返回空白节点。

用法示例:

import 'package:jaspr/jaspr.dart';
import 'package:jaspr/dom.dart';

class MyComponent extends StatelessComponent {
  const MyComponent({super.key});

  @override
  Component build(BuildContext context) {
    // 1. Return a single component (e.g. div)
    // 2. Use dot-shorthand (.text) instead of Text()
    return div(classes: 'my-class', [
      .text('Hello World'),
    ]);
  }
}

HTML 组件

Jaspr 为标准 HTML 元素(例如 div()、p()、a()、button())提供了带类型的组件。要使用这些组件,请导入 package:jaspr/dom.dart。

所有 HTML 组件都接受标准的命名参数 Key? key、String? id、String? classes、Styles? style、Map<String, String>? attributes 和 Map<String, void Function(Event)>? events。 大多数 HTML 组件都接受位置参数 List<Component> children(自闭合标签除外,例如 img、input、br 等)。

  • **规则 1:**始终将 children 列表放在最后,在所有命名参数之后。
  • **规则 2:**必须优先使用可用的带类型参数(例如 href、src、onClick),而不是使用原始的 attributes: 或 events: 映射。
  • **规则 3:**如果不确定某个 HTML 组件有哪些带类型参数,必须阅读随此技能提供的对应参考文件:
    • references/html/<tag>.md 包含给定标签对应组件的完整签名和用法示例。(例如,div() 对应 references/html/div.md,button() 对应 references/html/button.md 等。)
  • **规则 4:**如果某个标签没有对应的参考文件(因此组件本身也不存在),必须改用通用 .element(tag: '...', /* other standard params, */ children: [ /* ... */ ]) 构造函数。

用法示例:

import 'package:jaspr/jaspr.dart';
import 'package:jaspr/dom.dart';

class MyHtmlComponent extends StatelessComponent {
  const MyHtmlComponent({super.key});

  @override
  Component build(BuildContext context) {
    return div(id: 'my-container', classes: 'my-class', [ 
      p(attributes: {'aria-label': 'Example Paragraph'}, [
        .text('Hello World'),
      ]),
      // E.g. signature as found at 'references/html/a.md'
      a(href: 'https://example.com', [
        .text('Click me'),
      ]),
    ]);
  }
}

设置组件样式

Jaspr 内置了使用 CSS-in-Dart 为组件设置样式的支持。 如需了解更多信息,请参阅 jaspr-styling 技能。

交互与事件

1. 访问浏览器 API
  • **规则 1:**在 server 或 static 模式下,必须使用 package:universal_web/web.dart 访问浏览器 API,并使用 package:universal_web/js_interop.dart 访问 js interop API。
  • **规则 2:**在 server 或 static 模式下使用 package:universal_web 时,必须将所有 API 调用放在 if (kIsWeb) 检查中,以防止服务端渲染崩溃。
  • **规则 3:**在 client 模式下,可以直接使用 dart:js_interop 和 package:web。
  • **规则 4:**对于全局事件,必须使用 web.EventStreamProviders 来监听 window 或 document 上的事件,因为它们会提供带类型的 Dart Stream 事件流。
// Example of safe usage in server/static mode:
import 'package:universal_web/web.dart' as web;

void logSize() {
  if (kIsWeb) {
    print('Window size: ${web.window.innerWidth}x${web.window.innerHeight}');

    // Example of global event listener
    final sub = web.EventStreamProviders.resizeEvent.forTarget(web.window).listen((event) {
      print('Window resized');
    });
  }
}
2. 处理事件

所有 DOM 组件都支持 events: 参数,交互式组件还提供带类型的事件回调(例如 onClick、onChange)。

  • **规则 1:**为原始事件指定类型时,必须使用 web.Event。
  • **规则 2:**需要时,使用 events() 助手函数创建类型安全的回调。
import 'package:jaspr/jaspr.dart';
import 'package:jaspr/dom.dart';
import 'package:universal_web/web.dart' as web;

class MyButton extends StatelessComponent {
  @override
  Component build(BuildContext context) {
    return div(
      // Using raw events
      events: {'click': (web.Event event) {
        print('Div clicked');
      }},
      [
        // Using typed parameters
        button(
          onClick: () => print('Button clicked'),
          [.text('Click me')]
        )
      ]
    );
  }
}
3. 访问元素(GlobalNodeKey)

如果需要直接引用 Jaspr 渲染的底层 DOM 元素,可以为其分配一个 GlobalNodeKey。

import 'package:jaspr/jaspr.dart';
import 'package:jaspr/dom.dart';
import 'package:universal_web/web.dart' as web;

class MyInput extends StatefulComponent {
  @override
  State<MyInput> createState() => _MyInputState();
}

class _MyInputState extends State<MyInput> {
  final GlobalNodeKey<web.HTMLInputElement> inputKey = GlobalNodeKey();

  void focusInput() {
    inputKey.currentNode?.focus();
  }

  @override
  Component build(BuildContext context) {
    return input(key: inputKey, type: .text);
  }
}

更多资源

评论

支持 Markdown