无法通过 Promise 正确更新元素的大小

问题描述 投票:0回答:1

我正在编写这个函数来切换幻灯片事件,并且我试图在其上实现 Promise,但它没有达到预期的效果,只有当我使用 Promise 时我才能获得最终宽度。尽管它的工作没有承诺。

function toggleSlide(target, options){
    let menu = target.children[0];
    let end = options.end;
    let step = options.step;
    let iStep = options.iStep;
    let width = start = options.start;
    let isVertical = options.isVertical || false;
    let removeClass, addClass, slideFn = null;

    if(options.step < 0) options.step *= -1;
    if(!options.hasOwnProperty('isVertical')) options.isVertical = isVertical;

    if(end > start){
        addClass = 'block';     // display: block; css class
        removeClass = 'none';   // display: none; css class
        // slideFn = slideIn;
    }else{
        addClass = 'none';
        removeClass = 'block';
        // slideFn = slideOut;

        // make the menu dissapear before triggering the animation.
        menu.classList.add(addClass);
        menu.classList.remove(removeClass);
    }

    // slideFn(target, options)
    //     .then(() => {
    //         if(slideFn === slideIn){
    //             console.log('slideOut');
    //             menu.classList.add(addClass);
    //             menu.classList.remove(removeClass);
    //         }
    //         return;
    //     });

    let interval = setInterval(() => {
        if(width != end) width += step;
        if(isVertical){
            target.style.height = width + 'px';
        }else{
            target.style.width = width + 'px';
        }

        if(end < start ? width <= end : width >= end){
            menu.classList.add(addClass);
            menu.classList.remove(removeClass);
            clearInterval(interval);
        }
    }, iStep);
};

这些是slideIn 和slideOut 函数:

function slideIn(element, options, arg = false){
    let size = options.start || 100,
        end = options.end || 0,
        sStep = options.step || 1,      // size step
        iStep = options.iStep || 10,    // interval step
        isVertical = options.isVertical || false,
        dirProp = isVertical ? "height" : "width",
        interval = null;

    if(arg){
        return;
    }

    return new Promise(resolve => {
        interval = setInterval(() => {
            if(size > end) size -= sStep;
            if(size <= end) size = end;

            console.log(element.style[dirProp], size);

            element.style[dirProp] = size + "px";

            if(size === end){
                clearInterval(interval);
                resolve();
            }
        }, iStep);
    });
};
function slideOut(element, options, arg = false){
    let size = options.start || 0,
        end = options.end || 100,
        sStep = options.step || 1,      // size step
        iStep = options.iStep || 10,    // interval step
        isVertical = options.isVertical || false,
        dirProp = isVertical ? "height" : "width",
        interval = null;

    if(arg){
        return;
    }

    return new Promise(resolve => {
        interval = setInterval(() => {
            if(size < end) size += sStep;
            if(size >= end) size = end;

            console.log(element.style[dirProp], size);

            element.style[dirProp] = size + "px";

            if(size === end){
                clearInterval(interval);
                resolve();
            }
        }, iStep);
    });
};

我不确定在用promise调用它时如何使元素的宽度逐渐更新,这与函数调用本身有关吗?或者使用 async/await 中的 HTMLelements 行为。我不确定问题出在哪里。

javascript html promise
1个回答
0
投票

这是更正后的代码片段。

function toggle(target /*, args */ ) {

  const isActive = (function(target) {
    if (target.classList.contains('active')) {
      target.classList.remove('active');
    } else {
      target.classList.add('active');
    }

    return target.classList.contains('active')
  })(target);

  const data = isActive ? {
    start: 35,
    end: 120,
    step: 5,
    iStep: 10
  } : {
    start: 120,
    end: 35,
    step: -5,
    iStep: 10
  };

  const menu = document.getElementById('menu-links');
  toggleSlide(menu, data);
};

