代码来源:https://codepen.io/dagger8224/pen/myeKgVQ

任务:实现“按钮点击 +1”计数器,对比不同框架的写法与特性,并给出选型建议。


目录

  • 代码解读(逐框架)
    • jQuery(命令式 DOM)
    • AngularJS(作用域 + 指令)
    • Vue(响应式 + 模板指令)
    • React(状态 + 渲染函数)
    • dagger.js(原生 DOM 上的声明式指令,零样板)
  • 方案对照(要点一览)
  • 技术观察与解读
  • 什么时候选谁?
  • 附:关键代码片段

代码解读(逐框架)

jQuery(命令式 DOM)

HTML 一个按钮 #jquery,JS 里手动挂事件并改 innerHTML,用 - 0 把字符串转数值:

$('#jquery').on('click', e => e.target.innerHTML = e.target.innerHTML - 0 + 1);

这完全把 DOM 当“状态源”,简单直接,但没有数据层,后续可维护性与可组合性较弱。


AngularJS(作用域 + 指令)

ng-app="ngApp" ng-controller="buttonController" 声明应用与控制器,$scope.count 放状态,ng-click 触发 handleClick()

<div ng-app="ngApp" ng-controller="buttonController"><button ng-click="handleClick()">{{ count }}</button>
</div>
<script>
angular.module('ngApp', [])
.controller('buttonController', function($scope){$scope.count = 0;$scope.handleClick = function(){ $scope.count++; };
});
</script>

模板 {{ count }}$scope 绑定,靠 digest 循环驱动更新。对这个微例子而言,样板代码相对偏多。


Vue(响应式 + 模板指令)

数据在 data,事件在 methods,点击只改数据、视图自动更新:

<div id="vue"><button v-on:click="handleClick">{{ count }}</button>
</div>
<script>
new Vue({el:'#vue',data:{ count:0 },methods:{ handleClick(){ this.count++; } }
});
</script>

结构清晰,体量中等。


React(状态 + 渲染函数)

使用 class 组件:

class ReactButton extends React.Component {state = { count: 0 };handleClick = () => this.setState({ count: this.state.count + 1 });render(){return <button onClick={this.handleClick}>{this.state.count}</button>;}
}
ReactDOM.render(<ReactButton/>, document.getElementById('react'));

状态在 this.state,用 setState 触发重渲染。样板代码偏多(尤其在无需组件化时),但在大规模组件树、生态配套下优势明显。


dagger.js(原生 DOM 上的声明式指令,零样板)

一行 HTML 解决:

<button id="dagger" dg-cloak +load="{ count: 0 }" +click="count++">${ count }</button>
  • +load 初始化局部作用域(当前宿主元素)。
  • ${ count } 插值。
  • +click 直接写表达式增量。
  • dg-cloak 防止闪烁。

无需单独 JS 模块与挂载点,状态与视图强“同位(colocation)”。


方案对照(要点一览)

