cache.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. /**
  2. * @license
  3. * Copyright 2017 Google LLC
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. import { render, nothing, } from '../lit-html.js';
  7. import { directive, Directive, } from '../directive.js';
  8. import { clearPart, getCommittedValue, insertPart, isTemplateResult, setCommittedValue, } from '../directive-helpers.js';
  9. class CacheDirective extends Directive {
  10. constructor(partInfo) {
  11. super(partInfo);
  12. this._templateCache = new WeakMap();
  13. }
  14. render(v) {
  15. // Return an array of the value to induce lit-html to create a ChildPart
  16. // for the value that we can move into the cache.
  17. return [v];
  18. }
  19. update(containerPart, [v]) {
  20. // If the previous value is a TemplateResult and the new value is not,
  21. // or is a different Template as the previous value, move the child part
  22. // into the cache.
  23. if (isTemplateResult(this._value) &&
  24. (!isTemplateResult(v) || this._value.strings !== v.strings)) {
  25. // This is always an array because we return [v] in render()
  26. const partValue = getCommittedValue(containerPart);
  27. const childPart = partValue.pop();
  28. let cachedContainerPart = this._templateCache.get(this._value.strings);
  29. if (cachedContainerPart === undefined) {
  30. const fragment = document.createDocumentFragment();
  31. cachedContainerPart = render(nothing, fragment);
  32. cachedContainerPart.setConnected(false);
  33. this._templateCache.set(this._value.strings, cachedContainerPart);
  34. }
  35. // Move into cache
  36. setCommittedValue(cachedContainerPart, [childPart]);
  37. insertPart(cachedContainerPart, undefined, childPart);
  38. }
  39. // If the new value is a TemplateResult and the previous value is not,
  40. // or is a different Template as the previous value, restore the child
  41. // part from the cache.
  42. if (isTemplateResult(v)) {
  43. if (!isTemplateResult(this._value) || this._value.strings !== v.strings) {
  44. const cachedContainerPart = this._templateCache.get(v.strings);
  45. if (cachedContainerPart !== undefined) {
  46. // Move the cached part back into the container part value
  47. const partValue = getCommittedValue(cachedContainerPart);
  48. const cachedPart = partValue.pop();
  49. // Move cached part back into DOM
  50. clearPart(containerPart);
  51. insertPart(containerPart, undefined, cachedPart);
  52. setCommittedValue(containerPart, [cachedPart]);
  53. }
  54. }
  55. this._value = v;
  56. }
  57. else {
  58. this._value = undefined;
  59. }
  60. return this.render(v);
  61. }
  62. }
  63. /**
  64. * Enables fast switching between multiple templates by caching the DOM nodes
  65. * and TemplateInstances produced by the templates.
  66. *
  67. * Example:
  68. *
  69. * ```js
  70. * let checked = false;
  71. *
  72. * html`
  73. * ${cache(checked ? html`input is checked` : html`input is not checked`)}
  74. * `
  75. * ```
  76. */
  77. export const cache = directive(CacheDirective);
  78. //# sourceMappingURL=cache.js.map