CSS过渡不适用于Web组件上的Javascript

时间:2020-09-17 07:51:20

标签: javascript css css-transitions

我是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。

https://codepen.io/salvabarg/pen/zYqJNMj


我做错了什么?希望代码没有太多混乱。预先谢谢你!

1 个答案:

答案 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>