我可以通过缓存动态加载 Web 组件引用的数据吗?

Posted

技术标签:

【中文标题】我可以通过缓存动态加载 Web 组件引用的数据吗?【英文标题】:Can i load data referenced by a Web Component dynamically, with caching? 【发布时间】:2021-08-20 12:18:41 【问题描述】:

我目前正在学习 Web 组件,我想知道是否可以让组件动态加载自己的数据,类似于 <img> 从其 src 属性中所做的那样,即类似这样:

<my-fancy-thingy src='/stuff.json'></my-fancy-thingy>

如果stuff.json 可能相当大,这个功能显然会很有用,所以它也应该可以利用浏览器的缓存机制,所以每次我们请求页面时都不会重新加载引用的文件,除非更改.

这个可以吗?

【问题讨论】:

【参考方案1】:

当然,从 获取灵感见Dev.to Post

/*
  defining the <load-file> Web Component,
  
  yes! the documenation is longer than the code
  
  License: https://unlicense.org/

*/
customElements.define("load-file", class extends htmlElement 

  // declare default connectedCallback as sync so await can be used
  async connectedCallback(
    // attach a shadowRoot if none exists (prevents displaying error when moving Nodes)
    // declare as parameter to save 4 Bytes: 'let '
    shadowRoot = this.shadowRoot || this.attachShadow(mode:"open")
  ) 
      // load SVG file from src="" async, parse to text, add to shadowRoot.innerHTML
    shadowRoot.innerHTML = await (await fetch(this.getAttribute("src"))).text()

    // append optional <tag [shadowRoot]> Elements from inside <load-svg> after parsed <svg>
    shadowRoot.append(...this.querySelectorAll("[shadowRoot]"))

    // if "replaceWith" attribute 
    // then replace <load-svg> with loaded content <load-svg>
    // childNodes instead of children to include #textNodes also
    this.hasAttribute("replaceWith") && this.replaceWith(...shadowRoot.childNodes)
  
)

.text() 更改为 .json() 并解析 JSON 文件

可以通过将字符串存储在 localStorage 中来完成缓存(但我认为总共限制为 5MB):

https://en.wikipedia.org/wiki/Web_storage

https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage

你需要想出“数据已经改变”的策略;因为客户端不知道数据何时 实际更改了。如果(大)JSON 文件 发生更改,可能会有一个额外的 信号量 文件/端点提供信息。

【讨论】:

我想更像是重用浏览器内置的chaching策略,即如果服务器发送304,浏览器会重用其缓存副本。但我想这对于webcomponents是不可能的,所以我们必须重新发明使用您描述的某种方法进行相同的操作。 Web 组件是(自定义)HTML 标记。它们与 如何 浏览器缓存网络请求和任何其他 HTML 标记一样...无。跨度> 不确定这应该是什么意思...您是说“获取”功能会在适当时自动重用文件的浏览器端缓存版本,就像任何其他 html 触发的文件加载一样?但是为什么我需要手动将结果缓存在本地存储中呢? 如果您的服务器发送正确的标头以允许缓存,是的,那么 fetch 将使用缓存的版本。 nitropack.io/blog/post/web-caching-beginners-guide 和 developer.mozilla.org/en-US/docs/Web/HTTP/Caching。所有这些都与“Web 组件”无关【参考方案2】:

这就像一个魅力

export class MonElement extends HTMLElement                                                 
    constructor() 
        super();
        this.attachShadow(mode:'open'); 
        (...)
        this.shadowRoot.appendChild(atemplate);
    
    connectedCallback()...
    static get observedAttributes()
        return ['src'];
    
    attributeChangedCallback(nameattr,oldval,newval)
    
        if (nameattr==='src') 
            this[nameattr]=newval;
            here do the fetch for the src value which is newval then update what you got in the innerdom
    
    (...)

【讨论】:

以上是关于我可以通过缓存动态加载 Web 组件引用的数据吗?的主要内容,如果未能解决你的问题,请参考以下文章

Vue进阶-异步动态加载组件

Vue进阶-异步动态加载组件

Vue进阶-异步动态加载组件

可以通过动态生成的 <script> 注册 Knockout 组件吗?

django 制作web网站,动态页面数据已更新,但是无法刷新,这是怎么回事?是页面缓存吗?

在Java中,如何在Web应用程序中动态重新加载资源包?