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?
|
||||
|
||||
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
|
||||
|
||||
|
|
|
@ -14,4 +14,4 @@ export interface 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 {
|
||||
const element = document.querySelector<HTMLTextAreaElement>(`#${id}`);
|
||||
const element = document.querySelector<HTMLScriptElement>(`#${id}`);
|
||||
|
||||
if (element?.value)
|
||||
return JSON.parse(element.value)
|
||||
if (element?.innerText)
|
||||
return JSON.parse(element.innerText)
|
||||
|
||||
throw Error(`The call deserialize('${id}') did not find any data.
|
||||
Check that the following are correct:
|
||||
|
|
Loading…
Reference in a new issue