维度jQueryAngularJSVueReactdagger.js
状态归属DOM 即状态$scopedatathis.state元素局部作用域(+load
事件绑定代码里手绑ng-clickv-on:clickonClick+click(表达式)
视图更新手改 DOMdigest响应式重渲染直接驱动 DOM(无 VDOM)
样板/文件数最少,但可维护性弱偏多适中偏多极少(常一行搞定)
学习/心智低,命令式指令+作用域模板+响应式组件/状态/JSX原生 DOM + 轻指令
适配复杂度组件化弱过时生态生态完善生态最强轻量、无构建亦可

注:上表依据本例的写法与常见范式总结。


技术观察与解读

  1. “状态在哪里”决定复杂度走向

    • jQuery:把 DOM 当真相源,最轻,但交互增多时难控。
    • Vue/React:数据为真相源,模板/JSX 由状态驱动,易规模化。
    • dagger.js:把“小状态”就地挂在元素作用域,天然就近,适合局部交互。
  2. 事件写法的表达力与可组合性

    • Vue/Angular/React:声明事件名 → 调函数。
    • dagger.js:+click="count++" 直接表达更新意图,减少样板(无需 methods / this.setState)。
  3. 引导方式与挂载点

    • AngularJS:ng-app / ng-controller
    • Vue:new Vue({ el })
    • React:ReactDOM.render()
    • dagger.js:元素上声明即可,不依赖全局挂载点,适合“就地增强”。
  4. 样板与可读性

    • 本例中,从多到少大致是:React ≥ AngularJS ≥ Vue > jQuery ≈ dagger.js。
    • 对“按钮 + 计数”这类微交互,dagger 的“一行式”复制扩散成本最低。
  5. 可规模化与生态

    • 组件通信、路由、状态管理、SSR、工程化链路:React/Vue 生态占优。
    • dagger.js:无需构建的轻交互、内嵌到现有页面、分散微部件;与 jQuery 渗透场景重叠,但更现代、声明式。

什么时候选谁?

  • 给现有页面补几个小交互/小挂件:首选 dagger.js(或其他轻量范式),因为“就地声明 + 无样板”。
  • 中大型单页应用React / Vue 更稳,生态丰富、协作友好。
  • 快速脚本式改动jQuery 可用,但谨慎可维护性与状态一致性。
  • AngularJS 存量:按存量维护;新项目不建议再启用 AngularJS。

附:关键代码片段

以下为本示例中各技术栈的最小可用版本,便于复制到自己的实验页面。

jQuery

<button id="jquery">0</button>
<script src="https://cdn.jsdelivr.net/npm/jquery/dist/jquery.min.js"></script>
<script>
$('#jquery').on('click', e => e.target.innerHTML = e.target.innerHTML - 0 + 1);
</script>

AngularJS

<div ng-app="ngApp" ng-controller="buttonController"><button ng-click="handleClick()">{{ count }}</button>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script>
<script>
angular.module('ngApp', [])
.controller('buttonController', function($scope){$scope.count = 0;$scope.handleClick = function(){ $scope.count++; };
});
</script>

Vue

<div id="vue"><button v-on:click="handleClick">{{ count }}</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.min.js"></script>
<script>
new Vue({el:'#vue',data:{ count:0 },methods:{ handleClick(){ this.count++; } }
});
</script>

React

<div id="react"></div>
<script src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
<script type="text/babel">
class ReactButton extends React.Component {state = { count: 0 };handleClick = () => this.setState({ count: this.state.count + 1 });render(){return <button onClick={this.handleClick}>{this.state.count}</button>;}
}
ReactDOM.render(<ReactButton/>, document.getElementById('react'));
</script>

dagger.js

<script type="module" crossorigin="anonymous" src="https://assets.codepen.io/5782383/dagger-1.0.0-RC.js" defer></script>
<button id="dagger" dg-cloak +load="{ count: 0 }" +click="count++">${ count }</button>

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/95046.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/95046.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/95046.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

useEffect中直接使用 await报错

在 useEffect 中直接使用 await 会报错&#xff0c;因为 useEffect 的回调函数不能是 async 函数。有几种正确的方式来处理异步操作&#xff1a; 方法一&#xff1a;在 useEffect 内部创建 async 函数并立即调用 这是最常用的方式。 import React, { useEffect } from react;co…

卷积神经网络为什么要填充(Padding)

填充&#xff08;Padding&#xff09;是卷积神经网络中一个至关重要且巧妙的设计。它的核心目的可以概括为&#xff1a;为了解决卷积操作导致的特征图尺寸缩小和边缘信息丢失问题。

C++ 并发编程:全面解析主流锁管理类

在 C 的并发世界里&#xff0c;管理共享资源就像是在一个繁忙的十字路口指挥交通。如果指挥不当&#xff0c;就会发生混乱甚至致命的“死锁”。C 标准库提供的各种锁管理工具&#xff0c;就是我们手中的“交通信号灯”&#xff0c;它们各自拥有独特的职能&#xff0c;帮助我们编…

Spring boot 启用第二数据源

1. 数据源配置代码&#xff1a;import com.alibaba.druid.pool.DruidDataSource; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilde…

Wi-Fi 时延与掉包的关键因素全解析

在无线网络性能优化中&#xff0c;时延&#xff08;Latency&#xff09;与掉包&#xff08;Packet Loss&#xff09;是最核心的两个指标。本文将从 物理层、MAC层、系统栈、业务形态与环境 等多个维度&#xff0c;对 Wi-Fi 时延与掉包的关键因素进行全面梳理&#xff0c;并结合…

《Python 文本分析实战:从单词频率统计到高效可视化的全流程指南》

《Python 文本分析实战:从单词频率统计到高效可视化的全流程指南》 一、引言:小任务背后的大世界 在我多年的开发与教学中,文本处理始终是一个绕不开的主题。无论是日志分析、自然语言处理,还是搜索引擎、推荐系统,几乎所有数据驱动的系统都离不开对文本的理解。而“统计…

12KM无人机高清图传通信模组——打造未来空中通信新高度

在无人机技术飞速发展的今天&#xff0c;高清图传和稳定的通信模块无疑是提高无人机作业效率和可靠性的关键因素。作为新一代无人机核心技术之一&#xff0c;深圳云望物联12KM无人机高清图传通信模组凭借其卓越的性能&#xff0c;正逐步成为行业内的宠儿&#xff0c;成为无人机…

【LeetCode 热题 100】62. 不同路径——(解法二)递推

Problem: 62. 不同路径 文章目录整体思路完整代码时空复杂度时间复杂度&#xff1a;O(m * n)空间复杂度&#xff1a;O(m * n)整体思路 这段代码同样旨在解决 “不同路径” 问题&#xff0c;但它采用的是一种 自底向上&#xff08;Bottom-Up&#xff09;的动态规划 方法&#x…

C++ 高阶错误解析:MSVC 与 Qt 全景指南

在 C 开发中&#xff0c;尤其是在 Windows 平台使用 MSVC 或 Qt 框架 时&#xff0c;程序员经常会遇到编译错误、链接错误和运行时异常。本文将系统梳理这些问题&#xff0c;按 语法错误、类型错误、链接错误、Qt 运行错误 分类&#xff0c;并给出 触发示例、原因分析及修复策略…

基于Net海洋生态环境保护系统的设计与实现(代码+数据库+LW)

摘要 随着全球气候变化和人类活动的加剧&#xff0c;海洋生态系统面临着前所未有的威胁。污染、过度捕捞、栖息地破坏等问题严重影响了海洋生物多样性和生态平衡。为了应对海洋生态系统面临的严重威胁&#xff0c;如污染、过度捕捞和栖息地破坏等问题&#xff0c;利用C#语言和…

DoIP路由激活报文

目录 DoIP路由激活报文详解 基本概念 报文结构 响应报文 通信流程 注意事项 **DoIP (Diagnostics over Internet Protocol) 报文详解** **1. DoIP 报文结构** **1.1 通用报文格式** **2. 常见 DoIP 报文类型** **3. 典型 DoIP 报文示例** **3.1 车辆识别请求(广播)** **3.2 车…

学习Python中Selenium模块的基本用法(8:元素操作-2)

定位网页元素后&#xff0c;调用is_displayed函数可以判断元素的显示状态&#xff0c;如百度网站中有默认隐藏的元素&#xff0c;此时即可使用is_displayed函数判断该元素的显示状态&#xff0c;如下面代码所示&#xff1a;driver webdriver.Chrome() driver.get("https:…

双指针:从「LC11 盛最多水的容器」到「LC42 接雨水」

LC11 盛最多水的容器 选择两条线&#xff0c;它们与x轴构成的容器可以盛的水量取决于两条线中较短的那条以及两条线之间的距离。 朴素的思想是使用i和j遍历height中的所有线&#xff0c;但是这样的时间复杂度是O(n2)O(n^2)O(n2)。 我们让i从0开始&#xff0c;j从n-1开始&…

WINTRUST!_GetMessage函数分析之CRYPT32!CryptSIPGetSignedDataMsg函数的作用是得到nt5inf.cat的信息

UEDIT打开nt5inf.cat。第一部分&#xff1a;BOOL _GetMessage(CRYPT_PROVIDER_DATA *pProvData) {DWORD dwMsgEncoding;SIP_SUBJECTINFO *pSubjInfo;SIP_DISPATCH_INFO *pSip;DWORD cbEncodedMsg;BYTE *pbEncodedMsg;DWORD …

编译esp32报错解决办法

报错信息&#xff1a;CMake Error at build/CMakeFiles/git-data/grabRef.cmake:48 (file):file failed to open for reading (No such file or directory):这个错误是由于 Git 的安全检查导致的。从错误信息可以看出&#xff0c;Git 检测到了"可疑的所有权"&#xf…

【AI】常见8大LLM大语言模型地址

序号AI名称地址1 ChatGPT &#xff08;OpenAI&#xff09;https://chat.openai.com/2Gemini (Google personal AI assistant)https://gemini.google.com/app3Grok (xAI Grok LLM)https://x.ai/4DeepSeek (DeepSeek AI chatbot)DeepSeek5Claude (Anthropic Claude AI)App unavai…

软件系统的部署方式:单机、主备(冷主备、热主备)、集群

一、单机部署单机部署是将软件系统所有组件&#xff08;应用、数据库等&#xff09;部署在单台服务器上&#xff0c;架构简单、成本低但存在单点故障风险&#xff0c;适用于低负载或测试场景。一台服务器坏了&#xff0c;软件系统无法服务。二、主备&#xff08;冷主备、热主备…

从体验到系统工程丨上手评测国内首款 AI 电商 App

作者&#xff1a;王晨&#xff08;望宸&#xff09; 产品界面&#xff0c;往往体现了产品的设计哲学&#xff0c;界面是产品的第一入口。 近期&#xff0c;1688 推出了 1688 AI App&#xff0c;这貌似是国内第一个电商领域的独立 AI App 应用&#xff08;若不是&#xff0c;欢…

QML QQuickImage: Cannot open: qrc:/images/shrink.png(已解决)

此问题是 在 QT Quick 项目 显示图片的时候 遇到&#xff0c;显示&#xff1a;QML QQuickImage: Cannot open: qrc:/images/shrink.png&#xff0c;不能 打开 图片。为了解决此问题&#xff0c;找了很多资料&#xff0c;虽然是比较简单&#xff0c;但对于初学者来说&#xff0c…

maven scope 详解

Maven 的 scope用于定义依赖项在项目构建生命周期中的可见性和传递性&#xff0c;控制依赖在编译、测试、运行等阶段的可用性及是否被打包到最终产物中。以下是详细解析&#xff1a;⚙️ ​​一、Scope 的核心作用​​​​生命周期控制​​决定依赖在编译、测试、运行阶段的可用…