SBind前端框架设计说明

核心应用

代码预览

index.html

1<html> 2 <head> 3 <title>SBind</title> 4 <script src="sbind.js"></script> 5 </head> 6 <body> 7 <script> 8 SBind.boot(); //启动SBind程序 9 history.hash = "main"; //跳到默认路由 10 </script> 11 </body> 12</html>

main.js

1//定义main视图 2SBind({ 3 route: 'main', 4 id: 'main', 5 events: { 6 'click .goBack': 'goBack' //返回到上一视图 7 }, 8 model: { 9 title: 'SBind框架演示', 10 text: '测试内容' 11 }, 12 template: '<component:header><div>{{= text }}</div>', 13 onShow: function() { 14 console.log('Hello World!'); 15 }, 16 goBack: function() { 17 history.back(); 18 } 19}); 20 21//定义header组件 22SBind({ 23 id: 'header', 24 events: { 25 'click #goDetail': 'goDetail' //跳到详细说明页 26 }, 27 model: { 28 goback: '返回', 29 detail: '详细' 30 }, 31 template: './header.html', 32 goDetail: function() { 33 SBind.navigate('detail'); 34 } 35});

header.html

1<div> 2 <div class="goBack">{{- goback }}</div> 3 <h1>{{- title }}</h1> 4 <div id="goDetail">{{- detail }}</div> 5</div>

生成的html

1<html> 2 <head> 3 <title>SBind</title> 4 <script src="sbind.js"></script> 5 </head> 6 <body> 7 <script> 8 SBind.boot(); //启动SBind程序 9 history.hash = "main"; //跳到默认路由 10 </script> 11 <div id="sbind_views"> 12 <div sb-route="main" id="mian"> 13 <div sb-component="header"> 14 <div class="goBack">返回</div> 15 <h1>SBind框架演示</h1> 16 <div id="goDetail">详细</div> 17 </div> 18 <div>测试内容</div> 19 </div> 20 </div> 21 </body> 22</html>

说明

开始

  • 入口文件index.html,在head引入sbind.js,在body使用SBind.boot()启动程序,在执行boot之前可使用SBind.config配置一些选项,选项内容待设计。改变history.hash跳转页面,作为默认路由设置。
  • 引入第三方插件,如jQuery,简单页面可使用普通script标签引入,大型应用可使用gulp等自动化构建工具用import导入
  • 脚本编写,给SBind传入一个对象,所有工作都是给SBind传入的对象配置选项。
  • 生成的dom元素上带有sb-route、sb-component等属性,方便调试排错。

选项

键名

类型

备注

id

String

唯一标识符,作为Component必填

route

String

路由,作为View必填

events

Object

定义事件

model

Object

定义数据

template

String

定义模板

onCreate

Function

SBind实例创建完成时执行一次

onInit

Function

初次路由到达,对应view添加到html时执行一次

onShow

Function

每次路由到达时执行

onHide

Function

每次从当前路由离开时执行

路由

  • hash改变为#main时,SBind自动查找views[main],如果没有对应实例则查找main.js加载并执行。执行过main.js后保存为views[main]。
  • 以script、script[type=text/html]、link[rel=sheetstyle]形式加载脚本、模板、样式,不使用xhr,避开跨域。
  • 禁止路由环路,例:A->B->C->D->B,历史记录删除C、D,在B执行back直接回A而不是D

组件

  • 带有route的SBind对象最终产物称为view实例,只有id的称为component,可以将view视为特殊的component。路由改变时对应的view会被插到body>div#sbind_views并执行onShow。
  • view的内容由对应的template编译而成,如果没有显式指定template,程序自动查找与脚本名称对应的html文件。例:main.js会查找main.html。
  • component依赖view存在,即component的配置要写在view的文件里,否则不能被加载到。除非使用自动化构建,该内容将在大型应用构建详细说明。
  • 只在模板里使用component:header即可自动查找相应组件,不需要像vue、angular等需要手动传入组件。
  • 组件继承,使用parent:"parentId"指定父组件,方法数据事件全部继承,原型链指向父组件方式实现。

