ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Flight Mixin API 详解:组件式 JavaScript 框架中的混合复用机制

Flight Mixin API 详解:组件式 JavaScript 框架中的混合复用机制 前端Web框架【免费下载链接】flightA component-based, event-driven JavaScript framework from Twitter项目地址https://gitcode.com/gh_mirrors/fl/flight点击查看免费下载本篇技术指南围绕 Flight来自 Twitter 的 component-based、event-driven JavaScript 框架的 Mixin API 展开系统讲解 mixin 的定义方式、如何应用到 Component、如何通过compose.mixin应用到普通对象、mixin 中attributes的默认值覆盖规则以及如何基于既有 Component 派生新组件。读完本文你将掌握 Flight 组件复用的完整实战方案并能结合源码理解其防止方法被混入时覆盖的底层实现原理。什么是 Mixin在 Flight 中mixin 是一个函数它把一组属性属性值通常是方法赋值给目标对象这个目标对象由 mixin 函数体内的this关键字表示。mixin 具有以下核心特性这也是整个 Flight 组件体系复用的基础一个典型的 mixin 定义了一套可以被多个组件共用的功能避免在每个组件里重复书写相同逻辑一个 mixin 可以应用到任意数量的 Component 定义上一个 Component 定义可以同时应用任意数量的 mixin每个 Component 在自己的模块内部都会定义一个core mixin即描述该组件自身行为的那个函数mixin 本身也可以被其他 mixin 应用mixin 嵌套。换句话说Flight 的组件本质上就是一组 mixin 叠加在同一个原型对象上的结果。正如 Component API 文档 所述A Component is just a constructor with properties mixed into its prototype而把属性混入原型这一动作正是由flight.component内部的compose.mixin完成的。如何定义一个 MixinMixin 的定义方式和 Component 定义几乎一样唯一的区别是mixin 不需要调用flight.component。你只需要导出一个普通函数函数体内通过this挂载方法即可。// mixins/with_dropdown.js function withDropdown() { this.openDropdown function() { //... }; this.selectItem function() { //... }; } // 导出 mixin 函数 module.exports withDropdown;当这个 mixin 被应用到某个 Component 时withDropdown会以目标对象为this的方式被调用因此openDropdown、selectItem就成为该 Component 原型上的方法。从源码看这正是 lib/compose.js 中mixin(base, mixins)做的事情——对每个 mixin 执行mixins[i].call(base)从而把属性直接赋到base上。如何把 Mixin 应用到 Component在 Component 定义中把需要的 mixin 作为参数传给flight.component函数即可数量不限// components/fancy_component.js var flight require(flightjs); var withDialog require(mixins/with_dialog); var withDropdown require(mixins/with_dropdown); module.exports flight.component(fancyComponent, withDialog, withDropdown); function fancyComponent() { //... 这是该组件的 core mixin描述组件自身行为 }其中第一个参数fancyComponent就是这个组件的core mixin——Flight 中每个组件模块内部都会定义这么一个描述自身行为的函数它与后面传入的 mixin 一视同仁都会被混入组件的原型。从 lib/component.js 的defineComponent实现可以看到完整的调用链框架先无条件把内置的withBase基础能力on/off/trigger/select等、advice.withAdviceAOP 增强、registry.withRegistration实例注册三个 mixin 依次排到传入列表的最前面调试模式下还会插入withLogging然后调用compose.mixin(Component.prototype, mixins)把所有 mixin 连同用户传入的函数一起混入原型最后返回一个 Component 构造函数构造器上挂有attachTo、teardownAll、mixin等静态方法。因此你可以在组件实例中直接使用this.openDropdown()也可以照常使用基础 API 中由withBase提供的this.on(...)、this.trigger(...)等能力。同一 mixin 不会被重复混入compose.mixin内部通过base.mixedIn数组记录已经混入过的 mixin 函数引用if (base.mixedIn.indexOf(mixins[i]) -1) { setWritability(base, false); mixins[i].call(base); base.mixedIn.push(mixins[i]); }也就是说同一个 mixin 函数即使被多次传入也只会生效一次。这一点有对应的测试用例保障在 test/spec/mixin_spec.js 中对mixMeIn与mixMeToo各重复调用两次compose.mixin最终断言base.mixedInCount仍为 2每个 mixin 只执行一次避免副作用重复发生。如何把 Mixin 应用到普通对象compose.mixin在底层Component 添加 mixin 用的就是 Flight 的compose模块。compose.mixin除了执行函数混入之外还有一个重要职责防止 mixin 覆盖clobber目标对象上已有的方法名。它通过setWritability在混入期间临时把目标对象已有属性的writable置为falsemixedIn、attrDef两个键除外混入结束后再恢复为可写——即混入锁机制具体见 lib/compose.js 与 lib/utils.js 的propertyWritability实现。如果你需要把 mixin 应用到组件以外的对象上比如应用到另一个 mixin 上实现 mixin 的组合复用可以直接调用compose.mixin// mixins/with_dialog.js var flight require(flightjs); var withPositioning require(mixins/with_positioning); function withDialog() { //把 withPositioning 混入 withDialog flight.compose.mixin(this, [withPositioning]); //... } // 导出 mixin 函数 module.exports withDialog;这样withDialog在被应用到组件时会连带带上withPositioning的能力从而形成mixin 套 mixin的复用链。注意compose.mixin接收的第二个参数是 mixin 函数的数组这与flight.component的变长参数调用方式略有不同。compose.mixin对目标对象没有限制即使是Object.create(null)创建的对象也能正常混入这一点同样有测试覆盖见 test/spec/mixin_spec.js。在 Mixin 中覆盖默认值attributesattributes方法对组件模块和 mixin 模块都是可用的。当 mixin 里使用attributes时它不会覆盖组件模块中已经定义的同名属性——组件里定义的属性优先级更高。/* mixins/big_button */ function bigButton() { this.attributes({ buttonClass: js-button-big }); } module.exports bigButton;其底层原理可以从 lib/base.js 的this.attributes实现看出每次调用attributes框架都会基于已有的this.attrDef构造一个新的构造函数并把新的属性挂到该构造函数的prototype上this.attributes function(attrs) { var Attributes function() {}; if (this.attrDef) { Attributes.prototype new this.attrDef; // 继承已有的属性定义 } for (var name in attrs) { Attributes.prototype[name] attrs[name]; // 新属性叠加在原型链更外层 } this.attrDef Attributes; };由于属性定义通过原型链层层叠加实例化时查找属性会优先命中组件模块先定义的值mixin 中同名属性被自然让位从而实现了mixin 提供默认值、组件定义覆盖默认值的效果。这也与 Component API 文档 中attachTo(selector[, options])传入的 options 覆盖组件默认attr的机制一脉相承。从既有 Component 派生新组件Component.mixin已有的 Component 可以作为基础组件base component在此基础上派生出更多组件。典型场景假设你希望项目里所有组件都具备某种触摸屏行为并且都要覆盖 Flight 默认的trigger函数。与其把这些 mixin 逐个加到每个组件上不如先用它们创建一个基础组件components/base让所有其他组件去继承它// components/base.js var flight require(flightjs); var withTouchScreen require(mixins/with_touchscreen); var withCustomTrigger require(mixins/with_custom_trigger); module.exports flight.component(withTouchScreen, withCustomTrigger);然后Component 构造函数上提供了一个mixin方法可以用它基于原组件创建出一个新的 Component 构造函数// components/shopping_cart.js var Base require(components/base); module.exports Base.mixin(shoppingCart); function shoppingCart() { //.. }这样shoppingCart组件就同时继承了withTouchScreen、withCustomTrigger以及自己定义的 core mixin 行为。从 lib/component.js 的源码可以看到Component.mixin的实现是通过Object.create(Component.prototype)创建基于原原型的新原型对象复制mixedIn数组记录已混入的 mixin避免派生后重复混入和defaults/attrDef保留属性默认值定义对新原型调用compose.mixin(newPrototype, arguments)混入传入的新 mixin返回一个全新的 Component 构造函数。值得注意的是Base.mixin(shoppingCart)与flight.component(shoppingCart, withTouchScreen, withCustomTrigger)在效果上是等价的但前者避免了在派生组件里重复罗列基础 mixin且会保留基础组件上已有的属性默认值attrDef更利于维护统一的基础能力基线。实战总结mixin 的完整使用模式综合以上内容mixin 在 Flight 项目中的典型组织方式如下场景推荐用法关键 API定义可复用功能集导出普通函数函数内this.xxx function(){}无不调用flight.component应用到组件作为参数传入flight.componentflight.component(coreFn, mixinA, mixinB, ...)应用到普通对象 / 另一个 mixin直接调用 compose 模块flight.compose.mixin(this, [withMixin])提供属性默认值且不覆盖组件定义在 mixin 内调用this.attributes({...})attributes原型链叠加组件优先基于既有组件派生新组件调用组件构造函数的 mixin 方法Base.mixin(newCoreFn)关键机制回顾去重compose.mixin通过mixedIn数组保证同一 mixin 只混入一次lib/compose.js防覆盖混入期间临时锁定目标对象属性可写性避免 mixin 意外覆盖既有方法lib/utils.js属性继承attributes通过原型链层层叠加mixin 的默认值让位于组件自身的定义lib/base.js能力基线flight.component会自动混入withBase、withAdvice、withRegistration三个内置 mixin组件天然具备事件处理与注册能力lib/component.js。这些行为均有 test/spec/mixin_spec.js 中的测试用例直接验证你可以运行npm test参见 Makefile 与 package.json在本地复现。理解了 mixin 机制也就理解了 Flight 一切皆组合、组件通过事件通信 架构的基础——它让团队可以把 DOM 交互、数据拉取、动画等横切关注点拆成独立可测的 mixin 模块任意装配到不同组件上。赞分享前端Web框架【免费下载链接】flightA component-based, event-driven JavaScript framework from Twitter项目地址https://gitcode.com/gh_mirrors/fl/flight点击查看免费下载相关推荐5分钟掌握N_m3u8DL-RE跨平台流媒体下载终极指南5分钟掌握N_m3u8DL RE跨平台流媒体下载终极指南 你是否遇到过在线视频无法保存的烦恼那些精彩的课程、珍贵的直播、付费的内容只能在网页上观看想下载CLI音视频Yew框架中的组件属性(Properties)机制详解Yew框架中的组件属性 Properties 机制详解 引言为什么需要组件属性机制 在构建现代Web应用时组件化开发已成为主流范式。Yew作为Rust/W前端Web框架Zep与AutoGen集成为多智能体系统提供共享内存的终极指南Zep与AutoGen集成为多智能体系统提供共享内存的终极指南 在构建多智能体系统时如何让不同智能体之间高效共享和管理记忆是一个关键挑战。Zep作为一个快速AI AgentAI 应用Agent 框架RAGMCP 服务后端上一篇Nintendo Switch NAND管理神器NxNandManager完全指南下一篇Nintendo Switch NAND管理终极指南NxNandManager完整使用教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表