首页 > 其他分享 >dagger.js实战案例:是牛是马拉出来溜溜啊

dagger.js实战案例:是牛是马拉出来溜溜啊

时间:2025-01-10 21:58:39浏览次数:3  
标签:vue dagger 马拉 模块 组件 js 路由

欢迎关注微信公众号:我是王多余

大家好,我是Tony。在这篇文章中,我将通过一个实际的TODO List开发案例,展示如何使用dagger.js、React 和 Vue 3 构建功能完全相同的单页应用,深入对比这三种框架在设计和使用上的细节差异。

本示例涵盖了现代前端项目中常见的功能模块,包括模板和指令语法、路由配置、数据状态管理、双向数据绑定、事件处理以及组件设计等。

为了便于横向对比,我们将项目代码拆解为若干步骤,每个步骤依次展示三种框架的实现方式并做代码讲解。无论你是否熟悉这些框架,都可以按照本文的步骤轻松上手。

闲言少叙。接下来,我们将直接进入代码部分(完整的示例代码放在这里,供参考)。

步骤0:开发环境准备

1. 全局安装 Node.js。
本示例项目使用的Node.js 版本为 20.14.0
需要注意的是,React 和 Vue 项目的构建依赖于Node.js。而dagger.js是一个纯运行时框架,没有构建或打包过程,因此 dagger.js 的开发不需要依赖Node.js。

2. 创建一个名为TODO-List(或你喜欢的任何名字)的文件夹作为项目根目录。

步骤1:项目初始化

为便于横向对比,我们统一使用Vite来初始化项目并启动dev server。

react

在根目录下打开命令行工具,运行npm create vite,根据命令行提示进行项目配置:

  •     项目名称:react

  •     框架选择:React

  •     语言选择:JavaScript

vue

在根目录下打开命令行工具,运行npm create vite,根据命令行提示进行项目配置:

  • 项目名称:vue

  • 框架选择:Vue

  • 语言选择:JavaScript

dagger

在根目录下打开命令行工具,运行npm create vite,根据命令行提示进行项目配置:

  • 项目名称:dagger

  • 框架选择:Vanilla(原生 JavaScript)

  • 语言选择:JavaScript

我们也可以选择不依赖Vite来初始化dagger.js项目。

只需在项目根目录下创建一个名为dagger的子文件夹,并将一个常规的index.html页面模板复制到该文件夹中即可。

如果选择这种初始化方式,你需要通过其他的静态服务器(例如 Nginx 或 Live Server等)来启动dev server。

步骤2:启动项目

react  vue  dagger

从本步骤开始,命令行工具需要切换到各版本项目子文件夹下。

1. 运行npm install安装依赖模块。

2. 运行npm run dev启动dev server。

步骤3:调整代码结构

react

进入src文件夹。

1. 清空index.css和App.css的内容。

2. 将App.jsx中的代码改为如下图所示,只返回一组空的div标签:

图片

vue

进入src文件夹。

1. 删除components文件夹下的预置组件。

2. 清空style.css的内容。

3. 将App.vue改为如下的空白Vue页面模板:

图片

dagger

1. 删除src文件夹。

2. 将index.html内容修改如下:

图片

红框中的代码是项目的入口模块配置项。我们在根名空间下,声明了一个名为app的模块,其模块代码来自modules/APP.html文件。需要注意的是,dagger.js 框架要求模块名称必须以下划线或小写字母开头。

黄框中通过标签创建了一个app组件实例。

绿框内是dagger.js框架源码的引入方式,注意需要把script标签的类型设置为module,并加上defer声明。你可以通过以下cdn链接获取源码:

debug版本

https://assets.codepen.io/5782383/dagger-1.0.0-RC.js

release版本

https://assets.codepen.io/5782383/dagger.release-1.0.0-RC.js

在实际项目开发过程中,推荐使用debug版本,它会在控制台输出程序运行日志和详细的报错信息。上线时,建议切换到release版本,它的代码更加精简,执行效率也更高。

