项目作者: RmbRT

项目描述 :
Free lightweight dynamic component rendering framework.
高级语言: JavaScript
项目地址: git://github.com/RmbRT/renderable.js.git
创建时间: 2019-03-12T21:36:42Z
项目社区:https://github.com/RmbRT/renderable.js

开源协议:GNU General Public License v3.0

下载


" class="reference-link">Renderable.js

Free lightweight dynamic component rendering framework.

Features

Easy component injection
In your HTML, simply write ${render.component-name}, where component-name is the name of your component.
This automatically inserts the selected component into your document, or, if the component does not exist yet, creates a placeholder which will be replaced with the component as soon as it is created!

Easy to script
In your script, simply create a new component by writing the following:

  1. Renderable.create({
  2. lastName: "Davis",
  3. firstName: "Terrence Andrew",
  4. title: "Saint"
  5. }, {
  6. render() {
  7. return `${this.title} ${this.firstName} ${this.lastName}`.trim();
  8. },
  9. anchor: "user"
  10. });

This creates a renderable object called render.user, with the properties lastName, firstName, and title.
The object’s values can be accessed and changed through render.user.lastName etc.

To display the object, in your HTML file, write:

  1. <body>
  2. <p>Welcome, ${render.user}!</p>
  3. <p>
  4. To finish your registration, please click the
  5. link that has been sent to your email address.
  6. </p>
  7. </body>

Modularity
You can easily compose components out of other components, to reuse them:

  1. Renderable.create({}, {
  2. render() {
  3. return `Hello, ${render.user}, peace unto you!`;
  4. },
  5. anchor: "greeting"
  6. });

When the utilised renderable is updated, the other renderable is also updated.
This ensures that you can save a lot of code duplication.

  1. <body>
  2. <p>${render.greeting}</p>
  3. </body>

Smart automatic refresh
Whenever you modify a component’s values, all appearances of it in the document are re-rendered.
This also affects components that use the modified component.
To modify a component, simply access its object through the global render object:

  1. Renderable.create({
  2. time: new Date()
  3. }, {
  4. render() {
  5. return `${this.time.getHours()}:${this.time.getMinutes()}`;
  6. },
  7. anchor: "time"
  8. });
  9. // Update the time in regular intervals.
  10. setInterval(() => { render.time.time = new Date(); }, 50);
  1. <body>
  2. <p>It is currently ${render.time}.</p>
  3. </body>

This displays the current time in the document.
Note that even the very frequent modification of the time variable does not have much impact on performance, as caching and smart updating is employed: only if the generated HTML changed, the element is redrawn.
This only redraws the time if the string returned by render() differs from the previous string.

Dynamic HTML support
Even if you insert HTML dynamically into the site, then ${} anchors are properly recognised and replaced.
This makes the framework very flexible in its usage, and compatible with more sophisticated libraries that modify the DOM.

Turning on/off substitution
Substitution is automatically disabled in code, script, style, and the custom x-renderablejs-ignore tags and their descendants.
It is also possible to turn on substitution in a disabled tag by adding the data-renderablejs-ignore=no attribute.
If it is present, but not set to no, it also suppresses substitution.
Note that you cannot turn on substitution inside a tag whose parent tag has disabled substitution.
Also note that if a substitution results in a placeholder being generated, it is not substituted again.

Events and interactions
You can create interactive renderables which are treated differently from usual renderables and can receive events sent to their corresponding HTML elements.
This is done with Renderable.createInteractive, and supplying an events property in the second argument. Warning: please make sure to read the troubleshooting section below before using interactibles!

  1. function button(text, {onClick, anchor}) {
  2. return Renderable.createInteractive({text, onClick}, {
  3. render() { return `<button>${this.text}</button>`; },
  4. events: {
  5. click() { this.onClick() }
  6. },
  7. anchor
  8. });
  9. }
  1. Renderable.create({
  2. "list": ["wooden door", "bicycle exercise trainer", "barbecue"]
  3. }, {
  4. anchor: "myList",
  5. render() {
  6. return `
  7. <ul class="removable-list">
  8. ${this.list.map((text, i) => `
  9. <li>${text} ${
  10. button("x", {
  11. onClick: () => {
  12. // Remove entry from list.
  13. this.list.splice(i, 1);
  14. // Re-render.
  15. Renderable.invalidate(this);
  16. }
  17. })
  18. }</li>`).join("")
  19. }</ul>`;
  20. }
  21. });
  1. <h1>Shopping list</h1>
  2. ${render.myList}

Troubleshooting

For interactive renderables, the returned HTML is processed (top-level nodes are annotated with an ID). This step may break the HTML if its top-level nodes are not allowed as children to generic HTML nodes (such as td and tr). In that case, specify the required container element in the render() method as follows, by using an out parameter passed to it (as a callback):

  1. {
  2. render(settings) {
  3. settings({container: "tbody"});
  4. return `<tr><td>...</td></tr>`;
  5. }
  6. }

Failing to do so will result in botched HTML, as the HTML of interactibles is parsed into the children of a HTML tag via Element.innerHTML, which are then annotated with IDs, and converted back into HTML (again, via innerHTML). Sadly, there is no lightweight way to parse HTML natively, so tr and td tags are eliminated in the process. The settings.container option sets the desired tag name of the temporary container element, working around the issue.

settings.inline To allow the use of a renderable in attributes or other places where a placeholder tag is not legal, set settings.inline. This pastes the renderable’s HTML as a normal string. This probably also a good thing to do for small text-only nodes in general. If this field is not set, then it will generate a placeholder tag in its parent renderables. Especially for complex DOM elements, it is preferable not to inline them, as the cached DOM can be assembled more efficiently and less parsing and pasting occurs. Important: when inlining, set the settings before rendering any children, as this call propagates the settings as contextual information down to the children.

Server-side use

If you’re in a non-DOM context, like Node.js, you can simply require() renderable.js and it will return { Renderable, render }.
If you want to import it in a way that’s more compatible with DOM-style JS (using global scope instead of modules), define global.RenderableUseGlobal = true before calling require().
This will define Renderable and render as global objects which will be visible in all scripts.

License

Renderable.js is released under the GNU General Public License (GNU GPL) as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
A copy of the license can befound in LICENSE.