模板视图

  • 模板不使用v-for,v-on,ng-repeat,ms-attr等指令,全部使用{{}}语法,如{{each items as item}},<div class="{{= active }}">

  • {{= data }}双向,输出字符串,相当于innerText

  • {{- data }}单向,输出字符串

  • {{# data }}双向,输出html,相当于innerHTML

  • {{+ data }}单向,输出html

  • {{if}}{{/if}}条件

  • {{each items as item i}}循环

  • {{ }}运行任意javascript代码

  • 支持管道过滤器,表达式运算

  • 模板解释引擎需要处理的类型:文本(textContent)、dom节点(Node)、类(className)、属性值(Attribute)、表单输入(input/select/textarea)、数组列表(Array)

    <ul> <!-- 循环 --> {{each items as item i}} <li data-id="{{- item.id | filter}}"> <div>{{= item.title }}</div>
    1 <!-- 嵌套循环 --> 2 {{each item as it j}} 3 <p>{{= it.text }}</p> 4 {{/each}} 5</li> 6{{/each}}
    </ul> <div class="toast {{= showClass}}"> {{# tips }} </div> {{if isButton}}<button>确定</button>{{/if}}

事件

  • 事件events,使用代理的方式绑定到view上,任凭view里的内容怎样变化都能监听到。定义方式参考butterfly,键名为事件加选择器,值为字符串或函数,当为字符串时,自动匹配view对应的方法。
  • 组件内定义的事件仅在该组件内生效,层级包含关系,例如view[main]定义的点击事件,由于component[header]在view[main]里,因此在view[main]和component[header]里匹配的元素都会响应该点击事件,而在compontent[header]里定义的事件,点击compontent[header]外的任何元素都无效。

支持委托的常用事件

事件名称

说明

click

需要类似fastclick事件库处理300ms延迟,fastclick原理是在touchend使用stopImmediatePropagation阻止将要执行的click事件,并使用new Event创建点击事件促使立即执行。可根据其原理将300ms延迟提速功能写入SBind核心库,并收集现已不存在300ms问题的userAgent

focusin<br>focusout

火狐浏览器不支持该组事件,webapp多数webkit内核,可不考虑火狐。如果需要支持火狐,可在目标dom元素上绑定focus/blur事件,这两个事件不支持冒泡,即无法委托

input

使用input事件,输入中文会遇到中文未进输入框,键码先上屏的问题,可监听compositionstart和compositionend处理中文输入

touchstart<br>touchmove<br>touchend

该组事件一般组合使用,扩展为长按,左划,右划等事件

keydown<br>keyup<br>keypress

一般使用input代替该组事件

change

各大主流浏览器都支持

mousedown<br>mousemove<br>mouseup<br>mouseover

IOS手机不支持该组事件,移动端没有鼠标,SBind主要面向手机市场,可忽略该组事件的应用

数据模型

  • 数据继承,header组件没有定义title,在渲染时,模板找不到title,会自动向上搜索,这一特性方便复用组件。
  • 双向绑定算法,先解释成抽象树,赋值,对dom作标记,不绑定dom。model数据变化时再查找dom绑定并处理。按需绑定可很大程度减少编译时间。

(PS:以前用PHP做的CMS系统处理静态文件也使用按需处理的方式,很大程度的降低服务器IO操作。传统的CMS系统用户每次保存数据都会自动生成静态html,使用404方式可在访客访问时才生成html,即请求访问时系统拦截404并将静态url转为动态url,并生成html返回给访客,如果动态url也404才给访客返回404)

问题

  • 事件集中写在events上,不知道哪个dom元素绑定了事件,会不会给维护带来困难?

不会,事实上分离事件更利于维护,只要在事件后面加上扼要备注,对应的dom便一目了然。

1events: { 2 'click #goBack': 'goBack', //返回上一页面 3 'click #submit': 'pay', //支付 4 'input #telBox': 'filterNum' //电话只允许输入数字 5}
  • 没有指令也算是一个完整的框架?

指令的功能无非就是绑定属性、事件和处理判断、循环,早期的前端模板引擎没有指令处理这些问题也毫不费力,SBind的模板语法算是复古写法。

  • 不配置路由表,维护时想查看有多少路由怎么办?

建议路由与对应view文件同名,这样看文件名就了解了。如果是自动化构建的应用,一次性注册所有SBind实例,可以输出SBind.routingTable查看所有路由。

大型应用

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

java中比较两个时间的差值

项目背景1.某篇文稿的发布时间是publishDate,例如:2020072118:00:41。2.现要求判断该篇文稿的发布时间是否在近30天之内。publicstaticlongdayDiff(DatecurrentDate,DatepublishDate){LongcurrentTimecurrentDat