4. 创建一个名为modules的文件夹,在该文件夹下创建一个名为APP.html的视图模块文件,内容如下:

图片

刷新浏览器,页面显示“Hello dagger!”:

图片

需要说明的是,dagger.js是一个基于 HTML 的描述式框架,框架会根据模块和路由配置动态触发页面渲染。因此不像React或Vue应用那样需要依赖main脚本模块作为程序的执行入口点。

代码已经清理完成,接下来我们来添加路由。

步骤4:安装路由

react

1. 命令行运行npm install -S react-router-dom安装路由模块。

2. 重新运行npm run dev启动dev server。

vue

1. 命令行运行npm install -S vue-router@4安装路由模块。

2. 重新运行npm run dev启动dev server。

dagger

dagger.js内置了路由管理功能,不需要额外安装插件。

步骤5:添加路由

react

1. 在src下新建router.jsx文件,内容如下:

图片

2. 修改App.jsx,通过RouterProvider标签加载路由组件实例:

图片

vue

1. 在src下新建router.js文件,内容如下:

图片

2. 修改main.js,启用路由功能:

图片

3. 修改App.vue,通过RouterView标签加载路由组件实例:

图片

dagger

1. 在项目文件夹下新建router.json,内容如下:

图片

routing下是路由项和关联模块设置,我们为根路由添加一个viewName常量,并将app和post_list设置为根路由的关联模块名称。

dagger.js默认使用hash路由模式,这里我们将其设置为history模式。

在routing配置下设置路由项和关联模块。我们为根路由添加了一个viewName常量,并将app和post_list设置为根路由的关联模块名称。

2. 修改index.html文件,添加红框内代码引入路由:

图片

注意路由配置项标签的类型为dagger/routers。

3. 修改APP.html文件,删除“Hello dagger!”,并将其替换为一个声明了*html指令的模板标签:

图片

上图中的代码是dagger.js路由的典型使用方式:

框架解析router.json配置项,创建顶层对象$route,并将*html指令表达式设置为预定义常量$route.constants.viewName,这相当于在当前位置插入了<post_list></post_list>标签。

*html指令监听表达式的计算结果,当路由变化时,指令会重新计算并更新路由关联视图。

刷新浏览器,额,控制台报错了:

图片

别着急,接下来我们将添加post_list模块。

步骤6:添加PostList页面

react

1. 在src下新建pages文件夹,并在pages文件夹中新增PostList.jsx文件。文件内容如下:

图片

我们使用useState创建了响应变量postList,并在useEffect钩子中发送 AJAX请求以更新postList数据。onDelete方法用于从postList列表中删除指定的post数据,严格来说,是“将postList变量重置为不包含指定post数据的新列表”。

2. 在router.jsx文件中引入PostList组件:

图片

vue

1. 在src下新建pages文件夹,pages下新增PostList.vue文件:

图片

我们在生命周期回调onMounted中获取并更新postList数据。需要注意的是,这里的postList是一个Vue的ref对象,其value字段指向实际的post数组。Vue框架采用了类似于.NET中“装箱”(boxing)的方法将数据包裹,以实现数据的可观测性。

2. 在router.js文件中引入PostList组件:

图片

dagger

1. 在modules文件夹下新建PostList.html文件,内容如下:

图片

我们在生命周期指令+load中定义了postList数组,并在+loaded指令中发送AJAX请求来更新postList的值。

需要注意的是dagger指令表达式中$scope参数的用法。 $scope代表了当前上下文下可访问的作用域对象,我们在控制台打印出$scope来查看其内容:

图片

可以看到,$scope是一个包含了postList数组的派生对象,$scope的prototype指向根作用域。根作用域下包含前文中提到的顶层路由对象$route。

dagger.js和Vue都通过将数据转化为代理(Proxy)对象来实现可观测性。不同的是,Vue需要将对象进一步包装为一个自定义的Ref对象,而dagger.js则将数据与视图的关联信息存储在对象的元数据当中,这样用户可以使用原生 JavaScript 语法直接访问和修改数据。

