vugu / vugu

Vugu: A modern UI library for Go+WebAssembly (experimental)
https://www.vugu.org
MIT License
4.8k stars 175 forks source link

Vugu does not re-render after async change state #226

Closed Taoja closed 2 years ago

Taoja commented 2 years ago

Describe the bug vugu dom do not re-render after the state are changed by async function

Software Versions Vugu version: v0.3.4 Go version: 1.17.7 Browser and version: chrome

my code

<div @click="c.click(event)" :class='c.pressClass()'>
...
</div>
import "log"

type VutiCell struct{
  // data
  press bool `vugu:"data"`
  // property
  Title string
  Tips string
  Icon Icon
  IsLink bool
  // slot
  DefaultSlot vugu.Builder
  Left vugu.Builder
  Right vugu.Builder
  // event
  Click ClickHandler
}

type Icon struct {
  name string
  color string
}

func (c *VutiCell) wait(this js.Value, args [] js.Value) interface{} {
  c.press = false
  log.Println(c.press)
  return nil
}

func (c *VutiCell) click(event vugu.DOMEvent) {
  if (!c.press) {
    log.Println("按钮点击")
    c.press = true
    js.Global().Call("setTimeout", js.FuncOf(c.wait), 100)
    if (c.Click != nil) {
      c.Click.ClickHandle(ClickEvent{DOMEvent:event})
    }
  }
}

func (c *VutiCell) pressClass() string {
  if (c.press) {
    return "vuti-cell-press vuti vuti-cell"
  } else {
    return "vuti vuti-cell"
  }
}

//vugugen:event Click
Taoja commented 2 years ago

resolve it by dom-event lock

<script type="application/x-go">
type VutiCell struct{
  // data
  press bool `vugu:"data"`
  leftWidth string
  // property
  Title string
  Tips string
  Icon Icon
  IsLink bool
  // slot
  DefaultSlot vugu.Builder
  Left vugu.Builder
  Right vugu.Builder
  // event
  Click ClickHandler
}

type Icon struct {
  name string
  color string
}

func (c *VutiCell) Compute() {
  if (len(cellLeftWidth) != 0) {
    c.leftWidth = cellLeftWidth
  }
}

func (c *VutiCell) click(event vugu.DOMEvent) {
  ee := event.EventEnv()
  if (!c.press && c.IsLink) {
    go func() {
      ee.Lock()
      c.press = true
      ee.UnlockRender()
      if (c.Click != nil) {
        c.Click.ClickHandle(ClickEvent{DOMEvent:event})
      }
      js.Global().Call("setTimeout", js.FuncOf(func (this js.Value, args [] js.Value) interface {} {
        ee.Lock()
        c.press = false
        ee.UnlockRender()
        return nil
      }), 100)
    }()
  }
}

func (c *VutiCell) pressClass() string {
  if (c.press) {
    return "vuti-cell-press vuti vuti-cell"
  } else {
    return "vuti vuti-cell"
  }
}

//vugugen:event Click

</script>