Owl 组件¶
Odoo JavaScript 框架使用一个名为 Owl 的自定义组件框架。它是一个声明式的组件系统,受 Vue 和 React 的启发。组件通过 QWeb 模板 定义,并添加了一些 Owl 特有的指令进行增强。官方 Owl 文档 包含了完整的参考文档和教程。
重要
尽管代码可以在 web
模块中找到,但它是从一个单独的 GitHub 仓库进行维护的。因此,对 Owl 的任何修改都应通过 https://github.com/odoo/owl 上的拉取请求进行。
注解
目前,所有 Odoo 版本(从版本 14 开始)都使用相同的 Owl 版本。
使用 Owl 组件¶
Owl 文档 已经详细介绍了 Owl 框架,因此本页面将仅提供与 Odoo 相关的信息。但首先,让我们看看如何在 Odoo 中创建一个简单的组件。
const { useState } = owl.hooks;
const { xml } = owl.tags;
class MyComponent extends Component {
setup() {
this.state = useState({ value: 1 });
}
increment() {
this.state.value++;
}
}
MyComponent.template = xml
`<div t-on-click="increment">
<t t-esc="state.value">
</div>`;
此示例表明,Owl 作为库在全局命名空间中可用,即 owl
:它可以像 Odoo 中的大多数库一样直接使用。请注意,此处我们将模板定义为静态属性,但没有使用 static
关键字,因为在某些浏览器中该关键字不可用(Odoo 的 JavaScript 代码应符合 EcmaScript 2019 标准)。
我们在这里通过 xml
辅助函数在 JavaScript 代码中定义模板。然而,这仅适用于入门。实际上,在 Odoo 中,模板应定义在 XML 文件中,以便进行翻译。在这种情况下,组件只需定义模板名称即可。
在实际操作中,大多数组件应定义 2 或 3 个文件,位于同一位置:一个 JavaScript 文件(my_component.js
)、一个模板文件(my_component.xml
),以及可选的 SCSS(或 CSS)文件(my_component.scss
)。这些文件随后应添加到某个资源包中。Web 框架将负责加载 JavaScript/CSS 文件,并将模板加载到 Owl 中。
以下是该组件的定义方式:
const { useState } = owl.hooks;
class MyComponent extends Component {
...
}
MyComponent.template = 'myaddon.MyComponent';
并且模板现在位于相应的 XML 文件中:
<?xml version="1.0" encoding="UTF-8" ?>
<templates xml:space="preserve">
<t t-name="myaddon.MyComponent">
<div t-on-click="increment">
<t t-esc="state.value"/>
</div>
</t>
</templates>
注解
模板名称应遵循 addon_name.ComponentName
的命名规范。
另请参见
最佳实践¶
首先,组件是类,因此它们有一个构造函数。但构造函数是 JavaScript 中特殊的方法,无法以任何方式被覆盖。由于在 Odoo 中这种模式偶尔是有用的,我们需要确保 Odoo 中的任何组件都不直接使用构造函数方法。相反,组件应使用 setup
方法:
// correct:
class MyComponent extends Component {
setup() {
// initialize component here
}
}
// incorrect. Do not do that!
class IncorrectComponent extends Component {
constructor(parent, props) {
// initialize component here
}
}
另一个好的实践是为模板名称使用一致的命名规范:addon_name.ComponentName
。这可以防止 Odoo 插件之间的名称冲突。
参考列表¶
Odoo 网页客户端是使用 Owl 组件构建的。为了便于使用,Odoo JavaScript 框架提供了一套通用组件,可以在一些常见场景中重复使用,例如下拉框、复选框或日期选择器。本页面将解释如何使用这些通用组件。
技术名称 |
简要描述 |
---|---|
一个用于在触摸滑动时执行操作的滑动组件 |
|
一个带有旁边标签的简单复选框组件 |
|
可选择的颜色列表 |
|
全功能下拉菜单 |
|
一个用于通过选项卡在页面之间导航的组件 |
|
一个用于处理分页的小型组件 |
|
一个用于在不同选项之间进行选择的下拉组件 |
|
标签列表 |
显示为圆角药丸样式的标签列表 |
动作滑块¶
库位¶
@web/core/action_swiper/action_swiper
描述¶
这是一个可在元素水平滑动时执行动作的组件。滑动器会包裹目标元素以向其添加动作。当用户释放滑动器并使其滑过其宽度的一部分时,将执行该动作。
<ActionSwiper onLeftSwipe="Object" onRightSwipe="Object">
<SomeElement/>
</ActionSwiper>
使用组件最简单的方式是如上所示,在 XML 模板中直接将目标元素包裹在组件中。但有时,您可能希望扩展一个现有的元素,并且不希望重复模板。这是完全可以实现的。
如果您想扩展现有元素的行为,必须将该元素直接包裹在内部。此外,您还可以根据需要条件性地添加属性,以管理该元素是否可滑动、其动画效果以及执行操作所需的最小滑动比例。
你可以使用组件轻松地与记录、消息、列表中的条目等进行交互。

