当前位置: 首页 > ds >正文

零构建的快感!dagger.js 与 React Hooks 实现对比,谁更优雅?

“Add Tags” 技术方案并行对比:React Hooks vs dagger.js(含核心 JS 代码)

源码:

  • React Hooks:https://codepen.io/prvnbist/pen/jJzROe?editors=1010
  • dagger.js:https://codepen.io/dagger8224/pen/ZErjzwm

在这里插入图片描述

一、对比总览(表格)

维度React Hooks 实现(prvnbist)dagger.js 实现(dagger8224)结论
框架/依赖依赖 React/ReactDOM + Babel/JSX;ReactDOM.render 挂载原生 DOM + 指令(+load/*each/*value#trim/+click/+keyup),零构建可跑dagger 依赖更轻;React 生态更全
状态管理useState(不可变更新)作用域对象可变更新(push/spliceReact 可预测性强;dagger 上手直观
事件/输入onKeyUp 手写回调读取/清空输入*value#trim 双向绑定,+keyup#every:-Enter 声明式触发dagger 更少样板
列表渲染/删除tags.map(...) + onClick*each="tags" + +click="removeTags(...)"均直观;dagger 更贴 HTML
对外通信props.selectedTags([...]) 向父级冒泡示例未展示(可拓展自定义事件/全局 store)React 更现成
A11y删除控件是 span“x”,无按钮角色/ARIA(两边均是)同左建议两者都改 <button aria-label="Remove tag">
性能(本例)VDOM diff 开销极小直达 DOM 绑定小组件差异可忽略
适用场景工程化/组件生态/团队协作免构建/轻量嵌入/快速原型视项目体量取舍

二、代码量差异(粗略非空行统计)

注:仅为量级参考;CSS 两边大致一致。

面板React Hooksdagger.js
HTML~1 行(<div id="root">~10 行(含指令模板)
JS~33 行(TagsInput + App + render~12 行(loading/removeTags/addTags
CSS~80+ 行(两者近似)~80+ 行
合计(HTML+JS)~34 行~22 行

结论:dagger.js 显著减少 JS 体量,把交互“下沉”到 HTML 指令;React JS 更多但 HTML 更薄,符合组件化/状态提升的常规模式。


三、核心 JS 代码对照

1) React Hooks(核心 JS)

const TagsInput = props => {const [tags, setTags] = React.useState(props.tags);const removeTags = indexToRemove => {setTags([...tags.filter((_, index) => index !== indexToRemove)]);};const addTags = event => {if (event.target.value !== "") {setTags([...tags, event.target.value]);props.selectedTags([...tags, event.target.value]);event.target.value = "";}};return (<div className="tags-input"><ul id="tags">{tags.map((tag, index) => (<li key={index} className="tag"><span className='tag-title'>{tag}</span><span className='tag-close-icon'onClick={() => removeTags(index)}>x</span></li>))}</ul><inputtype="text"onKeyUp={event => event.key === "Enter" ? addTags(event) : null}placeholder="Press enter to add tags"/></div>);
};
const App = () => {const selectedTags = tags => {console.log(tags);};return (<div className="App"><TagsInput selectedTags={selectedTags}  tags={['Nodejs', 'MongoDB']}/></div>);
};
ReactDOM.render(<App />, document.getElementById("root"));

2) dagger.js(核心 JS)

const loading = () => ({tag: '',tags: ['Nodejs', 'MongoDB']
});
const removeTags = (index, tags) => tags.splice(index, 1);
const addTags = $scope => {const { tag, tags } = $scope;if (tag) {tags.push(tag);$scope.tag = '';}
};

dagger 对应模板(片段),可见通过指令表达列表、事件与双向绑定:

<div dg-cloak class="App" +load="loading()"><div class="tags-input"><ul id="tags"><li class="tag" *each="tags"><span class='tag-title'>${ item }</span><span class='tag-close-icon' +click="removeTags(index, tags)">x</span></li></ul><input type="text" placeholder="Press enter to add tags"*value#trim="tag" +keyup#every:-Enter="addTags($scope)"></div>
</div>

四、与代码对应的实现分析

A. 初始化与挂载

  • Reactconst [tags, setTags] = useState(props.tags); 为局部状态;通过 ReactDOM.render(<App/>, #root) 挂载。组件化边界清晰,便于复用与组合。
  • dagger+load="loading()" 在容器上注入初始作用域(tag/tags),无需显式渲染入口,适合在任意静态页“就地”增强。

B. 输入与校验

  • ReactaddTags(event) 里手动读取/清空 event.target.value;默认不 trim,可在函数中补充校验与去重。
  • dagger*value#trim="tag" 天然裁剪空白,结合 +keyup#every:-Enter 让“回车新增”无需手写键值判断。

C. 列表渲染与删除

  • Reacttags.map(...) 渲染项,onClick={() => removeTags(index)} 删除。不可变更新(filter)便于可预测渲染、状态回溯。
  • dagger*each="tags" 迭代;+click="removeTags(index, tags)" 直接调用,常配合可变更新(splice)写法简洁。

D. 对外通信

  • Reactprops.selectedTags([...]) 将内部变更上报给父组件或外层应用(常见于表单控件封装)。
  • dagger:示例未展示;可通过自定义事件(dispatchEvent)或外层监听指令来完成数据冒泡。

E. 可访问性(A11y)

  • 两边删除控件均为 span,建议替换为:
    <button type="button" class="tag-close-icon" aria-label="Remove tag">x</button>
    
    并配合键盘支持(Enter/Space)和更明确的焦点样式。

五、改进建议(两边通用)

  • 输入规则:去重、最大标签数、禁止全空白;支持粘贴多标签(按逗号/空格分割)。
  • 错误反馈:同名标签时给出可视化提示(如 shake 动画/辅助文本)。
  • 测试:React 侧可配合 Testing Library;dagger 侧可通过 DOM 测试/端到端测试保障交互。
  • 样式与主题:抽离 tokens/vars,支持暗色模式与尺寸变体。

六、选型参考

  • 需要工程化、强生态、多人协作 —— 倾向 React:组件化边界清晰、工具链与第三方库成熟。
  • 追求零构建、轻量嵌入、快速上线 —— 倾向 dagger:指令式绑定 + 原生 DOM,代码量更小,上手极快。

本文内容就到这里,后续文章将为大家带来更多案例和讲解。

如果对dagger.js感兴趣的话,请您点赞收藏、分享本系列文章,也欢迎留言或者私信作者提出问题和建议,您的关注是对我最大的支持和鼓励。感谢您的阅读,祝工作学习顺利!

http://www.xdnf.cn/news/19885.html

相关文章:

  • Python OpenCV图像处理与深度学习:Python OpenCV DNN模块深度学习与图像处理
  • 线程安全问题及解决方案
  • 163起融资,梅卡曼德融资额夺冠,钉钉、百度智能云10周年,汉桑科技IPO| 2025年8月人工智能投融资观察 · 极新月报
  • Android --- 搭建JNI框架
  • % g++ *.cpp ...: fatal error: ‘opencv2/opencv.hpp‘ file not found 1
  • 数论常见公式定理大全
  • 无需服务器,免费、快捷的一键部署前端 vue React代码--PinMe
  • 嵌入式学习 51单片机基础
  • 《微服务协作实战指南:构建全链路稳健性的防御体系》
  • AR技术赋能风电运维:精准、高效、智能
  • 算法模板(Java版)_非负整数的高精度运算
  • 【论文阅读】Jet-Nemotron: 高效语言模型与后神经网络架构搜索
  • 研发团队缺乏统一文档模板怎么办
  • 服务器的监控和管理手段有哪些?
  • 【LeetCode牛客数据结构】单链表的应用——环形链表及链表分割问题详解
  • 【Python3教程】Python3高级篇之多线程
  • Chrome浏览器调用ActiveX控件之allWebOffice在线编辑控件
  • 记录收入最高的一次私活 选号网,需要大量卖号的人可能需要,比如游戏脚本批量跑的号
  • 电脑配置不足怎么办,告别硬件束缚,川翔云电脑
  • 从Oracle到PostgreSQL的数据库迁移
  • MySQL中binlog、redolog与undolog的不同之处解析
  • 传统大数据 Hadoop 和 云原生湖仓 Databend 对比
  • Spring MVC + JSP 项目的配置流程,适合传统 Java Web 项目开发
  • LangGraph 重要注意事项和常见问题
  • 猫头虎AI分享:无需OCR,基于ColQwen2、Qwen2.5和Weaviate对PDF进行多模态RAG的解决方案
  • 基于STM32的居家养老健康安全检测系统
  • 中文分词器之结巴分词
  • GPT-Realtime 弹幕TTS API 低延迟集成教程
  • leetcode111. 二叉树的最小深度
  • 2025华为最值得入的耳机,真的赢麻了!