router.py 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. from pathlib import Path
  2. from typing import Awaitable, Callable, Dict, Union
  3. from nicegui import background_tasks, ui
  4. from nicegui.dependencies import register_vue_component
  5. register_vue_component(name='router_frame', path=Path(__file__).parent / 'router_frame.js')
  6. class Router():
  7. def __init__(self) -> None:
  8. self.routes: Dict[str, Callable] = {}
  9. self.content: ui.element = None
  10. def add(self, path: str):
  11. def decorator(func: Callable):
  12. self.routes[path] = func
  13. return func
  14. return decorator
  15. def open(self, target: Union[Callable, str]) -> None:
  16. if isinstance(target, str):
  17. path = target
  18. builder = self.routes[target]
  19. else:
  20. path = {v: k for k, v in self.routes.items()}[target]
  21. builder = target
  22. async def build() -> None:
  23. with self.content:
  24. await ui.run_javascript(f'''
  25. if (window.location.pathname !== "{path}") {{
  26. history.pushState({{page: "{path}"}}, "", "{path}");
  27. }}
  28. ''', respond=False)
  29. result = builder()
  30. if isinstance(result, Awaitable):
  31. await result
  32. self.content.clear()
  33. background_tasks.create(build())
  34. def frame(self) -> ui.element:
  35. self.content = ui.element('router_frame') \
  36. .on('open', lambda msg: self.open(msg['args'])) \
  37. .use_component('router_frame')
  38. return self.content