单击时切换所有 stencil.js 个同类组件
Toggle all stencil.js components of the same kind when clicked
我正在创建一个工具栏,将用于文本编辑。
工具栏中的每个项目都是使用以下代码创建的:
import {Component, h, Prop, Event, EventEmitter} from '@stencil/core';
@Component({
tag: 'spa-toolbar-item',
styleUrl: 'spa-toolbar-item.scss',
})
export class spaToolbarItem {
@Prop({reflectToAttr: true, mutable: true}) toggle: boolean = false;
@Prop({reflectToAttr: true}) type: string;
@Event() onToggle: EventEmitter;
toggleComponent(): void {
this.toggle = !this.toggle;
this.onToggle.emit({visible: this.toggle});
}
render() {
return [
<button onClick={() => this.toggleComponent()}>
<slot/>
</button>,
<div class={this.toggle ? 'is-active' : null}>
{this.type == 'font'
? <div class={this.type}>
<span class="arial">Arial</span>
<span class="georgia">Georgia</span>
<span class="palatino">Palatino</span>
<span class="tahoma">Tahoma</span>
<span class="times">Times New Roman</span>
<span class="helvetica">Helvetica</span>
<span class="courier">Courier New</span>
<span class="lucida">Lucida Sans Typewriter</span>
<span class="verdana">Verdana</span>
</div>
: null}
</div>
]
}
}
这按预期工作,但是,我希望所有其他下拉菜单在单击一个项目时关闭,因此基本上 'this.toggle' 需要应用于所有非活动下拉菜单。我该怎么做?
你可以用 pure javascript 做的是,遍历所有元素 class is-active,并将每个元素的 toggle 属性设置为 0(或其他任何方式)你在做)
示例:
new Array(document.getElementsByClassName('is-active')).forEach(function(e){/*Set toggle property to 0*/});
这个做的是,搜索所有带[=11=的元素],遍历它们,并设置一个函数,在这个函数中参数e等于当前元素,你可以设置你的属性那里。
因此,我们的想法是将 addEventListener
应用于您的文档以及组件本身(主机 - 下拉列表)。为此,您可以使用像 componentdidload
.
这样的生命周期钩子
import {Component, h, Prop, Event, EventEmitter} from '@stencil/core';
@Component({
tag: 'spa-toolbar-item',
styleUrl: 'spa-toolbar-item.scss',
})
export class spaToolbarItem {
@Prop({reflectToAttr: true, mutable: true}) toggle: boolean = false;
@Prop({reflectToAttr: true}) type: string;
@Event() onToggle: EventEmitter;
private hostElement;
private buttonElement;
closeDropdown(){
this.toggle = false;
}
toggleComponent(): void {
this.toggle = !this.toggle;
this.onToggle.emit({visible: this.toggle});
}
render() {
return
<Host ref={(el) => this.hostElement = el}>
//everything you had before in the return value
</Host>
}
componentDidLoad(){
document.addEventListener("click", ()=>{this.clickManager("document");}, true)
this.hostElement.addEventListener("click", ()=>{this.clickManager("dropdown");}, true)
}
private clickManager(identifier){
if(identifier == "dropdown"){
//the clicked dropdown -> active dropdown
this.toggleComponent();
return;
}
//all non active Dropdowns
this.closeDropdown();
}
}
如您所见,我们有两个调用 clickManager 的事件。第一个是文档,第二个是您单击的下拉菜单。当然,您必须删除按钮上的 onclick 事件,但此代码无法按预期工作。现在您可以决定如果单击下拉菜单会发生什么,以及所有非活动下拉菜单会发生什么。
这是基本概念,如有需要,请随意调整和更改。
谢谢 Christian,我最终在下面使用了这个解决方案。
import {Component, h, Prop, Host, Element} from '@stencil/core';
@Component({
tag: 'spa-toolbar-item',
styleUrl: 'spa-toolbar-item.scss',
})
export class spaToolbarItem {
@Prop({reflectToAttr: true, mutable: true}) isOpen: string = 'false';
@Prop({reflectToAttr: true}) type: string;
@Element() el: HTMLElement;
openDropdown() {
function closeDropdown() {
let dropdowns = document.querySelectorAll('spa-toolbar-item[is-open]');
dropdowns.forEach(item => {
item.setAttribute('is-open', 'false')
});
}
if (this.el.getAttribute('is-open') == 'true') {
closeDropdown();
return
}
if (this.el.getAttribute('is-open') == 'false') {
closeDropdown();
this.el.setAttribute('is-open', 'true')
}
}
render() {
return (
<Host>
<button onClick={this.openDropdown.bind(this)}>
<slot/>
</button>
<div class={this.type}>
{this.type == 'font'
? <div>
<span class="arial">Arial</span>
<span class="georgia">Georgia</span>
<span class="palatino">Palatino</span>
<span class="tahoma">Tahoma</span>
<span class="times">Times New Roman</span>
<span class="helvetica">Helvetica</span>
<span class="courier">Courier New</span>
<span class="lucida">Lucida Sans Typewriter</span>
<span class="verdana">Verdana</span>
</div>
: null}
</div>
</Host>
)
}
}
我正在创建一个工具栏,将用于文本编辑。
工具栏中的每个项目都是使用以下代码创建的:
import {Component, h, Prop, Event, EventEmitter} from '@stencil/core';
@Component({
tag: 'spa-toolbar-item',
styleUrl: 'spa-toolbar-item.scss',
})
export class spaToolbarItem {
@Prop({reflectToAttr: true, mutable: true}) toggle: boolean = false;
@Prop({reflectToAttr: true}) type: string;
@Event() onToggle: EventEmitter;
toggleComponent(): void {
this.toggle = !this.toggle;
this.onToggle.emit({visible: this.toggle});
}
render() {
return [
<button onClick={() => this.toggleComponent()}>
<slot/>
</button>,
<div class={this.toggle ? 'is-active' : null}>
{this.type == 'font'
? <div class={this.type}>
<span class="arial">Arial</span>
<span class="georgia">Georgia</span>
<span class="palatino">Palatino</span>
<span class="tahoma">Tahoma</span>
<span class="times">Times New Roman</span>
<span class="helvetica">Helvetica</span>
<span class="courier">Courier New</span>
<span class="lucida">Lucida Sans Typewriter</span>
<span class="verdana">Verdana</span>
</div>
: null}
</div>
]
}
}
这按预期工作,但是,我希望所有其他下拉菜单在单击一个项目时关闭,因此基本上 'this.toggle' 需要应用于所有非活动下拉菜单。我该怎么做?
你可以用 pure javascript 做的是,遍历所有元素 class is-active,并将每个元素的 toggle 属性设置为 0(或其他任何方式)你在做)
示例:
new Array(document.getElementsByClassName('is-active')).forEach(function(e){/*Set toggle property to 0*/});
这个做的是,搜索所有带[=11=的元素],遍历它们,并设置一个函数,在这个函数中参数e等于当前元素,你可以设置你的属性那里。
因此,我们的想法是将 addEventListener
应用于您的文档以及组件本身(主机 - 下拉列表)。为此,您可以使用像 componentdidload
.
import {Component, h, Prop, Event, EventEmitter} from '@stencil/core';
@Component({
tag: 'spa-toolbar-item',
styleUrl: 'spa-toolbar-item.scss',
})
export class spaToolbarItem {
@Prop({reflectToAttr: true, mutable: true}) toggle: boolean = false;
@Prop({reflectToAttr: true}) type: string;
@Event() onToggle: EventEmitter;
private hostElement;
private buttonElement;
closeDropdown(){
this.toggle = false;
}
toggleComponent(): void {
this.toggle = !this.toggle;
this.onToggle.emit({visible: this.toggle});
}
render() {
return
<Host ref={(el) => this.hostElement = el}>
//everything you had before in the return value
</Host>
}
componentDidLoad(){
document.addEventListener("click", ()=>{this.clickManager("document");}, true)
this.hostElement.addEventListener("click", ()=>{this.clickManager("dropdown");}, true)
}
private clickManager(identifier){
if(identifier == "dropdown"){
//the clicked dropdown -> active dropdown
this.toggleComponent();
return;
}
//all non active Dropdowns
this.closeDropdown();
}
}
如您所见,我们有两个调用 clickManager 的事件。第一个是文档,第二个是您单击的下拉菜单。当然,您必须删除按钮上的 onclick 事件,但此代码无法按预期工作。现在您可以决定如果单击下拉菜单会发生什么,以及所有非活动下拉菜单会发生什么。
这是基本概念,如有需要,请随意调整和更改。
谢谢 Christian,我最终在下面使用了这个解决方案。
import {Component, h, Prop, Host, Element} from '@stencil/core';
@Component({
tag: 'spa-toolbar-item',
styleUrl: 'spa-toolbar-item.scss',
})
export class spaToolbarItem {
@Prop({reflectToAttr: true, mutable: true}) isOpen: string = 'false';
@Prop({reflectToAttr: true}) type: string;
@Element() el: HTMLElement;
openDropdown() {
function closeDropdown() {
let dropdowns = document.querySelectorAll('spa-toolbar-item[is-open]');
dropdowns.forEach(item => {
item.setAttribute('is-open', 'false')
});
}
if (this.el.getAttribute('is-open') == 'true') {
closeDropdown();
return
}
if (this.el.getAttribute('is-open') == 'false') {
closeDropdown();
this.el.setAttribute('is-open', 'true')
}
}
render() {
return (
<Host>
<button onClick={this.openDropdown.bind(this)}>
<slot/>
</button>
<div class={this.type}>
{this.type == 'font'
? <div>
<span class="arial">Arial</span>
<span class="georgia">Georgia</span>
<span class="palatino">Palatino</span>
<span class="tahoma">Tahoma</span>
<span class="times">Times New Roman</span>
<span class="helvetica">Helvetica</span>
<span class="courier">Courier New</span>
<span class="lucida">Lucida Sans Typewriter</span>
<span class="verdana">Verdana</span>
</div>
: null}
</div>
</Host>
)
}
}