#JSCommonUtil
PS:一些代码和思路来源于AngularJS avalon, 并加以修改。
页面模板众多,而又想依赖ajax做单页应用
支持chrome游览器,其他游览器暂时未测试,一般游览器支持Object.keys
Array.forEach
Array.map
ECMA5标准 的,基本上没什么问题
jquery
项目使用grunt作为自动化脚本环境, 使用jasmine和jasmine-jquery.js作为测试框架,并且做了一些即是demo还是说明的html页面,可供开发参考,由于demo会发送ajax请求views文件夹下的模板,所以需要运行在web容器下面
欢迎fork!
当前版本将重点放在模板渲染和模板与模板之间的数据变化相应。
jc.util
该对象现有两个常用的函数,暴露出来,以供大家使用
isInDocument
isInDocument(parent,child)
判定子节点是否存在,(当子节点和传入的父节点是同一个时,返回true),
当参数为一个时,判定该节点是否在当前页面body内
nextUid
在当前页面产生一个唯一的id标识
jc.Array
该对象内封装了多个函数groupBy
group
objToArr
isEqual
getIndex
contain
getDistinct
replaceElem
.具体说明,可参照src/arrayHelper.js
里的注释,用法可参照test/arrayHelperSpec.js
,如果在开发中遇到数据转换的问题,可以使用这个对象内的方法。
groupBy
group
两个函数都是用来对数组进行分组的。
objToArr
将object对象的key和value转换成数组。
isEqual
对数组进行深度判定值是否相等。
getIndex
根据提供的参数,数据这个元素在数组中的下表。
contain
判定数组中是否拥有某个元素,支持数组元素是是对象的判定。
getDistinct
数组去重,仅支持Array类型。
replaceElem
根据查找条件找到对象并替换掉
jc.mix
用来做javascript继承(父子继承和数据复制),code from jquery。这个函数在做模板间互动时,会减少一些工作量。
jc.mix(bool,child,parent)
,bool
参数代表着是深度copy,还是浅copy(当parent
有个object|array属性时,浅copy会将这个属性引用赋值给子类,而深copy则是遍历父类的集合属性)。
具体如何用,可参考prepareSpec.js
中关于该函数的测试用例。
jc.initPB
订阅发布模块,可用来创建自己的一套发布订阅机制,功能会随着版本的叠加而增强。现在还没有过滤器概念。但拥有channel
,参考pubsubSpec.js
中关于该函数的测试。
jc.getType
从avalon中拿过来的关于类型判定的函数,支持boolean number string function array date regexp object error
的类型判定。返回值皆为小写。基本用法为
if(jc.getType(unKnownType)==='object'){
//TODO
}else{
//TODO
}
在解释模板数据之前,需要解释一个名词模板实例
。模板实例是指将模板插入到指定的dom中,并通过数据渲染,这时便成称之为模板实例。一个模板可以有多个实例。模板实例可通过jc.th($jquerySelector)
获取。
模板数据,就是和模板实例绑定在一起的数据。通过模板的写,它可以监管模板实例view层变化,并反映在数据中。用户只需要操作模板数据即可,不需要再过多的关注view。模板数据以通过jc.th($jquerySelector).data()
获取。
使用JSCommonUtils需要特别关注模板数据的操作与构建,好的模板数据构建会使模板更容易维护。所以,在写模板之前,请一定要思考好模板数据如何构造。jc.mix
jc.Array.objToArr
函数在构建模板数据时会很有用。
当要更改更改数组中的值时,请使用
data.array.set($index,value)
方法。这样才会触发变化
jc.render
jc.render(data,url,$jquerySelector,callback,options)
//data:模板数据
//url:地址,.html 要省略掉
//$jquerySelector 要确保选择器选出来的存在且唯一,否则抛出异常
//callback:回调函数,并为其传递进当前模板实例引用
//options 暂时还没有用,以后可能会扩展一些函数
整个项目中重要的函数,用来调用模板渲染函数scanNodes
以及对模板状态的更新。具体说明可参考src/documentParse.js
内关于此函数的注释
注意,jc.render内部执行了异步调用模板ajax请求,所以关于当前模板实例的业务逻辑都需要写到 回调函数中。
现在已开发的标签有jc-if
jc-repeat
jc-reuse
jc-bind
jc-cal
jc-duplex
jc-dupfilter
jc-value
jc-reset
jc-attr
jc-foreach
jc-class
, 注意:如果使用了未被定义的标签,会自动调用jc-cal
来进行匹配,例如 :
<intput jc-value="..."/>
<intput jc-cal-value="..."/>
这两种使用方式等价
jc-if
<div jc-if='abc'>
...
</div>
jc-if
表示是否该div存在于dom中,如果abc
为false|undefined|''|0,则会删除此div,且其子元素不会没扫描。jc-if-not
和jc-if
正好相反,如果abc
为false|undefined|''|0,则显示该div,并扫描子元素。jc-if-loop
则是和jc-repeat
一块使用,可参看关于jc-repeat
标签的讲解jc-if
jc-if-not
在渲染自由度比较大的模板时,会被大量用到
jc-repeat
<ul>
<li jc-repeat-elem='arr' jc-if='isShow' jc-if-loop='this.$index%2===0'>{{$index}}: {{elem}}</li>
</ul>
数据
var data={
arr:[1,2,3],//data:[1,2,3]
isShow:true
}
//当要渲染上面的li元素时,data会依据当前要渲染的数组元素生成新的数据结构
{
elem:$arrayData,//data.arr[$index]
$index:$num,
$data:data,
$path:$string,//当前元素索引
$isForEach:$boolean//当前是否是在渲染repeat元素
}
//来渲染li元素
//如果数组元素是一个object时,会生成下面的数据结构
{
elem:{
$objectData,
$index:$num,
$path:$string//当前元素索引
},
$data:data,
$isForEach:$boolean//当前是否是在渲染repeat元素
}
//所以,模板数据的key值最好不要以`$`开头,有可能会被框架内部的值覆盖掉
jc-repeat-$param
用来循环当前元素。$param
用来做模板写数据的索引,以$_
或字母开头
在jc-repeat
中,包含了额外的元素
jc.render
的模版数据在使用jc-repeat
的时候,会遇到嵌套的情况,请参考test-repeat.html
关于jc-repeat
使用。需要注意的是:
jc-repeat
不支持遍历object,可通过jc.Array.objToArr
函数来进行转换。$param
参数不要以$
开头,并且最好不要和索引路径同名称jc-if
jc-repeat
是有先后顺序的,先判定jc-if
是不是要渲染,再来判定jc-repeat
当使用jc-repeat
嵌套时,当嵌套的最里面为一个值数组时,直接使用$index,$path 即可获取值,如果为object数组时,需要elem.$index,elem.$path来获取值。且嵌套的内层可获取外层的值索引,而外层无法获取内层值索引。 当更改集合内的数据时,请使用set($index,$value)
方法。例如 {a:[1,2,3]},可以使用a.set(2,5)将数据改为{a:[1,2,5]}。直接使用a[2]=5进行 赋值的话,不会触发响应关于此数据的变化。
jc-foreach
jc-foreach
标签是jc-repeat
标签的补充,性能上有所下降,能用jc-repeat
标签的话,不要使用jc-foreach
,`jc-foreach是用来迭代内部元素的,例如,循环
dl中的
dt dd元素。这种功能是
jc-repeat`标签力所不逮的。
<div jc-foreach-e='....'>
<!--循环内部-->
<div>
jc-cal
<div jc-cal-data='...'>
</div>
jc-cal-$any
会计算表达式的值,然后以 $any='计算后的结果' 插入到当前元素的attribute中,如果当前dom已有该attribute,会被覆盖掉。
任何未被框架声明处理的jc-$any
,都会转化成jc-cal-$any
来进行处理
注意:
jc-cal-class
被做了特殊处理,会以addClass的形式添加进当前对象中,不会进行覆盖
jc-attr
jc-attr-$any
和jc-cal标签都是作用在element上的attribute,但jc-attr
和jc-cal
相比,多了模版数据变化触发模版实例变化的功能。
注意: jc-attr 不支持 jc-attr-class 。
jc-value
<input jc-value='data|filter'/>
<textarea jc-value='...'></textarea>
jc-value
会和jc-cal-value
效果功能差不多,唯一不同的是当在textarea
html标签中使用时,jc-cal-val
不会起作用(<textarea>{{....}}</textarea>
也不会起作用)。
jc-reset
<input jc-reset value='重置'/>
<button jc-reset >重置</button>
jc-reset-$event
用来重置当前表单,$event 为触发重置表单的事件,默认为click
请不要使用
<input type='reset' value='重置'/>
,它不会触发jc-bind
和jc-duplex
标签效果
jc-class
<div class='afg' jc-class-$any='isOk'>
</div>
jc-class-$any
是专门为class设计的,当表达式结果为true时,$any就会加到当前元素的class中去,如果为false,则会从中去除$any
jc-reuse
<div jc-reuse='tag1'>
....
</div>
js
jc.th(...).reRender('tag1',data)
该标签是用来标明其子元素可能会被重新彻底渲染。jc-reuse
标签子元素的html会被缓存起来,并用其属性值作为标记,用户可以使用jc.th(...)reRender
来把其重新渲染一边。注意,传递个reRender的值会更改模版数据。该标签是本框架未完善时的过渡标签,以后可能会废弃掉。
jc-bind
jc-bind-$event
用在表单元素上,将view层的变化传递给模板数据。$event为触发事件,不写的话,会根据表单元素的不同特性进行默认。且根据表单元素的特点传递给模板数据的值类型也不尽相同,在设计上,尽量符合游览器表单元素基本使用情况。
下面是数据转化:
mousemove
mouseleave
等表单事件input number 如果输入值不正确的话,是不会触发模板数据变化
jc-bind
的工作原理,是先判定当前元素的类型,根据类型选定默认触发事件和值处理方法, 然后绑定更改模板数据的函数到该元素上,当事件发生时,便会执行该函数
jc-duplex
和jc-dupfilter
<input type='text' jc-duplex='a' />
<input type= 'checkbox' jc-duplex='check|sampleMap(true,enable,false,disable)' jc-checked='check|toBoolean(enable)' jc-dupfilter='|toBoolean(enable)'/>
jc-duplex-$event
是在jc-bind
的功能之上,做的扩展,支持模板数据变化,触发view层也跟着变化。
如果jc-duplex
的表达式使用了过滤器,必须在相同的节点上使用jc-dupfilter
用来写反向过滤器,使之view数据和模板数据可以相互转换
用了
jc-duplex
不需要再写jc-bind
标签 关于jc-duplex
和jc-bind
如何使用,请参考test_bind.html和test_duplex.html
JSCommonUtil默认{{...}}
{{#...}}
作为表达式在TextNode中的包裹标签,不支持{{...{{...}}...}}嵌套使用,如果想改,可以通过jc.config.interpolate(array)来配置(from avalon),
{{...}}
仅仅是计算框内的值然后渲染到页面中去,{{#...}}
则在会渲染后,会将当前渲染的textNode和模板数据进行绑定,如果模板数据产生了变化,页面也会变化。
关于{{...}}的具体使用,可参考test-textExpression.html
文件。
表达式分为两部分,第一部分数值计算-值索引
,第二部分过滤器
(也可以称之为文本转换器)
用法:{{数值计算-值索引|过滤器1|过滤器2...}}
要想熟练使用,需要理解其原理。
值索引:
//var UniObj ={}
function dotPath(object, path) {
var re = object;
path.split(".").forEach(function(v) {
if (re[v] === undefined) {
re = UniObj
} else {
re = re[v]
}
});
if (re !== UniObj) {
return re;
}
}
数值计算:
var noop=function(){}
//value 就是表达式中的第一部分,data为数据
Function.apply(noop, ["return " + value]).call(data)
所以,当使用数值计算模式时,是需据要this关键字来索引数,请注意:
jc-duplex
,jc-bind
标签不支持数值计算模式
表达式如果是要索引数组数据,会和js数组索引有所区别:
var data={arr:[1,2,3]}
// {{arr.0}} 正确
// {{arr[0]}} 错误
// {{this.arr[0]}} 正确 但是不推荐如此用,性能会降低一些
过滤器用来转换表达式第一部分计算结果成其它返回值。过滤器接收参数但会将参数转化为字符串,例如
{{value|defaultVal(默认值)}}
,默认值
会转化成字符串传递进defaultVal过滤器函数。
现在框架内部实现了三个过滤器。
defaultVal
当模板数据根据索引找出来的值为undefined或者null时,就会转换为第一个参数。没有参数的话,会默认为空字符串toBoolean
返回true or false ,当有参数的时候,会将索引出来的值和参数做比较,相同,为true,不同为falsesampleMap
简单的值映射,可参考上面的例子 。注意: {{...}}只能在textNode中使用,不能在attribute中使用,而如果在下列 area,base,basefont,br,col,command,embed,hr,img,input, link,meta,param,source,track,wbr,noscript,script,style,textarea html标签内,表达式不会被处理 以后可能会根据需求,将textarea开放出来,现在可用
jc-value
标签来做关于textarea的开发。
具体例子可参照常规页面联动.html
。如果数据结构比较混乱时,可参照test-th-pb.html
。
jc.th
函数会返回一个方法对象,里面提供类似jquery的empty
html
hide
show
等方法。
listen
listen($path,$targetDivs,$targetPath)
主要是用来监听其他模板数据变化并更改自己的模板数据,具体参考test-th-pb.html
中的用法,这个函数的参数十分灵活,当目标模板实例和原模板实例 模板数据结构相同时,
可以直接listen($path,$targetDivs)
使用,$path可以是数据,字符串,object。他们都会在内部被转化成寻址数组
注意:监听数组内的具体数据时,最好再监听下整个数组变化,如果数组被调用Array方法或重新赋值时,通知范畴是以数组为单位的。
bind
bind($path,function,fnName)
用来绑定一个function,可以通过对函数命名来分类,方便批量unbind
。在绑定函数列表中,他们的执行是按照绑定的先后顺序来执行的。如果出现了bug,可以使用jc.th.$pb.fn.$jcQueue
和jc.$watchPB.fn.$jcQueue
查看当前系统内的函数绑定状态(jc.th($div)._data("id")
可以获得模板实例的唯一标识)
unbind
unbind(fnName)
解除绑定的函数,当传递进$all
时,会删除掉整个绑定在该模板的函数。
reRender
*deprecated*
reRender
方法要和jc-reuse
标签搭配使用,使用jc-reuse
表明该元素的子元素会被重用,然后使用reRender
方法重新渲染这一块元素。注意,当你
想用该组合时,可以思考有没有更好的写法来替代它。
empty
empty
会将当前模版实例从dom中移除掉,并去除响应的事件监听,以达到节约内存的目的
如果模板要清空的话,请使用
jc.th($jquerySelect).hide()
jc.th($jquerySelect).show()
等来操作模板状态的变化。
getCleanData
渲染后的模版数据是有可能含有额外的$index $path
值的,如果想获取纯净的数据,直接jc.th($selector).getCleanData()
即可
如果需要更改当前dom的,请扩展 jc.scanMod
对象,如果是对值进行转换(表达式的过滤器)的,例如将id转换为具体的名称,可扩转jc.filters
,如果需要根据当前dom进行模板数据操作,可扩展jc.bindMod
。注意: jc-id
标签保留,可能会在后面的版本中使用
#####配置
//默认配置
jc.config={
tplRootUrl:'./views/',//默认取模版的根目录
}
jc.config.interpolate(['{{','}}']) //默认文本计算符
1.1.0
$broadcast
$emit
of Angulararray.length=0
bug框架写的时候,想的很多,然后写了一些较为复杂的代码,后来才发现,既然用最简单的方法能实现,就不要追求复杂的东西,虽然复杂带来了一些 想像上的性能提升,但随之而来的bug更会让人头疼。所以,code simple to happy!
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。