feat: use JSON script for serializing
This commit is contained in:
parent
f584ba3b7e
commit
0339b7c262
3 changed files with 12 additions and 8 deletions
12
README.md
12
README.md
|
@ -96,13 +96,17 @@ export interface Props {
|
||||||
|
|
||||||
## What's happening here?
|
## What's happening here?
|
||||||
|
|
||||||
For simple applications with just a few components, this is a quick pattern to embed serialized information into your HTML. The `Serialize` component will do this for you, currently by using a hidden `textarea` element to hold the string.
|
This is a quick and easy pattern to embed serialized information into your HTML and make it available in the client-side script.
|
||||||
|
|
||||||
The `deserialize()` function can then parse the value string for use in your client script. You have to manage the IDs yourself (i.e., make sure they are unique) and understand that the `deserialize()` function will crawl the whole document incurring some performance cost.
|
The `Serialize` component will write the data as JSON wrapped in a `<script type="application/json">` element to hold the string.
|
||||||
|
|
||||||
Another approach we see in other frameworks is embedding JSON in your HTML and the frameworks themselves managing/tracking the IDs for you, but we don't have access to this in Astro as we are not really shipping a framework to the browser. That's nice and ideal (in my opinion), but we do have to manage things ourselves.
|
The `deserialize()` function can then parse the value string for use in your client script.
|
||||||
|
|
||||||
There is a pattern [given in the Astro docs](https://docs.astro.build/en/guides/client-side-scripts/#pass-frontmatter-variables-to-scripts) to use a Custom Element that takes a `data-` prop which properly protects the scope of your component. That is a good pattern to follow for complex applications that don't use UI frameworks.
|
There is also a pattern [given in the Astro docs](https://docs.astro.build/en/guides/client-side-scripts/#pass-frontmatter-variables-to-scripts) to use a Custom Element that takes a `data-` prop which properly protects the scope of your component. That is a good pattern to follow for complex applications that don't use UI frameworks.
|
||||||
|
|
||||||
|
## Trade-Off
|
||||||
|
|
||||||
|
You have to manage the IDs yourself (i.e., make sure they are unique) and understand that the `deserialize()` function will crawl the whole document incurring a minimal performance cost depending on how big your HTML is.
|
||||||
|
|
||||||
## Reporting Issues
|
## Reporting Issues
|
||||||
|
|
||||||
|
|
|
@ -14,4 +14,4 @@ export interface Props {
|
||||||
const {id, data} = Astro.props;
|
const {id, data} = Astro.props;
|
||||||
---
|
---
|
||||||
|
|
||||||
<textarea hidden id={id}>{JSON.stringify(data)}</textarea>
|
<script type="application/json" id={id} set:html={JSON.stringify(data)}></script>
|
|
@ -1,8 +1,8 @@
|
||||||
export function deserialize<T = any>(id: string): T {
|
export function deserialize<T = any>(id: string): T {
|
||||||
const element = document.querySelector<HTMLTextAreaElement>(`#${id}`);
|
const element = document.querySelector<HTMLScriptElement>(`#${id}`);
|
||||||
|
|
||||||
if (element?.value)
|
if (element?.innerText)
|
||||||
return JSON.parse(element.value)
|
return JSON.parse(element.innerText)
|
||||||
|
|
||||||
throw Error(`The call deserialize('${id}') did not find any data.
|
throw Error(`The call deserialize('${id}') did not find any data.
|
||||||
Check that the following are correct:
|
Check that the following are correct:
|
||||||
|
|
Loading…
Reference in a new issue