我正在尝试使用发光元素实现活动按钮。单击按钮时,css类应该附加到该特定元素。在下一个按钮上,点击css必须从上一个按钮中删除,并添加到新按钮中。我已经使用单个自定义元素实现了这一点,它运行良好。但我尝试使用父子自定义元素来实现这一点。
我的应用程序-父组件我的按钮-子组件
问题:在点击下一个按钮时,活动类不会从第一个按钮中删除。请参阅所附的输出图像。
我正在尝试更改我的按钮的公共属性自己点击。
this.clicked=!this.clicked;
有没有什么方法可以通过在自己的类中更改子组件的公共属性来使下面的代码正常工作?
<!doctype html>
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<style>
body {
margin: 0;
height: 100vh;
text-align: center;
margin-top: 50px;
font-family: Arial;
}
</style>
</head>
<body>
<my-app></my-app>
</body>
<script type="module">
import {LitElement, html, css} from 'https://unpkg.com/lit-element/lit-element.js?module';
class MyButton extends LitElement {
static properties = {
clicked: {},
label: {},
};
static styles = css`
/* Style the buttons */
button {
border: none;
outline: none;
padding: 10px 16px;
background-color: #f1f1f1;
cursor: pointer;
font-size: 18px;
}
/* Style the active class, and buttons on mouse-over */
.active, button:hover {
background-color: #666;
color: white;
}
`;
constructor() {
super();
this.label = 0;
}
render() {
console.log("C Render " + this.clicked);
return html`
<button
class=${ this.clicked ? 'active' : '' }
@click=${ this.setClicked }
>
${this.label}
</button>
`;
}
setClicked(e) {
const event = new Event('ask-parent-reset', {bubbles: true, composed: true});
this.dispatchEvent(event);
this.clicked = ! this.clicked;
}
}
customElements.define('my-button', MyButton);
const fBoolRrand = () => Math.random() < 0.5;
class MyApp extends LitElement {
static properties = {
pclicked: {
hasChanged(newVal, oldVal) {
return true;
}
},
};
constructor() {
super();
this.pclicked = [ false, false, false, false ];
}
render() {
console.log("P Render " + this.pclicked);
return html`
<div>
${
this.pclicked.map( (_,i) => {
return html `
<my-button
.label=${i+1}
.clicked=${this.pclicked[i]}
@ask-parent-reset=${this.resetClicked}
>
</my-button>
`
})
}
</div>
`;
}
resetClicked(e) {
this.pclicked = [ false, false, false, false ];
//this.requestUpdate();
//this.pclicked = [ true, true, true, true ];
//this.pclicked = [ fBoolRrand(), fBoolRrand(), fBoolRrand(), fBoolRrand() ];
//this.pclicked = this.pclicked.map( x => x ? false : false );
//console.log(e.target.clicked);
//const recvElem = e.srcElement;
//recvElem.clicked = !recvElem.clicked;
}
}
customElements.define('my-app', MyApp);
</script>
输出:输出图像
有没有办法通过在自己的类中更改子组件的公共属性来实现下面的代码?
我不能百分之百确定我是否理解你的问题,但我认为这是可能的。我认为你的尝试非常接近成功,所以我建议做一个小的改变,这将产生一个有效的解决方案。
- 您可以在事件中包含"detail"属性,因此我将"ask parent reset"事件更改为包含按下按钮的上的数据:
之前:
const event = new Event('ask-parent-reset', {bubbles: true, composed: true});
之后:
const event = new CustomEvent('ask-parent-reset', {bubbles: true, composed: true, detail: {button: this.label}});
- 使用新事件设置
pclicked
父属性,使其反映请求的更改
之前:
resetClicked(e) {
this.pclicked = [ false, false, false, false ];
}
之后:
resetClicked(e) {
const buttonIndex = e.detail.button - 1
const oldState = this.pclicked[buttonIndex]
this.pclicked = [ false, false, false, false ];
this.pclicked[buttonIndex] = !oldState
}
希望这能有所帮助!
Stacklitz链接到我建议的代码:https://stackblitz.com/edit/web-platform-6pfvzh?file=index.html
完整HTML源代码:
<!doctype html>
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<style>
body {
margin: 0;
height: 100vh;
text-align: center;
margin-top: 50px;
font-family: Arial;
}
</style>
</head>
<body>
<my-app></my-app>
</body>
<script type="module">
import {LitElement, html, css} from 'https://unpkg.com/lit-element/lit-element.js?module';
class MyButton extends LitElement {
static properties = {
clicked: {},
label: {},
};
static styles = css`
/* Style the buttons */
button {
border: none;
outline: none;
padding: 10px 16px;
background-color: #f1f1f1;
cursor: pointer;
font-size: 18px;
}
/* Style the active class, and buttons on mouse-over */
.active, button:hover {
background-color: #666;
color: white;
}
`;
constructor() {
super();
this.label = 0;
}
render() {
console.log("C Render " + this.clicked);
return html`
<button
class=${ this.clicked ? 'active' : '' }
@click=${ this.setClicked }
>
${this.label}
</button>
`;
}
setClicked(e) {
const event = new CustomEvent('ask-parent-reset', {bubbles: true, composed: true, detail: {button: this.label}});
this.dispatchEvent(event);
this.clicked = ! this.clicked;
}
}
customElements.define('my-button', MyButton);
const fBoolRrand = () => Math.random() < 0.5;
class MyApp extends LitElement {
static properties = {
pclicked: {
hasChanged(newVal, oldVal) {
return true;
}
},
};
constructor() {
super();
this.pclicked = [ false, false, false, false ];
}
render() {
console.log("P Render " + this.pclicked);
return html`
<div>
${
this.pclicked.map( (_,i) => {
return html `
<my-button
.label=${i+1}
.clicked=${this.pclicked[i]}
@ask-parent-reset=${this.resetClicked}
>
</my-button>
`
})
}
</div>
`;
}
resetClicked(e) {
this.pclicked = [ false, false, false, false ];
this.pclicked[e.detail.button - 1] = true
//this.requestUpdate();
//this.pclicked = [ true, true, true, true ];
//this.pclicked = [ fBoolRrand(), fBoolRrand(), fBoolRrand(), fBoolRrand() ];
//this.pclicked = this.pclicked.map( x => x ? false : false );
//console.log(e.target.clicked);
//const recvElem = e.srcElement;
//recvElem.clicked = !recvElem.clicked;
}
}
customElements.define('my-app', MyApp);
</script>