以下示例创建了一个基本的 ActionSwiper 组件。在此示例中,两个方向的滑动均被启用。
<ActionSwiper
onRightSwipe="
{
action: '() => Delete item',
icon: 'fa-delete',
bgColor: 'bg-danger',
}"
onLeftSwipe="
{
action: '() => Star item',
icon: 'fa-star',
bgColor: 'bg-warning',
}"
>
<div>
Swipable item
</div>
</ActionSwiper>
注解
当使用从右到左(RTL)语言时,操作会进行反转。
属性¶
名称 |
类型 |
描述 |
---|---|---|
|
|
可选布尔值,用于确定滑动时是否存在翻译效果 |
|
|
可选的动画,在滑动结束后使用( |
|
|
如果存在,可以通过向左滑动来触发操作切换器 |
|
|
如果存在,可以通过向右滑动来操作 actionswiper |
|
|
可选的最小宽度比例,必须滑动该比例以执行动作 |
你可以同时使用 onLeftSwipe
和 onRightSwipe
属性。
用于左/右滑动的 Object
必须包含:
action
,即作为回调的可调用Function
。一旦在给定方向上完成滑动,就会执行该动作。
icon
是要使用的图标类,通常用于表示动作。它必须是字符串
。
bgColor
是背景颜色,用于装饰动作。可以是以下 Bootstrap 上下文颜色 中的一种(danger
、info
、secondary
、success
或warning
)。这些值必须提供以定义滑动器的行为和视觉外观。
示例:扩展现有组件¶
在下面的示例中,你可以使用 xpath
来包装 ActionSwiper 组件中的现有元素。这里,为邮件中的消息标记为已读添加了一个滑动组件。
<xpath expr="//*[hasclass('o_Message')]" position="after">
<ActionSwiper
onRightSwipe="messaging.device.isMobile and messageView.message.isNeedaction ?
{
action: () => messageView.message.markAsRead(),
icon: 'fa-check-circle',
bgColor: 'bg-success',
} : undefined"
/>
</xpath>
<xpath expr="//ActionSwiper" position="inside">
<xpath expr="//*[hasclass('o_Message')]" position="move"/>
</xpath>
复选框¶
库位¶
@web/core/checkbox/checkbox
描述¶
这是一个带有旁边标签的简单复选框组件。复选框与标签相关联:当点击标签时,复选框会切换状态。
<CheckBox value="boolean" disabled="boolean" t-on-change="onValueChange">
Some Text
</CheckBox>
属性¶
名称 |
类型 |
描述 |
---|---|---|
|
|
如果为 true,则复选框被选中,否则未被选中 |
|
|
如果为 true,则复选框被禁用,否则为启用。 |
颜色列表¶
库位¶
@web/core/colorlist/colorlist
描述¶
颜色列表允许您从预定义的颜色列表中进行选择。默认情况下,该组件会显示当前选中的颜色,并且在 canToggle
属性存在之前,该组件是不可展开的。不同的属性可以改变其行为,例如始终展开列表,或在点击后使其作为切换器使用,以显示可用颜色列表,直到选择一个颜色为止。
属性¶
名称 |
类型 |
描述 |
---|---|---|
|
|
可选。是否可以在点击时扩展颜色列表 |
|
|
组件中要显示的颜色列表。每个颜色都有一个唯一的 |
|
|
可选。如果为 true,则列表始终展开 |
|
|
可选。如果为真,列表默认展开 |
|
|
选择一种颜色后执行的回调函数 |
|
|
可选。所选颜色的 |
颜色 id
的如下:
ID |
颜色 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
“鲑鱼粉红色” |
|
|
|
|
|
|
|
|
|
|
下拉菜单¶
库位¶
@web/core/dropdown/dropdown
和 @web/core/dropdown/dropdown_item
描述¶
下拉菜单在点击切换按钮时会显示一个包含多个项目的菜单。它们可以与下拉项(DropdownItems)结合使用,以便在选择项目时调用回调函数并关闭菜单。
下拉菜单是出人意料的复杂组件,它们提供的功能列表如下:
点击以切换项目列表
点击外部区域关闭
当选择项目时调用函数
可选地,在选择一项时关闭项目列表
SIY:自行设计样式
支持子下拉菜单,层级不限
可配置的快捷键,用于打开/关闭下拉菜单或选择下拉项
键盘导航(箭头键、Tab、Shift+Tab、Home、End、Enter 和 Escape)
在页面滚动或调整大小时重新定位自身
智能选择其应打开的方向(右到左方向会自动处理)。
直接兄弟下拉菜单:当一个打开时,在悬停时切换其他下拉菜单
要正确使用 <Dropdown/>
组件,你需要填充两个 OWL 插槽 :
default
插槽:它包含下拉菜单的 切换 元素。默认情况下,点击事件会绑定到此元素以打开和关闭下拉菜单。content
插槽:它包含下拉菜单本身的内容,并在弹出框中渲染。虽然不是必须的,但你可以在该插槽中放置一些DropdownItem
,当选择这些项时,下拉菜单会自动关闭。
<Dropdown>
<!-- The content of the "default" slot is the component's toggle -->
<button class="my-btn" type="button">
Click me to toggle the dropdown menu!
</button>
<!-- The "content" slot is rendered inside the menu that pops up next to the toggle -->
<t t-set-slot="content">
<DropdownItem onSelected="selectItem1">Menu Item 1</DropdownItem>
<DropdownItem onSelected="selectItem2">Menu Item 2</DropdownItem>
</t>
</Dropdown>
下拉菜单属性¶
名称 |
类型 |
描述 |
---|---|---|
|
|
可选的类名添加到下拉菜单中 |
|
|
可选,如果为 true,则禁用下拉菜单,用户将无法再打开它。(默认: |
|
|
可选的项目列表,将在下拉菜单的菜单中作为 DropdownItems 显示 |
|
|
可选地定义所需的菜单打开位置。RTL 方向会自动应用。应为有效的 usePosition 挂钩位置。(默认: |
|
|
可选函数,在打开前调用。可能是异步的。 |
|
|
可选函数,仅在打开后调用。 |
|
|
可选函数,在打开或关闭下拉菜单后调用(接受一个布尔值作为唯一参数,表示下拉菜单是否已打开)。 |
|
|
可选对象,具有 |
|
|
可选,当为 true 时,下拉组件将不会在切换器上添加点击事件监听器。这允许更灵活地控制何时打开下拉菜单。(应与 |
|
|
可选地覆盖下拉菜单的导航选项(参见 |
|
|
可选,如果为 true,则在鼠标悬停在下拉菜单上时保持菜单位置不变,当菜单内容发生变化时可以提供更好的用户体验。 |
|
|
可选,用于获取下拉菜单的引用(需传入 |
下拉菜单项 属性¶
名称 |
类型 |
描述 |
---|---|---|
|
|
可选值,用于添加到根 span 的类名(支持字符串和 OWL 类名对象表示法)。 |
|
|
可选函数,当选择下拉项时调用。 |
|
|
可选,用于控制在选择该项时应关闭哪个父级下拉菜单: |
|
|
可选对象,用于向根元素添加属性。 |
重要
在为你的组件编写自定义 CSS 时,请不要忘记菜单元素并不在切换按钮的旁边,而是在覆盖容器内部,位于文档的底部。因此,可以使用 menuClass
和 class
属性来更方便地编写你的选择器。(这种 DOM 操作帮助我们避免了大量 z-index 的问题。)
嵌套下拉菜单¶
下拉菜单可以嵌套,只需将新的下拉菜单组件放在其他下拉菜单的内容插槽中即可。当父级下拉菜单打开时,子级下拉菜单会在悬停时自动打开。
默认情况下,选择一个 DropdownItem 会关闭整个 Dropdown 树。
Example
此示例展示了如何创建一个嵌套的文件下拉菜单,包含用于新建子元素的子菜单。
<Dropdown>
<button>File</button>
<t t-set-slot="content">
<DropdownItem onSelected="() => this.onItemSelected('file-save')">Save</DropdownItem>
<DropdownItem onSelected="() => this.onItemSelected('file-open')">Open</DropdownItem>
<Dropdown>
<button>New</button>
<t t-set-slot="content">
<DropdownItem onSelected="() => this.onItemSelected('file-new-document')">Document</DropdownItem>
<DropdownItem onSelected="() => this.onItemSelected('file-new-spreadsheet')">Spreadsheet</DropdownItem>
</t>
</Dropdown>
</t>
</Dropdown>
在下面的示例中,我们递归调用一个模板以显示树状结构。
<t t-name="addon.MainTemplate">
<div>
<t t-call="addon.RecursiveDropdown">
<t t-set="name" t-value="'Main Menu'" />
<t t-set="items" t-value="state.menuItems" />
</t>
</div>
</t>
<t t-name="addon.RecursiveDropdown">
<Dropdown>
<button t-esc="name"></button>
<t t-set-slot="content">
<t t-foreach="items" t-as="item" t-key="item.id">
<!-- If this item has no child: make it a <DropdownItem/> -->
<DropdownItem t-if="!item.childrenTree.length" onSelected="() => this.onItemSelected(item)" t-esc="item.name"/>
<!-- Else: recursively call the current dropdown template. -->
<t t-else="" t-call="addon.RecursiveDropdown">
<t t-set="name" t-value="item.name" />
<t t-set="items" t-value="item.childrenTree" />
</t>
</t>
</t>
</Dropdown>
</t>
受控下拉框¶
如果需要,你也可以通过代码打开或关闭下拉菜单。要做到这一点,你必须使用 useDropdownState
钩子以及 state
属性。useDropdownState
返回一个包含 open
和 close
方法的对象(以及一个 isOpen
获取器)。将该对象传递给你要控制的下拉菜单的 state
属性,然后调用相应的方法应该就可以打开和关闭你的下拉菜单了。
你可以将 manual
设置为 true
,如果你不希望默认的点击处理程序被添加到切换按钮上。
Example
以下示例显示了一个在挂载时会自动打开的下拉菜单,并且当点击内部按钮时,只有 50% 的几率关闭。
import { Component, onMounted } from "@odoo/owl";
import { Dropdown } from "@web/core/dropdown/dropdown";
import { DropdownItem } from "@web/core/dropdown/dropdown_item";
import { useDropdownState } from "@web/core/dropdown/dropdown_hooks";
class MyComponent extends Component {
static components = { Dropdown, DropdownItem };
static template = xml`
<Dropdown state="this.dropdown">
<div>My Dropdown</div>
<t t-set-slot="content">
<button t-on-click="() => this.mightClose()">Close It!<button>
</t>
</Dropdown>
`;
setup() {
this.dropdown = useDropdownState();
onMounted(() => {
this.dropdown.open();
});
}
mightClose() {
if (Math.random() > 0.5) {
this.dropdown.close();
}
}
}
下拉组¶
库位: @web/core/dropdown/dropdown_group
你可以使用 DropdownGroup 组件,使下拉菜单共享一个公共组。这意味着当其中一个下拉菜单打开时,其他下拉菜单会在鼠标悬停时自动打开,而无需单击。
要做到这一点,可以将所有下拉菜单包裹在一个单一的 DropdownGroup 中,或者将它们包裹在具有相同 group
键的多个 DropdownGroup 中。
Example
在下面的代码片段中,所有下拉菜单将共享同一个用户组:
<DropdownGroup>
<Dropdown>...</Dropdown>
<Dropdown>...</Dropdown>
<Dropdown>...</Dropdown>
</DropdownGroup>
在下面的代码片段中,只有第一个、第二个和第四个下拉菜单共享同一个用户组:
<DropdownGroup group="'my-group'">
<Dropdown>...</Dropdown>
<Dropdown>...</Dropdown>
</DropdownGroup>
<DropdownGroup group="'my-other-group'">
<Dropdown>...</Dropdown>
</DropdownGroup>
<DropdownGroup group="'my-group'">
<Dropdown>...</Dropdown>
</DropdownGroup>
笔记本¶
库位¶
@web/core/notebook/notebook
描述¶
笔记本用于以选项卡界面显示多个页面。选项卡可以位于元素顶部以水平方式显示,或位于左侧以实现垂直布局。
有两种方式可以定义你的 Notebook 页面以进行实例化,可以通过使用 slot
,或者通过传递专用的 props
。
一个页面可以通过 isDisabled
属性禁用,该属性可以直接设置在插槽节点上,或者在使用 Notebook 时,如果将 pages
作为 props 传递,则可以在页面声明中设置。一旦被禁用,对应的标签页将变灰,并且也会被设置为未激活状态。
属性¶
名称 |
类型 |
描述 |
---|---|---|
|
|
可选。允许导航到当前不可见标签页内的元素。 |
|
|
可选。组件根元素上的类名。 |
|
|
可选。默认显示的页面 |
|
|
可选。选项卡中使用的图标列表。 |
|
|
|
` onPageUpdate ` |
|
可选。页面更改后执行的回调函数。 |
|
|
可选。包含从模板中填充的 |
Example
第一种方法是将页面设置在组件的插槽中。
<Notebook orientation="'vertical'"> <t t-set-slot="page_1" title="'Page 1'" isVisible="true"> <h1>My First Page</h1> <p>It's time to build Owl components. Did you read the documentation?</p> </t> <t t-set-slot="page_2" title="'2nd page'" isVisible="true"> <p>Wise owl's silent flight. Through the moonlit forest deep, guides my path to code</p> </t> </Notebook>另一种定义页面的方式是通过传递 props。这在某些页面具有相同结构时会很有用。首先为每个你可能使用的页面模板创建一个组件。
import { Notebook } from "@web/core/notebook/notebook"; class MyTemplateComponent extends owl.Component { static template = owl.tags.xml` <h1 t-esc="props.title" /> <p t-esc="props.text" /> `; } class MyComponent extends owl.Component { get pages() { return [ { Component: MyTemplateComponent, title: "Page 1", props: { title: "My First Page", text: "This page is not visible", }, }, { Component: MyTemplateComponent, id: "page_2", title: "Page 2", props: { title: "My second page", text: "You're at the right place!", }, }, ] } } MyComponent.template = owl.tags.xml` <Notebook defaultPage="'page_2'" pages="pages" /> `;
此处展示了两个示例:

分页器¶
库位¶
@web/core/pager/pager
描述¶
分页器是一个用于处理分页的小型组件。一页由一个 offset`(偏移量)和一个 `limit`(每页大小)定义。它会显示当前页码和 `total`(总元素数),例如,“9-12 / 20”。在前面的例子中,`offset
是 8,limit
是 4,total
是 20。它包含两个按钮(“上一页”和“下一页”),用于在不同页面之间导航。
注解
分页器可以在任何地方使用,但其主要用途是在控制面板中。有关操作控制面板分页器的信息,请参阅 usePager 钩子。
<Pager offset="0" limit="80" total="50" onUpdate="doSomething" />
属性¶
名称 |
类型 |
描述 |
---|---|---|
|
|
当前页面第一个元素的索引。它从 0 开始,但分页器显示 |
|
|
页面的大小。 |
|
|
该页面可以访问的元素总数。 |
|
|
当分页器修改页面时调用的函数。此函数可以是异步的,在此函数执行期间,分页器无法被编辑。 |
|
|
允许单击当前页面以进行编辑(默认为 |
|
|
绑定上一页按钮的访问键 |
库位¶
@web/core/select_menu/select_menu
描述¶
当您需要比使用原生的 select
元素更复杂的功能时,可以使用此组件。您可以自定义选项模板,从而在选项中进行搜索,或将其分组为子部分。
注解
优先使用原生的 HTML <select>
元素,因为它默认提供了可访问性功能,并且在移动设备上具有更好的用户界面。此组件旨在用于更复杂的使用场景,以克服原生元素的限制。
属性¶
名称 |
类型 |
描述 |
---|---|---|
|
|
可选。在下拉菜单中显示的 |
|
|
可选。设置在 SelectMenu 组件根元素上的类名。 |
|
|
可选。包含 |
|
|
可选。启用多选功能。当启用多选时,所选值会以 标签 的形式显示在 SelectMenu 输入框中。 |
|
|
可选。切换按钮的类名。 |
|
|
可选。指定所选值是否可以取消选择。 |
|
|
可选。下拉菜单中是否显示搜索框。 |
|
|
可选。作为搜索框占位符显示的文本。 |
|
|
可选。当前选中的值。它可以是任何类型的值。 |
|
|
可选。当选择一个选项时执行的回调函数。 |
choice
的形状如下:
value
是选项的实际值。它通常是一个技术字符串,但也可以是any
类型。
label
是与选项相关联的显示文本。通常,这个值是一个更友好且已翻译的string
。
一个 group
的结构如下:
choices
是此用户组要显示的choice
列表。
label
是与用户组关联的显示文本。这是一个显示在用户组顶部的字符串
。
Example
在下面的例子中,SelectMenu 将显示四个选项。其中有一个选项显示在选项上方,因为它没有关联任何用户组,而其他选项则根据其所属用户组的标签进行分组显示。
import { SelectMenu } from "@web/core/select_menu/select_menu";
class MyComponent extends owl.Component {
get choices() {
return [
{
value: "value_1",
label: "First value"
}
]
}
get groups() {
return [
{
label: "Group A",
choices: [
{
value: "value_2",
label: "Second value"
},
{
value: "value_3",
label: "Third value"
}
]
},
{
label: "Group B",
choices: [
{
value: "value_4",
label: "Fourth value"
}
]
}
]
}
}
MyComponent.template = owl.tags.xml`
<SelectMenu
choices="choices"
groups="groups"
value="'value_2'"
/>
`;
你可以通过使用相应的组件 slot
自定义切换器的外观,并为选项设置自定义模板。
MyComponent.template = owl.tags.xml`
<SelectMenu
choices="choices"
groups="groups"
value="'value_2'"
>
Make a choice!
<t t-set-slot="choice" t-slot-scope="choice">
<span class="coolClass" t-esc="'👉 ' + choice.data.label + ' 👈'" />
</t>
</SelectMenu>
`;

当 SelectMenu 用于多选时,value
属性必须是一个包含所选选项值的 Array
。

对于更高级的用例,您可以自定义下拉菜单的底部区域,使用 bottomArea
插槽。在这里,我们选择显示一个按钮,其对应的值设置在搜索输入中。
MyComponent.template = owl.tags.xml`
<SelectMenu
choices="choices"
>
<span class="select_menu_test">Select something</span>
<t t-set-slot="bottomArea" t-slot-scope="select">
<div t-if="select.data.searchValue">
<button class="btn text-primary" t-on-click="() => this.onCreate(select.data.searchValue)">
Create this article "<i t-esc="select.data.searchValue" />"
</button>
</div>
</t>
</SelectMenu>
`;

库位¶
@web/core/tags_list/tags_list
描述¶
此组件可以以圆角药丸的形式显示一组标签。这些标签可以简单地列出几个值,也可以是可编辑的,允许删除项目。可以使用 itemsVisible
属性来限制显示的项目数量。如果列表长度超过此限制,则会在最后一个标签旁边显示一个圆圈,表示额外的项目数量。
属性¶
名称 |
类型 |
描述 |
---|---|---|
|
|
可选。指定标签是否以徽章形式显示。 |
|
|
可选。指定标签是否显示文本。 |
|
|
可选。列表中可见标签的限制。 |
|
|
组件接收到的 |
tag
的形状如下:
colorIndex
是一个可选的颜色 ID。
icon
是一个可选图标,在显示的文本之前显示。
id
是标签的唯一标识符。
img
是一个可选的图片,以圆形显示在显示文本的前面。
onClick
是一个可选的回调函数,可以传递给该元素。这允许父元素根据点击的标签来处理任何功能。
onDelete
是一个可选的回调函数,可以传递给元素。这使得从标签列表中移除该项目成为可能,并必须由父元素进行处理。
text
是与标签相关联的显示string
。
Example
在下一个示例中,使用了 TagsList 组件来显示多个标签。当点击标签或删除按钮时会发生什么,由开发者负责处理。
import { TagsList } from "@web/core/tags_list/tags_list";
class Parent extends Component {
setup() {
this.tags = [{
id: "tag1",
text: "Earth"
}, {
colorIndex: 1,
id: "tag2",
text: "Wind",
onDelete: () => {...}
}, {
colorIndex: 2,
id: "tag3",
text: "Fire",
onClick: () => {...},
onDelete: () => {...}
}];
}
}
Parent.components = { TagsList };
Parent.template = xml`<TagsList tags="tags" />`;
根据每个标签所赋予的属性,它们的外观和行为将会有所不同。
