Merge branch 'draft/refs' of https://github.com/bluenote10/karax into bluenote10-draft/refs

This commit is contained in:
Araq 2017-06-17 00:00:38 +02:00
commit e68d92d22a
6 changed files with 89 additions and 3 deletions

View file

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<meta charSet="utf-8"/>
<title>Refs</title>
</head>
<body id="body">
<div id="ROOT"></div>
<script type="text/javascript" src="nimcache/demo.js"></script>
</body>
</html>

56
experiments/refs/demo.nim Normal file
View file

@ -0,0 +1,56 @@
include karaxprelude
import future, sequtils
type
CustomRef = ref object of VNodeRef
method onAttach(r: CustomRef) =
kout(cstring"custom ref attached")
method onDetach(r: CustomRef) =
kout(cstring"custom ref detached")
var
modelData = @[5, 2, 4]
refA = VNodeRef()
refB = VNodeRef()
refC = CustomRef()
refSeq = newSeq[VNodeRef]()
proc onClick(ev: Event, n: VNode) =
modelData.add(0)
proc showRefs() =
kout(refA)
kout(refB)
kout(refC)
kout(refSeq.map(nref => nref.vnode))
proc secureRefSlot(i: int): VNodeRef =
while refSeq.len <= i:
refSeq.add(VNodeRef())
result = refSeq[i]
proc view(): VNode =
result = buildHtml():
tdiv:
button(onclick=onClick):
text "click me"
# storing refs to single elements is straightforward now
if modelData.len mod 2 == 0:
tdiv(nref=refA):
text "A"
tdiv(nref=refB):
text "B"
tdiv(nref=refC):
text "C"
# It's a bit more tricky when containers are involved:
for i, x in modelData.pairs:
tdiv(nref=secureRefSlot(i)):
text "List item: " & $x
proc renderer(): VNode =
view()
setRenderer(renderer, showRefs)

View file

@ -0,0 +1 @@
--path: "../../src"

View file

@ -79,8 +79,16 @@ proc wrapEvent(d: Node; n: VNode; k: EventKind; action: EventHandler) =
# --------------------- DOM diff -----------------------------------------
template detach(n: VNode) = n.dom = nil
template attach(n: Vnode) = n.dom = result
template detach(n: VNode) =
if not n.nref.isNil():
n.nref.vnode = nil
n.nref.onDetach()
n.dom = nil
template attach(n: VNode) =
if not n.nref.isNil():
n.nref.vnode = n
n.nref.onAttach()
n.dom = result
proc vnodeToDom(n: VNode; kxi: KaraxInstance): Node =
if n.kind == VNodeKind.text:

View file

@ -4,7 +4,7 @@ from strutils import startsWith, toLowerAscii
const
StmtContext = ["kout", "inc", "echo", "dec", "!"]
SpecialAttrs = ["id", "class", "value", "key", "style"]
SpecialAttrs = ["id", "class", "value", "key", "style", "nref"]
proc getName(n: NimNode): string =
case n.kind

View file

@ -101,6 +101,9 @@ macro buildLookupTables(): untyped =
buildLookupTables()
type
VNodeRef* = ref object of RootObj
vnode*: VNode
EventHandler* = proc (ev: Event; target: VNode) {.closure.}
VKey* = int
@ -108,6 +111,7 @@ type
kind*: VNodeKind
key*: VKey
id*, class*, text*: cstring
nref*: VNodeRef
kids: seq[VNode]
# even index: key, odd index: value; done this way for memory efficiency:
attrs: seq[cstring]
@ -118,6 +122,10 @@ type
dom*: Node ## the attached real DOM node. Can be 'nil' if the virtual node
## is not part of the virtual DOM anymore.
method onAttach*(v: VNodeRef) {.base.} = discard
method onDetach*(v: VNodeRef) {.base.} = discard
method changed*(v: VNodeRef): bool {.base.} = false
proc value*(n: VNode): cstring = n.text
proc `value=`*(n: VNode; v: cstring) = n.text = v