一个合理的微应用框架,具有实用的可重用性。
el.js是一个构建在 Riot.js 模板之上的框架,用于构建微应用程序。
Web 框架要求开发人员将大部分(如果不是全部)网页构建为动态 Web 应用程序。这使得开发人员能够确保网页上的所有内容都遵循他们可以推理的单一一致、可预测的渲染流程。然而,与传统的静态网站相比,它也存在许多缺点,包括更复杂的缓存方案、更长的加载时间和 SEO 问题。微应用为这些缺点提供了强大的解决方案。不要构建巨大的整体 Web 应用程序,而是构建小型应用程序并将它们嵌入到静态页面中。
微应用程序执行一个小且范围非常狭窄的功能,可以一次又一次地重用。微应用程序与框架成为标准之前的可嵌入小部件的想法没有太大区别,但它们在执行上有所不同,因为它们强调对合理框架和实际可重用性的依赖。
HTML:索引.html
< html >
< head >
<!-- Head Content -->
< link rel =" stylesheet " src =" https://cdn.jsdelivr.net/gh/hanzo-io/el-controls/theme.css " />
</ head >
< body >
< my-form >
< div >
< label > Type Your Name </ label >
<!-- bind my-input to parent(my-form).data.name, parent.data is implicit for what is supplied to bind attribute -->
< my-input bind =' name ' />
</ div >
< div >
< span > Your Name Is </ span >
< span > { data.name } </ span >
</ div
</ my-form >
<!-- el.js Library -->
< script src =" https://cdn.jsdelivr.net/gh/hanzo-io/el.js/el.min.js " > </ script >
< script src =" my-script.js " > </ script >
</ body >
</ html >
JS:我的脚本.js
// window.El is the global value
// El.Form extends El.View and validates bound El.Inputs
class Form extends El . Form {
constuctor ( ) {
// data contains your state
this . data = {
name : '?' ,
}
// your custom tag name
this . tag = 'my-form'
super ( )
}
}
Form . register ( )
// El.Input extends El.View and binds to updating El.Form values
class Input extends El . Input {
constructor ( ) {
// your custom tag name
this . tag = 'my-input'
// the default this.change function works with all basic html inputs(<input>, <textarea>, ...).
this . html = '<input onkeydown="{ change }" />'
super ( )
}
}
Input . register ( )
El . mount ( '*' )
将此标签添加到自定义脚本和依赖项以及引用 window.El 之前的底部。
< script src =" https://cdn.jsdelivr.net/gh/hanzo-io/el.js/el.min.js " > </ script >
通过 NPM 安装
npm install el . js -- save
支持 CommonJS
var El = require ' el.js '
或 ES6 导入
import El from ' el.js '
El.Form引用此类型来存储用于验证与name关联的字段的信息。
姓名 | 类型 | 默认 | 描述 |
---|---|---|---|
配置 | MiddlewareFunction或 [ MiddlewareFunction ] | 不明确的 | 该类型存储用于创建validate() 的原始MiddlewareFunction或MiddlewareFunctions |
姓名 | 细绳 | ” | 这是该类型的其余部分引用的El.Form数据属性上的字段名称。 |
参考 | 参考树 | 不明确的 | 这是一个指向可变数据树的链接,可以通过调用 this.ref.get( name ) 来检索name的值 |
姓名 | 类型 | 描述 |
---|---|---|
证实 | (参考树,字符串)=> Promise | 此方法使用 Promise 串行调用所有MiddlwareFunctions 。 |
该类型用于定义El.Form的中间件。使用这些函数进行验证和输入清理,例如:
function isRequired ( value ) {
value = value . trim ( )
if ( value && value != '' ) {
return value
}
throw new Error ( 'Required' )
}
这种类型在内部使用,以方便通过引用返回承诺。
这是所有 El 类的基类。每个El.View都对应一个自定义标签。扩展此类以创建您自己的自定义标签。
姓名 | 类型 | 默认 | 描述 |
---|---|---|---|
CSS | 细绳 | ” | 这是一个代表标签 CSS 的字符串。安装时,它会在标签底部为每个类注入一次。 |
数据 | 参考树 | 不明确的 | 该属性存储标签的状态。 |
html | 细绳 | ” | 这是一个表示标签内部 html 的字符串。 |
根 | HTML元素 | 不明确的 | 此属性存储对网页中已安装视图绑定到的标签的引用。 |
标签 | 细绳 | ” | 这是自定义标签名称。 |
姓名 | 类型 | 描述 |
---|---|---|
初始化之前 | ()=> | 这里的代码在标签初始化之前执行。 |
初始化 | ()=> | 这里的代码在标签初始化时但在安装之前执行。推荐- 如果您需要绑定到标签的生命周期,请在此处执行。 |
日程更新 | () => 承诺 | 此方法安排异步更新调用。如果存在嵌套视图,它会在最顶层视图中批量更新调用。它返回更新执行时间的承诺 |
更新 | ()=> | 此方法更新标签。这是在网页触发事件后隐式调用的。对于这种情况,请参阅“简单表单示例”中的 onkeydown。手动调用该方法来更新标签。推荐- 建议手动调用scheduleUpdate(),以防止同步更新级联。 |
每个El.View都是一个事件发射器。请参阅 riot.observable 了解更多文档,http://riotjs.com/api/observable/
姓名 | 类型 | 描述 |
---|---|---|
El.View.register | ()=> | 这会向渲染引擎注册当前的自定义标签。定义标签后调用它 |
此类用于表示表单以及更复杂的 IO 驱动的微应用程序。此类提供通用表单验证和表单提交逻辑。
姓名 | 类型 | 默认 | 描述 |
---|---|---|---|
配置 | 目的 | 不明确的 | 向MiddlewareFunction或MiddlewareFunctions数组提供名称映射。有关详细信息,请参阅MiddlewareFunction 。 |
输入 | 目的 | 无效的 | configs中的每个元素都会转换为input中的元素。不建议直接修改。 |
姓名 | 类型 | 描述 |
---|---|---|
初始化 | ()=> | 这里的代码在标签初始化时但在安装之前执行。调用initInputs(),因此手动调用它 - 或者在 ES6 中调用 super()。推荐- 如果您需要绑定到标签的生命周期,请在此处执行。 |
初始化输入 | ()=> | 编译配置并将发出的结构分配给input 。像configs这样的输入包含对data中指定字段的引用。 |
提交 | (事件)=> 承诺 | 此方法会触发对configs中定义的data中每个字段的验证。该方法应作为事件处理程序/侦听器调用。如果验证成功,它会调用submit() ,并在验证成功/失败时返回一个承诺 |
_提交 | ()=> | 此处的代码在调用Submit()期间验证表单时执行 |
这是构建表单输入和 IO 控件的基类。
姓名 | 类型 | 默认 | 描述 |
---|---|---|---|
绑定 | 细绳 | ” | 此属性确定绑定到父表单数据中的哪个字段。 |
抬头 | 细绳 | ” | 与bind相同,已弃用。 |
错误信息 | 细绳 | ” | 此属性设置为 this.input.validate 返回的 Promise 捕获的第一条错误消息。 |
输入 | 输入类型 | 无效的 | 该属性是根据父数据的字段绑定指定的内容从父表单的输入属性中获取的。 |
有效的 | 布尔值 | 错误的 | 该属性用于确定输入所处的验证状态。它在调用 this.input.validate 时设置,只有在 this.input.validate 返回的 Promise 完全执行时才会设置为 true。 |
姓名 | 类型 | 描述 |
---|---|---|
改变 | (事件)=> | 此方法更新输入,然后验证它。该方法应该由事件处理程序/侦听器调用。 |
改变了 | ()=> | 当 this.input.validate 返回的 Promise 完全执行时调用此方法。 |
清除错误 | ()=> | 此方法将errorMessage设置为 '' 并在验证之前调用。 |
错误 | (错误)=> | 该方法设置errorMessage并在验证失败时调用。 |
获取值 | (事件)=> 任何 | 该方法从输入中获取值。默认情况下,此方法返回Event的 target.value。 |
证实 | (PromiseReference?) => 承诺 | 此方法验证输入,它通过引用(内部需要)和值返回代表验证成功和失败的 Promise。 |
姓名 | 类型 | 描述 |
---|---|---|
El.scheduleUpdate | ()=> | 安排页面上所有微应用的更新。 |
el.js的生命周期函数继承自 Riot.js。
el.js使用引用树来存储其表单数据。
根据您自己的数据结构的引用实现 get、set、on、once、off 方法,并将其作为数据属性放入。
容器是一种自定义标签,提供用于其内部模板的方法,并且其内容可以完全覆盖(仅包含一个或多个标签中的内容)。控件是与用户交互的组件,其目的是以有趣的方式显示信息或获取输入(例如输入、选择或 GoogleMaps 嵌入)。
不要以紧密耦合的方式构建小部件,而是将小部件分解为容器和控件,以最大限度地提高可重用性。以最有意义的方式构建内部 html。然后,向用户发布已完成的小部件、容器和控件,以便他们可以根据自己的各种需求自定义小部件。
通过像这样抽象您的 ui 元素,其他人可以更轻松地重用和自定义您的代码。请参阅 shop.js 了解实现。
最好使用单个高级状态存储来简化网页或整个网站的状态保存和恢复。
这可以通过为页面上的所有顶级容器提供相同的数据字段来完成。通过初始挂载调用
var data = {
state0 : 0 ,
state1 : 1 ,
}
El . mount ( '*' , { data : data } )
与普通的 Riot 渲染不同, el.js允许通过渲染上下文的原型继承隐式访问 this.parent 和 this.parent...parent 上的值。这样做是为了避免通过嵌套容器重复传递相同的数据,因为它容易出错且过于冗长。这也使得构建容器和控件变得更加容易。
显式传递数据变量:
< my-container-1 >
< my-container-2 data =' { data } ' >
< my-container-3 data =' { data } ' >
value: { data.value1 }
</ my-container-3 >
< my-container-3 data =' { data } ' >
value: { data.value2 }
</ my-container-3 >
</ my-container-2 >
< my-container-2 data =' { data } ' >
< my-container-3 data =' { data } ' >
value: { data.value3 }
</ my-container-3 >
< my-container-3 data =' { data } ' >
value: { data.value4 }
</ my-container-3 >
</ my-container-2 >
</ my-container-1 >
// El.mount passes data to the top level container of each micro-app
El . mount ( '*' , data : { value1 : 1 , value2 : 2 , value3 : 3 , value4 : 4 } )
相当于隐式引用数据变量。
< my-container-1 >
< my-container-2 >
< my-container-3 >
value: { data.value1 }
</ my-container-3 >
< my-container-3 >
value: { data.value2 }
</ my-container-3 >
</ my-container-2 >
< my-container-2 >
< my-container-3 >
value: { data.value3 }
</ my-container-3 >
< my-container-3 >
value: { data.value4 }
</ my-container-3 >
</ my-container-2 >
</ my-container-1 >
// El.mount passes data to the top level container of each micro-app
El . mount ( '*' , data : { value1 : 1 , value2 : 2 , value3 : 3 , value4 : 4 } )
BSD