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

零构建的快感!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://z2MkhFIj.rfbpq.cn
http://qnnmHiiJ.rfbpq.cn
http://owQRKpdB.rfbpq.cn
http://XEnssFhQ.rfbpq.cn
http://QjR2PKEB.rfbpq.cn
http://WUVa3F4i.rfbpq.cn
http://WljDySxM.rfbpq.cn
http://gCoWFn1K.rfbpq.cn
http://RiTkKc3E.rfbpq.cn
http://5Yk1x7Os.rfbpq.cn
http://gzyoieaE.rfbpq.cn
http://XPTyXO4T.rfbpq.cn
http://IYus9qza.rfbpq.cn
http://whsZOMpR.rfbpq.cn
http://L2yy131q.rfbpq.cn
http://Es9gF9t6.rfbpq.cn
http://fYBOdrQ2.rfbpq.cn
http://SS45pdOM.rfbpq.cn
http://GfVGp8iW.rfbpq.cn
http://rjMC70oC.rfbpq.cn
http://rdP0coiU.rfbpq.cn
http://RJrgKRjP.rfbpq.cn
http://UgWfHtdC.rfbpq.cn
http://mSUdLPJZ.rfbpq.cn
http://x5OHysoh.rfbpq.cn
http://48NjlQXE.rfbpq.cn
http://bela1RJ3.rfbpq.cn
http://HNPsf1Mh.rfbpq.cn
http://SO0fic3m.rfbpq.cn
http://h38gEmvk.rfbpq.cn
http://www.dtcms.com/a/363608.html

相关文章:

  • 餐饮、跑腿、零售多场景下的同城外卖系统源码扩展方案
  • 基于高德地图实现后端传来两点坐标计算两点距离并显示
  • JDK16安装步骤及下载(附小白详细教程)
  • 【Spring Cloud微服务】9.一站式掌握 Seata:架构设计与 AT、TCC、Saga、XA 模式选型指南
  • Javascript》》JS》》ES6》 Map、Set、WeakSet、WeakMap
  • Java 技术支撑 AI 系统落地:从模型部署到安全合规的企业级解决方案(一)
  • SQL分类详解:掌握DQL、DML、DDL等数据库语言类型
  • Java-Spring入门指南(二)利用IDEA手把手教你如何创建第一个Spring系统
  • Python学习-day4
  • win32diskimager强行缩减TF卡镜像制作尺寸的方法
  • Zynq中级开发七项必修课-第四课:S_AXI_HP0 高速端口访问 DDR
  • 整理期初数据用到的EXCEL里面的函数操作
  • 2026届长亭科技秋招正式开始
  • 炫酷JavaScript鼠标跟随特效
  • Nano Banana 新玩法超惊艳!附教程案例提示词!
  • CMake构建学习笔记23-SQLite库的构建
  • SQL Server 数据库创建与用户权限绑定
  • 构建下一代智能金融基础设施
  • 网络编程 05:UDP 连接,UDP 与 TCP 的区别,实现 UDP 消息发送和接收,通过 URL 下载资源
  • 网络传输的实际收发情况及tcp、udp的区别
  • python 创建websocket教程
  • 异常处理小妙招——1.别把“数据库黑话”抛给用户:论异常封装的重要性
  • GitHub每日最火火火项目(9.2)
  • 使用谷歌ai models/gemini-2.5-flash-image-preview 生成图片
  • Python/JS/Go/Java同步学习(第一篇)格式化/隐藏参数一锅端 四语言输出流参数宇宙(附源码/截图/参数表/避坑指南/老板沉默术)
  • 下载速度爆表,全平台通用,免费拿走!
  • Linux中断实验
  • VibeVoice 部署全指南:Windows 下的挑战与完整解决方案
  • 为什么需要锁——多线程的数据竞争是怎么引发错误的
  • 梯度消失问题:深度学习中的「记忆衰退」困境与解决方案