2. 在index.html的模块配置项中添加如下代码以创建post_list模块:

图片

需要注意的是dagger.js与其他两个框架在引入组件方式上的区别。

在dagger.js版本中,整个应用程序是由框架进行管理的。开发者需要编写的代码包括两部分:一是配置项(如路由和模块声明等),二是模块本身(如视图、脚本模块等)。dagger.js会根据配置项和当前页面的路由状态,决定加载和执行哪些模块。简而言之,开发者提供的所有业务代码实际上是dagger.js的回调参数。

下一步我们继续添加PostItem组件。

步骤7:添加PostItem组件

react

1. 在src下新建components文件夹,components下新增PostItem.jsx文件:

图片

PostItem仍然是一个常规的函数组件。

红框内的onDelete是在父组件PostList中定义的删除post方法,作为prop参数传递给子组件PostItem。当用户点击“Delete”按钮时,会触发该方法(见绿框代码)。

黄框内使用Link标签定义了一个跳转到编辑页面的链接。

2. 在PostList.jsx中引入PostItem组件并渲染:

图片

黄框内代码用于循环渲染PostItem列表,其中post数据和onDelete方法作为props属性传递给子组件。

vue

1. 在components下新增PostItem.vue文件:

图片

红框内代码用RouterLink标签定义了一个跳转到编辑页面的链接。

黄框内代码通过emit方式将待删除的数据传递回父组件。Vue提供了令人目不暇接的多种组件通信方式,但这不是本文的重点,打算考研的同学请自行参考相关文档进行深入学习。

2. 在PostList.vue中引入PostItem组件并渲染:

图片

Vue通过v-for指令实现数组的循环渲染。这里需要注意@delete事件和PostItem.vue中emit调用的对应关系。

dagger

1. 在modules下新增PostItem.html文件:

图片

如红框中代码所示,dagger.js通过在原生标签a上添加*href指令的方式来创建路由链接。

黄框中是点击删除post事件代码。这里的postList是由父级作用域创建的数组对象,由于作用域存在继承关系,子组件中可以直接访问和修改父组件中定义的数据。当然,我们也可以将删除方法定义在父作用域的脚本模块当中。和作用域一样,脚本模块同样具有继承关系,子组件可以直接调用在父级组件内引入的方法。

2. 在PostList.html中引入PostItem组件并渲染:

图片

这里我们新增了一个类型为dagger/modules的脚本标签,作为当前名空间的模块配置项。实际上,每个名空间模块都有一个缺省的模块配置项:

图片

开发者可以自定义一个完整的模块配置项,也可以通过extends属性声明当前的模块配置项是从缺省模块配置项扩展而来的。

红框内的代码等价于:

图片

黄框里是循环渲染PostItem列表的代码,dagger.js使用*each指令进行循环渲染。我们在*each指令上添加了修饰符#item:post,这相当于在子级作用域中创建了一个名为post的对象。

接下来,我们将添加列表项的创建和编辑页面组件。

步骤8:添加PostForm页面

react

1. 在pages文件夹下新增PostForm.jsx文件。由于文件内容较长,我们将其分成三部分来逐一查看:

图片

通过useState hook创建了model对象来存放post数据。

通过useParams hook获取路由参数id。

在useEffect hook中,使用setModel方法加载指定id的post数据。

图片

接下来是定义用于提交表单数据的onSubmit方法。需要加入红框代码来阻止默认的表单提交行为。另外,在AJAX请求调用完成后,通过路由器对象的router.navigate方法来进行路由跳转(见黄框代码)。

图片

最后一部分是视图模板。在React框架中,并没有内置的双向数据绑定功能,因此开发者需要自行实现input标签的onInput事件来更新数据。

2. router.jsx文件引入PostForm组件并设置新的路由:

图片

vue

1. pages文件夹下新增PostForm.vue文件:

图片

先来看视图模板部分,Vue 提供了内置的双向数据绑定功能,通过v-model指令,可以将数据和input标签的输入内容动态同步。