function toggleSlide(target, options, className = null) {
  let menu = target.children[0];
  let end = options.end;
  let step = options.step;
  let iStep = options.iStep;
  let size = start = options.start;
  let isVertical = options.isVertical || false;
  let removeClass, addClass, slideFn = null;

  if (options.step < 0) options.step *= -1;
  if (!options.hasOwnProperty('isVertical')) options.isVertical = isVertical;

  if (end > start) {
    addClass = 'block'; // display: block; css class
    removeClass = 'none'; // display: none; css class
    slideFn = slideOut;
  } else {
    addClass = 'none';
    removeClass = 'block';
    slideFn = slideIn;

    // make the menu dissapear before triggering the animation.
    menu.classList.add(addClass);
    menu.classList.remove(removeClass);
  }

  // slideFn(target, options, true);
  // if(slideFn === slideOut){
  //     menu.classList.add(addClass);
  //     menu.classList.remove(removeClass);
  // }

  slideFn(target, options)
    .then(() => {
      if (slideFn === slideOut) {
        menu.classList.add(addClass);
        menu.classList.remove(removeClass);
      }
      return;
    });

  // let interval = setInterval(() => {
  //     if(size != end) size += step;
  //     if(isVertical){
  //         target.style.height = size + 'px';
  //     }else{
  //         target.style.width = size + 'px';
  //     }
  //     // console.log(slideFn === slideOut, menu);
  //     if(end < start ? size <= end : size >= end){
  //         // if(end > start)
  //         //     menu.classList.add(className);
  //         menu.classList.add(addClass);
  //         menu.classList.remove(removeClass);
  //         clearInterval(interval);
  //     }
  // }, iStep);
};

function slideIn(element, options, arg = false) {
  let size = options.start || 100,
    end = options.end || 0,
    sStep = options.step || 1, // size step
    iStep = options.iStep || 10, // interval step
    isVertical = options.isVertical || false,
    dirProp = isVertical ? "height" : "width",
    interval = null;

  if (arg) {
    console.log("slideIn with no Promise")
    interval = setInterval(() => {
      if (size > end) size -= sStep;

      element.style[dirProp] = size + "px";

      if (size <= end) {
        element.style[dirProp] = end + "px";
        clearInterval(interval);
      }
    }, iStep);
    return;
  }

  return new Promise(resolve => {
    interval = setInterval(() => {
      if (size > end) size -= sStep;

      element.style[dirProp] = size + "px";

      if (size <= end) {
        element.style[dirProp] = end + "px";
        clearInterval(interval);
        resolve();
      }
    }, iStep);
  });
};

function slideOut(element, options, arg = false) {
  let size = options.start || 0,
    end = options.end || 100,
    sStep = options.step || 1, // size step
    iStep = options.iStep || 10, // interval step
    isVertical = options.isVertical || false,
    dirProp = isVertical ? "height" : "width",
    interval = null;

  if (arg) {
    console.log("slideOut with no Promise")
    interval = setInterval(() => {
      if (size < end) size += sStep;

      element.style[dirProp] = size + "px";

      if (size >= end) {
        element.style[dirProp] = end + "px";
        clearInterval(interval);
      }
    }, iStep);
    return;
  }

  return new Promise(resolve => {
    interval = setInterval(() => {
      if (size < end) size += sStep;

      element.style[dirProp] = size + "px";

      if (size >= end) {
        element.style[dirProp] = end + "px";
        clearInterval(interval);
        resolve();
      }
    }, iStep);
  });
};
.lb {
  background-color: lightblue;
}

.none {
  display: none;
}

.block {
  display: block;
}

.active {
  display: block;
}

.link {
  padding: 10px;
  margin: 5px;
  background-color: #fff;
  border-radius: 5px;
  box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
}

#container {
  width: 180px;
  height: 125px;
  position: relative;
}


/* #menu{} */

#menu {
  position: relative;
  z-index: 2;
  width: 30px;
  cursor: pointer;
}

#menu:before,
#menu:after,
#menu div {
  background: black;
  content: "";
  display: block;
  height: 4px;
  border-radius: 3px;
  margin: 3px 0;
  transition: 0.2s;
}

#menu.active:before {
  transform: translateY(7px) rotate(135deg);
}

#menu.active:after {
  transform: translateY(-7px) rotate(-135deg);
}

#menu.active div {
  transform: scale(0);
}

#menu-links {
  min-width: 35px;
  max-width: 120px;
  padding: 2px;
  padding-top: 30px;
  min-height: 114px;
  display: none;
  position: absolute;
  top: 5px;
  z-index: 1;
}

#menu-links ul li {
  margin: 1px 0;
}

#menu-links.active {
  display: block;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Title Here</title>
</head>

<body>
  <div id="container" class="link">
    <div id="menu" onclick="toggle(this)">
      <div>
      </div>
    </div>
    <div id="menu-links" class="lb active">
      <ul class="none">
        <li>Home</li>
        <li>About</li>
        <li>Contact</li>
        <li>Login</li>
      </ul>
    </div>
  </div>
</body>

</html>

© www.soinside.com 2019 - 2024. All rights reserved.