You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Riot/JS如何动态创建标准HTML元素(如OL/UL)以避免代码重复

Great question! Duplicating template code is never fun, and Riot.js has some built-in features that let you solve this cleanly without touching innerHTML. Here are two approaches that fit your needs:

1. Extract Repeating Content into a Nested Component

First, eliminate the duplicate <li> code by moving it into a reusable sub-component. This keeps your main list template clean and makes maintenance easier.

Create a new tag file my-list-item.tag:

<my-list-item>
  <li>
    <!-- Your extensive inner code goes here -->
    <!-- You can pass props from the parent if needed, e.g.: -->
    <span>{this.props.item.content}</span>
    <button onclick={this.props.handleDelete}>Delete</button>
    <!-- Add all your existing inner elements, event handlers, etc. -->
  </li>

  <script>
    // Optional: Add component logic here if needed
  </script>
</my-list-item>

Then update your my-list.tag to use this component instead of duplicating code:

<my-list>
  <ol if="{this.opts.isOrdered}">
    <my-list-item each={item in this.opts.items} item={item} handleDelete={this.deleteItem} />
  </ol>
  <ul if="{!this.opts.isOrdered}">
    <my-list-item each={item in this.opts.items} item={item} handleDelete={this.deleteItem} />
  </ul>

  <script>
    this.deleteItem = (e) => {
      // Your delete logic here
    };
  </script>
</my-list>

This way, you only write the inner <li> code once, and reuse it across both list types.

2. Handle Dynamic Wrapper Elements (Beyond ol/ul)

For cases where you need dynamic, non-predefined wrapper elements, Riot.js supports dynamic tag names using curly braces. This lets you render any valid HTML tag without manual DOM manipulation.

Update my-list.tag to use a dynamic wrapper, with optional fallback and validation:

<my-list>
  <script>
    this.on('before-mount', () => {
      // Use custom wrapperTag if provided, else fall back to ol/ul based on isOrdered
      this.wrapperTag = this.opts.wrapperTag || (this.opts.isOrdered ? 'ol' : 'ul');
      
      // Optional: Validate the tag is allowed (prevent invalid HTML)
      const allowedTags = ['ol', 'ul', 'div', 'nav', 'section'];
      if (!allowedTags.includes(this.wrapperTag)) {
        console.warn(`Wrapper tag "${this.wrapperTag}" is not allowed. Falling back to ul.`);
        this.wrapperTag = 'ul';
      }
    });

    this.deleteItem = (e) => {
      // Your delete logic here
    };
  </script>

  <!-- Render the dynamic wrapper tag -->
  <{this.wrapperTag}>
    <my-list-item each={item in this.opts.items} item={item} handleDelete={this.deleteItem} />
  </{this.wrapperTag}>
</my-list>

Now you can use your component with any valid wrapper tag:

<!-- Ordered list -->
<my-list is-ordered items="{myItems}" />

<!-- Unordered list -->
<my-list items="{myItems}" />

<!-- Custom wrapper like div -->
<my-list wrapper-tag="div" items="{myItems}" />

Key Benefits

  • No manual innerHTML manipulation—all rendering uses Riot's native template system.
  • DRY code: Reuse the inner list item logic across all wrapper types.
  • Flexible: Supports both predefined (ol/ul) and dynamic wrapper elements.
  • Maintainable: Changes to the inner list item only need to be made once.

内容的提问来源于stack exchange,提问作者Remirror

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:12:20