vnode caching works in the toy example

This commit is contained in:
Andreas Rumpf 2017-03-31 11:21:10 +02:00
commit 8da1ac07c0
5 changed files with 76 additions and 8 deletions

View file

@ -7,12 +7,12 @@
<body id="body"> <body id="body">
<div id="ROOT" />
<script type="text/javascript" src="nimcache/example.js"></script> <script type="text/javascript" src="nimcache/example.js"></script>
<script type="text/javascript"> <script type="text/javascript">
onload(window.location.pathname.split('/')[1]) onload(window.location.pathname.split('/')[1])
</script> </script>
<div id="ROOT" />
</body> </body>
</html> </html>

View file

@ -1,5 +1,5 @@
import vdom, karax, karaxdsl import vdom, karax, karaxdsl, jdict
when false: when false:
var plugins {.exportc.}: seq[(string, proc())] = @[] var plugins {.exportc.}: seq[(string, proc())] = @[]
@ -21,15 +21,24 @@ proc onTodoEnter(val: cstring) =
proc onclickHandler(ev: Event; n: VNode) = proc onclickHandler(ev: Event; n: VNode) =
let id = suffixAsInt(n.id, "remove:") let id = suffixAsInt(n.id, "remove:")
entries.delete(id) #entries.delete(id)
entries[id] = nil
var entryCache = newJDict[int, VNode]()
proc createEntry(i: int; d: cstring): VNode = proc createEntry(i: int; d: cstring): VNode =
# implement caching:
if entryCache.contains(i):
let old = entryCache[i]
return old
result = buildHtml(tr) do: result = buildHtml(tr) do:
td: td:
text d text d
td: td:
span(id="remove:" & $i, onclick=onclickHandler): span(id="remove:" & $i, onclick=onclickHandler):
text "[remove]" text "[remove]"
entryCache[i] = result
proc createDom(): VNode = proc createDom(): VNode =
result = buildHtml(tdiv) do: result = buildHtml(tdiv) do:
@ -42,7 +51,8 @@ proc createDom(): VNode =
enterInput("todo-input", "", onTodoEnter) enterInput("todo-input", "", onTodoEnter)
table(class = "wl"): table(class = "wl"):
for i, d in entries: for i, d in entries:
createEntry(i, d) if d != nil:
createEntry(i, d)
setRenderer createDom setRenderer createDom

11
jdict.nim Normal file
View file

@ -0,0 +1,11 @@
type
JDict*[K, V] = ref object
proc `[]`*[K, V](d: JDict[K, V], k: K): V {.importcpp: "#[#]".}
proc `[]=`*[K, V](d: JDict[K, V], k: K, v: V) {.importcpp: "#[#] = #".}
proc newJDict*[K, V](): JDict[K, V] {.importcpp: "{@}".}
proc contains*[K, V](d: JDict[K, V], k: K): bool {.importcpp: "#.hasOwnProperty(#)".}

View file

@ -138,9 +138,12 @@ proc dodraw() =
proc redraw*() = proc redraw*() =
# we buffer redraw requests: # we buffer redraw requests:
if drawTimeout != nil: when false:
clearTimeout(drawTimeout) if drawTimeout != nil:
drawTimeout = setTimeout(dodraw, 30) clearTimeout(drawTimeout)
drawTimeout = setTimeout(dodraw, 30)
else:
dodraw()
#proc prepend*(parent, kid: Element) = #proc prepend*(parent, kid: Element) =
# parent.insertBefore(kid, parent.firstChild) # parent.insertBefore(kid, parent.firstChild)

View file

@ -39,6 +39,21 @@ type
proc value*(n: VNode): cstring = n.text proc value*(n: VNode): cstring = n.text
proc `value=`*(n: VNode; v: cstring) = n.text = v proc `value=`*(n: VNode; v: cstring) = n.text = v
proc eq*(a, b: VNode): bool =
if a.kind != b.kind: return false
if a.id != b.id: return false
if a.class != b.class: return false
if a.kind != VNodeKind.text:
if a.kids.len != b.kids.len: return false
for i in 0..<a.kids.len:
if not eq(a.kids[i], b.kids[i]): return false
else:
if a.text != b.text: return false
if a.attrs.len != b.attrs.len: return false
for i in 0..<a.attrs.len:
if a.attrs[i] != b.attrs[i]: return false
result = true
proc setAttr*(n: VNode; key: cstring; val: cstring = "") = proc setAttr*(n: VNode; key: cstring; val: cstring = "") =
if n.attrs.isNil: if n.attrs.isNil:
n.attrs = @[key, val] n.attrs = @[key, val]
@ -80,3 +95,32 @@ iterator attrs*(n: VNode): (cstring, cstring) =
proc addEventListener*(n: VNode; event: EventKind; handler: EventHandler) = proc addEventListener*(n: VNode; event: EventKind; handler: EventHandler) =
n.events.add((event, handler)) n.events.add((event, handler))
template toStringAttr(field) =
if n.field != nil:
result.add " " & astToStr(field) & " = " & $n.field
proc toString*(n: VNode; result: var string; indent: int) =
for i in 1..indent: result.add ' '
if result.len > 0: result.add '\L'
result.add "<" & $n.kind
toStringAttr(id)
toStringAttr(class)
for k, v in attrs(n):
result.add " " & $k & " = " & $v
result.add ">\L"
if n.kind == VNodeKind.text:
result.add n.text
else:
if n.text != nil:
result.add " value = "
result.add n.text
for child in items(n):
toString(child, result, indent+2)
for i in 1..indent: result.add ' '
result.add "\L</" & $n.kind & ">"
proc `$`*(n: VNode): cstring =
var res = ""
toString(n, res, 0)
result = cstring(res)