.prevent指令修饰符将阻止submit事件的默认行为,这相当于React代码中的event.preventDefault()。

图片

通过useRoute获取路由对象。

通过useRouter获取路由器对象。

图片

在AJAX请求调用完成后,通过路由器对象的router.push方法实现路由跳转。

2. router.js文件引入PostForm组件并设置新的路由:

图片

dagger

1. 在modules文件夹下新增PostForm文件夹,在PostForm文件夹下新增namespace.html和script.js两个文件。

我们这里将PostForm名空间下的脚本模块放到单独的js文件中。相比直接在html文件中嵌入script标签来说,使用单独js脚本的资源定位方案实现了关注点分离,代码更加清晰易读,同时可以获得更好的编辑器语法高亮和自动补全支持。

namespace.html:

图片

这里值得注意的内容包括:

#prevent指令修饰符会阻止submit事件的默认行为,相当于React代码中的event.preventDefault()或Vue代码中的.prevent修饰符。

input标签的*value指令提供了双向数据绑定能力,类似于Vue的v-model指令。

接下来看script.js:

图片

参数id通过顶层的路由对象$route中获取。

命令式路由跳转使用原生JavaScript内置的history.pushState或者history.replaceState方法来实现。

2. router.json文件引入PostForm组件并设置新的路由:

图片

dagger.js的路由配置项是一个树型结构对象。

我们在根路由下新增加两个子路由节点,分别与路径new和edit/:id匹配,这两个子路由的viewName常量字段和modules都设置为post_form。

缺省情况下,只有叶路由节点才能作为路由匹配的终点。红框中新增的tailable: true允许当前的路由节点(根路由)作为路由匹配的终止结点。如果去掉这个配置,直接访问http://localhost:5176将匹配失败,控制台报错:

图片

3. 回到index.html页面,在模块配置项中增加post_form模块声明:

图片

我们刷新页面看下:

图片

内容已经渲染出来了,但是看起来非常简陋。现在我们在三个版本的index.html中分别增加如下代码,引入Bootstrap样式库:

<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">

再次刷新页面,页面现在看起来美观多了:

图片

点击按钮和链接,测试前面加入的各项功能是否正常。到此,我们的演示实例已经基本开发完成了。

关于数据状态管理

接下来聊最后一个话题:数据状态管理。

以React和Vue为代表的现代前端框架,普遍遵循单向数据流(瀑布模型)的设计思想。在单向数据流模型中,应用程序的数据流动是有明确方向的(父级流向子级)。子级组件可以消费父级数据,但原则上不允许直接修改父级数据,数据的维护应由其创建者负责。这一设计思想进一步催生了数据中心存储(dataStore)和不可变性(immutable)等开发模式。

与此不同,dagger.js 更倾向于将整个应用程序视为一块四通八达的电路板(我称之为集成电路模型)。自数据对象创建起,电路(即作用域链)上的每个“电器”(指令)都可以作为数据的消费者和修改者。简单来说,数据即状态,任何组件或指令都可以对其可访问的数据进行操作。同时,任何对数据的原子修改(mutation)都会被其他依赖该数据的指令感知,进而触发页面更新(全域响应性)。

实际上,dagger.js的设计思路更加贴近原生IavaScript语法。我们可以通过一组原生IavaScript嵌套函数调用,来对比瀑布模型与集成电路模型之间的差别。

瀑布模型:

图片

集成电路模型:

图片

图片

孰优孰劣,见仁见智。

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

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

附:本文示例中涉及到的各框架主要差异列表:

框架

react (18.3.1)

vue (3.5.13)

dagger (1.0.0-RC)

开发环境

nodejs

nodejs

可选安装node.js

初始化

Vite

Vite

Vite或手动创建

启动开发服务

npm

npm

npm或其他静态服务器

代码入口

main.jsx

main.js

dagger.js

路由模块

react-router插件

vue-router插件

内置

路由视图渲染

RouterProvider

RouterView

*html指令

路由链接

Link

RouterLink

a标签

路由对象获取

useParams

useRoute

$route

