render: (@virtualDomDefine, scope = {}, doneOrAsync = ->)->
@_status = 1
@emit 'beforeRender'
scopeKeys = objectKeys scope
scopeLen = scopeKeys.length
if scopeLen == 0
@renderQueue doneOrAsync
else
ix = scopeLen - 1
each scopeKeys, (v, k)=>
@set v, scope[v], k == ix and doneOrAsync or null
this
_render: (done)->
scope = extend true, @scope
{virtualDom} = @virtualDomDefine scope, @
if @virtualDom == null
@virtualDom = virtualDom
@refs = @virtualDom.render()
each @_initTask, (task)-> task()
@_initTask = []
else
patches = diff @virtualDom, virtualDom
@virtualDom = virtualDom
patch @refs, patches
@_status = 2
@emit 'rendered', @refs
done @refs if isFunction done
renderQueue: (doneOrAsync)->
nextTick.clear @_queueId
if true == doneOrAsync
@_render()
else
@_status = 1
@_queueId = nextTick =>
@_render doneOrAsync
addEvent: (event, el, callback, id)->
event = event.toLowerCase()
@_events[event] or= []
isIn = false
each @_events[event], (e)->
if e.id == id
isIn = true
e.callback = callback
return false
if false == isIn
@_events[event].push
el: el
callback: callback
id: id
@addEventListener event
removeEvent: (event, el, id)->
return if !@refs
event = event.toLowerCase()
return if false == @_events.hasOwnProperty(event)
each @_events[event], (e, i)=>
if e.id == id
@_events[event].splice i, 1
return false
if @_events[event].length == 0
removeEvent @refs, event, @_eventListener[event]
regEventCallback: (event)->
@_eventReged.push event
@_eventListener[event] = (e)=>
tasks = @_events[event]
each tasks, (task)=>
if task.el == e.target or nodeContains task.el, e.target
res = null
args = [e, task.el]
callbackName = task.callback
if isArray task.callback
_args = task.callback
callbackName = _args[0]
each _args, (arg, k)->
args.push arg if k > 0
if @_proxy and isFunction @_proxy[callbackName]
res = @_proxy[callbackName].apply @_proxy, args
else if isFunction callbackName
res = callbackName.apply @, args
else if isFunction @[callbackName]
res = @[callbackName].apply @, args
else
console.log task.callback
throw new Error 'not callback : ' + task.callback
if false == res
if e.stopPropagation and e.preventDefault
e.stopPropagation()
e.preventDefault()
else
window.event.cancelBubble = true
window.event.returnValue = false
return false
addEventListener: (event)->
if !@refs
@_initTask.push => @addEventListener event
return
if event not in @_eventReged
@regEventCallback event
addEvent @refs, event, @_eventListener[event]
date 2016-01-09 16:39:56, author vfasky vfasky@gmail.com, and link http://vfasky.com
基于 virtual dom 的模板引擎