我是Java语言的新手,我正尝试创建一个Web组件,正是某种列表视图。目标是当我单击某个项目时它可以扩展和折叠,并且我希望它与过渡有关。
我已经将过渡放在模板上,但是由于某种原因,它不起作用,只是在没有动画的情况下立即增大或折叠。
很少,如果我先进行const listView = document.querySelector(".list-view")
,然后再进行listView.collapse()
,则它可以正常工作。
摘要代码为:
class ListItem extends HTMLElement {
constructor(items = []) {
super();
//Template and its variables
const listItemTemplate = document.createElement("template");
listItemTemplate.innerHTML = `
<style>
.listitem{
//some other properties
transition: height 0.3s cubic-bezier(0.65, 0, 0.35, 1);
height: ${this.initialHeight};
}
//Other styles...
</style>
changedItem(itemSelected){
//More stuff
this.refreshDOMItems();
this.collsapse();
}
`;
expand() {
let height = 10;
Array.from(this.itemsHTML).forEach((item) => {
height += item.clientHeight;
});
this.listItem.style.height = height / 16 + "rem";
}
collapse() {
this.listItem.style.height = this.initialHeight;
}
编辑:这是一个Codepen。
我做错了什么?希望代码没有太多混乱。预先谢谢你!
答案 0 :(得分:1)
您正在transition: background .5s ease;
上用.listitem:hover
覆盖高度转换,因此删除此行可以解决问题:
.listitem:hover{
/*transition: background .5s ease;*/
background: rgba(255,255,255,.65);
}
class ListItem extends HTMLElement {
constructor(items = []) {
super();
//Template and its variables
this.initialHeight = "3.75rem";
this.initialBorderRadius = stringToNumber(this.initialHeight) / 2 + "rem";
const listItemTemplate = document.createElement("template");
listItemTemplate.innerHTML = `
<style>
ul{
box-sizing: border-box;
margin: 0px;
padding: 0px;
list-style: none;
}
.ul{
display: flex;
align-items: center;
flex-direction: column;
height: 3.75rem;
}
.listitem{
font-family: 'Nunito', sans-serif;
display: inline-block;
overflow: hidden;
box-sizing: border-box;
background-color: white;
border-radius: ${this.initialBorderRadius};
padding: 0px 1rem;
cursor: pointer;
box-shadow: 0px 0px 1.25rem rgba(4,25,106,.14);
transition: height 0.3s cubic-bezier(0.65, 0, 0.35, 1);
height: ${this.initialHeight};
}
li.item{
box-sizing: border-box;
min-height: ${this.initialHeight};
display: flex;
align-items: center;
-webkit-touch-callout: none; /* iOS Safari */
-webkit-user-select: none; /* Safari */
-khtml-user-select: none; /* Konqueror HTML */
-moz-user-select: none; /* Old versions of Firefox */
-ms-user-select: none; /* Internet Explorer/Edge */
user-select: none; /* Non-prefixed version, currently
supported by Chrome, Edge, Opera and Firefox */
}
.img{
width: 2rem;
margin-right: 0.625rem;
border-radius: 50%;
}
.name{
font-size: 1.125rem;
font-weight: 700;
color: var(--autores);
margin-right: 0.6rem;
}
.listitem:hover{
/*transition: background .5s ease;*/
background: rgba(255,255,255,.65);
}</style>
<div class="listitem">
<ul class="ul">
</ul>
</div>
`;
//Constructor
this.attachShadow({
mode: "open"
});
this.shadowRoot.appendChild(listItemTemplate.content.cloneNode(true));
this.items = items;
this.listItem = this.shadowRoot.querySelector(".listitem");
this.itemsHTML = this.shadowRoot
.querySelector(".listitem")
.querySelector(".ul").children;
const ul = this.shadowRoot.querySelector(".listitem").querySelector(".ul");
this.ul = ul;
}
connectedCallback() {
//Do
//Carga de items por defecto
const item = {
name: "Item",
avatar: "images/users.svg",
selected: false
};
const item_two = {
name: "Item 2",
avatar: "images/users.svg",
selected: false
};
const item_three = {
name: "Item 3",
avatar: "images/users.svg",
selected: false
};
this.addItem(item);
this.addItem(item_two);
this.addItem(item_three);
this.refreshDOMItems();
//event listeners for each item;
const itemClick = this.shadowRoot.querySelector(".listitem");
itemClick.addEventListener("click", (event) => {
event.preventDefault();
let targetStr = "";
const trgtCls = event.target.classList;
if (
trgtCls.contains("name") ||
trgtCls.contains("img") ||
trgtCls.contains("item")
) {
if (trgtCls.contains("name")) {
targetStr = event.target.innerText;
}
if (trgtCls.contains("img")) {
targetStr = event.target.nextElementSibling.innerText;
}
if (trgtCls.contains("item")) {
targetStr = event.target.querySelector(".name").innerText;
}
}
if (targetStr === this.items[0].name) {
this.expand();
} else {
this.changedItem(targetStr);
}
});
}
addItem(item = Object) {
this.items.push(item);
this.items.forEach((item) => {
item.selected = false;
});
this.items[0].selected = true;
console.log(item.selected);
}
refreshDOMItems() {
removeChildNodes(this.ul);
this.items.forEach((item) => {
const itemTemplate = document.createElement("template");
itemTemplate.innerHTML = `
<li class="item">
<svg viewBox="0 0 512 512" width="100" title="user-alt" class="img">
<path d="M256 288c79.5 0 144-64.5 144-144S335.5 0 256 0 112 64.5 112 144s64.5 144 144 144zm128 32h-55.1c-22.2 10.2-46.9 16-72.9 16s-50.6-5.8-72.9-16H128C57.3 320 0 377.3 0 448v16c0 26.5 21.5 48 48 48h416c26.5 0 48-21.5 48-48v-16c0-70.7-57.3-128-128-128z" />
</svg>
<p class="name">${item.name}</p>
</li>
`;
this.ul.appendChild(itemTemplate.content.cloneNode(true));
});
}
getItems() {
return this.items;
}
changedItem(itemSelected) {
let arr = Array.from(this.items);
this.items.forEach(function(item, index) {
if (item.name == itemSelected) {
arr = moveElementArray(arr, index, 0);
}
});
this.items = arr;
this.items.forEach((item) => {
item.selected = false;
});
this.items[0].selected = true;
this.refreshDOMItems();
this.collapse();
}
selected() {
let selected;
this.items.forEach((item) => {
if (item.selected === true) {
selected = item;
}
});
return selected;
}
value() {
let selected;
this.items.forEach((item) => {
if (item.selected === true) {
selected = item;
}
});
return selected.name;
}
expand() {
let height = 10;
Array.from(this.itemsHTML).forEach((item) => {
height += item.clientHeight;
});
this.listItem.style.height = height / 16 + "rem";
}
collapse() {
this.listItem.style.height = this.initialHeight;
}
}
window.customElements.define("c-list-item", ListItem);
const lsim = document.querySelector(".list");
function removeChildNodes(element = HTMLElement) {
while (element.childElementCount > 0) {
element.removeChild(element.firstChild);
}
}
function stringToNumber(string = String) {
let newNumber = "";
let afterComma = "";
let comma = false;
Array.from(string).forEach((char) => {
if (char === "." || char === ",") {
comma = true;
}
if (comma === false) {
if (Number(char)) {
newNumber += Number(char);
}
} else {
if (Number(char)) {
afterComma += Number(char);
}
}
});
if (afterComma != "") {
newNumber += "." + afterComma;
}
return Number(newNumber);
}
function moveElementArray(array = Array, from = Number, to = Number) {
const fromArr = array[from];
if (from > to) {
for (let index = from; index >= to; index--) {
array[index] = array[index - 1];
if (index == to) {
array[index] = fromArr;
}
}
} else {
for (let index = from; index <= to; index++) {
array[index] = array[index + 1];
if (index == to) {
array[index] = fromArr;
}
}
}
return array;
}
function replaceElementArray(array = Array, from = Number, to = Number) {
const fromArr = array[from];
const toArr = array[to];
array[from] = toArr;
array[to] = fromArr;
return array;
}
<body style="background-color: #f0f0f0;">
<c-list-item class="list"></c-list-item>
</body>