命令式路由跳转

router.navigate

router.push

history.pushState

创建可观测数据

useState

ref

+load指令

组件加载完成回调

useEffect

onMounted

+loaded指令

循环语法

Array.map

v-for指令

*each指令

双向数据绑定

onInput事件

v-model指令

*value指令

数据状态管理

Context API

vuex

数据即状态

构建发布

npm

npm

无需构建

按:本文中采用的示例取材于油管博主@TheCodeholic的教学视频,作者通过一个TODO List案例展示了react和vue两个框架的用法差异。示例很经典,讲解也十分细致清晰,是非常好的前端单页应用开发入门教程。推荐大家观看原视频

标签:vue,dagger,马拉,模块,组件,js,路由
From: https://blog.csdn.net/2404_89388058/article/details/145065949

相关文章

  • JSP客房预订管理系统u2ms3(程序+源码+数据库+调试部署+开发环境)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容一、研究背景随着旅游业的蓬勃发展,酒店行业面临着日益增长的客户预订需求。传统的手工预订方式不仅效率低下,还容易出错,无法满足现代酒店管理的需求......
  • JSP科技企业孵化器管理信息系统udx9v--(程序+源码+数据库+调试部署+开发环境)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容一、研究背景科技企业孵化器作为推动科技创新和经济发展的重要平台,为初创企业提供全方位的支持和服务。然而,现有的孵化器管理模式存在一些问题,如管......
  • JSP客制化键盘网站ql5m4(程序+源码+数据库+调试部署+开发环境)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表技术要求: 开发语言:JSP前端使用:HTML5,CSS,JSP动态网页技术后端使用SpringBoot,Spring技术主数据库使用MySQL开题报告内容一、项目背景随着电子竞技的迅猛......
  • JSP科研成果管理系统b3qv7--(程序+源码+数据库+调试部署+开发环境)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表技术要求:开发语言:JSP前端使用:HTML5,CSS,JSP动态网页技术后端使用SpringBoot,Spring技术主数据库使用MySQL开题报告内容一、研究背景随着科研活动的日益频......
  • JSP可回收物回收管理系统u5rw7程序+源码+数据库+调试部署+开发环境
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表技术要求:开发语言:JSP前端使用:HTML5,CSS,JSP动态网页技术后端使用SpringBoot,Spring技术主数据库使用MySQL开题报告内容一、研究背景随着城市化进程的加快,......
  • JSP课程辅助教学系统x6z10(程序+源码+数据库+调试部署+开发环境)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表技术要求:开发语言:JSP前端使用:HTML5,CSS,JSP动态网页技术后端使用SpringBoot,Spring技术主数据库使用MySQL开题报告内容一、项目背景随着教育技术的快速发......
  • JSP课程教学辅助系统的设计与实现edj0s(程序+源码+数据库+调试部署+开发环境)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表技术要求:开发语言:JSP前端使用:HTML5,CSS,JSP动态网页技术后端使用SpringBoot,Spring技术主数据库使用MySQL开题报告内容一、项目背景在信息化教育的大背景......
  • JSP科傲数码配件线上销售系统6n19l(程序+源码+数据库+调试部署+开发环境)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表技术要求:开发语言:JSP前端使用:HTML5,CSS,JSP动态网页技术后端使用SpringBoot,Spring技术主数据库使用MySQL开题报告内容一、研究背景随着互联网技术的快速发......
  • JS-27 字符串方法_split()
    split方法按照给定规则分割字符串,返回一个由分割出来的子字符串组成的数组'it|sxt|zifuchuan'.split('|')//["it","sxt","zifuchuan"]如果分割规则为空字符串,则返回数组的成员是原字符串的每一个字符。'a|b|c'.split('')//["a","|","b&q......
  • java基于JSP学生信息管理系统论文+源码 2025毕设
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容一、研究背景在当今的教育环境中,随着学校规模的不断扩大和教育管理事务的日益繁杂,传统的人工管理方式已难以满足高效、准确管理学生信息的需求。学校需要处理......