2021.04.08
😊 2021.04.08
1. Vue slot을 활용한 컴포넌트 재활용
2. 뷰 컴포넌트 props 타입이 배열이나 객체인 경우
팩토리 패턴으로 작성해야함.
3. 슬롯에 데이터바인딩
: https://beomy.tistory.com/58
4. hsla?
border-color: hsla(0, 0%, 100%, 0.5);
5. bin-packing algorithm 알고리즘
6. javascript json 파싱 에러 처리
if (typeof positions == "string") {
  try {
    // 성공
    positions = JSON.parse(positions);
    onSuccess(positions);
  } catch (error) {
    // 실패
    console.error("JSON parse error: " + error);
    onError();
    return;
  }
}
7. Packery 라이브러리 자동 빈 공간 채우기 방지
- 참고
 
- https://github.com/metafizzy/packery/issues/337
 - https://packery.metafizzy.co/#initialize-with-vanilla-javascript
 - https://jeonghwan-kim.github.io/2018/05/12/extended-component.html
 
- HTML
 
// html
<div class="grid" id="grid">insert html</div>
- CSS
 
/*css*/
* {
  box-sizing: border-box;
}
body {
  font-family: sans-serif;
}
/* ---- grid ---- */
.grid {
  background: #ddd;
  width: 100%;
  max-width: 800px;
  min-width: 400px;
  min-height: 400px;
}
/* clear fix */
.grid:after {
  content: "";
  display: block;
  clear: both;
}
/* ---- .grid-item ---- */
.grid-item {
  float: left;
  width: 25%;
  height: 100px;
  background: #c09;
  border: 2px solid hsla(0, 0%, 0%, 0.5);
}
.grid-item.col-1 {
  width: 100%;
}
.grid-item.col-2 {
  width: 50%;
}
.grid-item.col-3 {
  width: 25%;
}
.grid-item:hover {
  border-color: hsla(0, 0%, 100%, 0.5);
  cursor: move;
}
.grid-item.is-dragging,
.grid-item.is-positioning-post-drag {
  background: #c90;
  z-index: 2;
}
.packery-drop-placeholder {
  outline: 3px dashed hsla(0, 0%, 0%, 0.5);
  outline-offset: -6px;
  -webkit-transition: -webkit-transform 0.2s;
  transition: transform 0.2s;
}
- Javascript
 
// javascript
const $ = (selector) => document.querySelector(selector);
const gridView = {
  init(el) {
    console.log("[gridView init]");
    const self = this;
    this.el = el;
    this.data = [];
    // 패커리 실행
    this.packery = initPackery(this.el);
    // 이벤트 설정
    this.packery.on("dragItemPositioned", function (draggedItem) {
      self.onDragEnd(draggedItem);
    });
    window.packery = this.packery;
    return this;
  },
  setData(data) {
    console.log("[gridView setData]");
    this.data = data;
    return this;
  },
  render() {
    console.log("[gridView render]");
    this.el.innerHTML = "";
    this.data.forEach((item) => {
      const div = document.createElement("div");
      div.setAttribute("data-id", item.id);
      div.setAttribute("data-sort", item.sort);
      div.className = item.className;
      div.setAttribute("data-top", item.top);
      div.setAttribute("data-left", item.left);
      div.innerText = item.title;
      this.el.appendChild(div);
    });
    this.initLayout();
    return this;
  },
  //   레이아웃 그리기
  initLayout() {
    const self = this;
    // 렌더링 후 다시 패커리 세팅
    this.packery.reloadItems();
    this.setItemDraggable();
    this.packery._resetLayout();
    const elements = this.packery.getItemElements();
    try {
      elements.forEach(function (element) {
        const packeryItem = self.packery.getItem(element);
        console.log(packeryItem);
        try {
          const left = element.getAttribute("data-left");
          const top = element.getAttribute("data-top");
          if (isNaN(left) || isNaN(top)) {
            throw new Error("position error");
          }
          packeryItem.rect.x = +left * self.packery.packer.width;
          //   packeryItem.rect.y = +top * self.packery.packer.width;
          packeryItem.rect.y = +top;
          packeryItem.element.style.top = packeryItem.rect.y + "px";
          packeryItem.element.style.left = packeryItem.rect.x + "px";
        } catch (error) {
          throw error;
        }
      });
      //   self.packery.shiftLayout();
    } catch (error) {
      console.log(error.message);
      self.packery.layout();
    }
  },
  //   드래그 앤 드롭 설정
  setItemDraggable() {
    this.packery.getItemElements().forEach(function (itemElem) {
      var draggie = new Draggabilly(itemElem);
      this.packery.bindDraggabillyEvents(draggie);
    });
  },
  onDragEnd(draggedItem) {
    const self = this;
    const items = draggedItem.layout.items;
    const gridWidth = self.packery.packer.width;
    const newData = items.map(function (item) {
      const rect = item.rect;
      const element = item.element;
      return {
        left: rect.x / gridWidth,
        // top: rect.y / gridWidth,
        top: rect.y,
        className: element.className,
        sort: element.getAttribute("data-sort"),
        id: element.getAttribute("data-id"),
        title: element.innerText,
      };
    });
    console.log(newData);
    localStorage.setItem("initData", JSON.stringify(newData));
    // 서버에 데이터 전송
    // this.data = newData;
  },
};
document.addEventListener("DOMContentLoaded", function (e) {
  init();
});
function init() {
  console.log("[init]");
  gridView.init($("#grid"));
  window.gridView = gridView;
  list().then((data) => {
    gridView.setData(data).render();
  });
}
function list() {
  console.log("[list]");
  const data = [
    {
      id: "card-2",
      title: "카드2",
      className: "grid-item col-2",
      sort: 2,
      position: {},
    },
    {
      id: "card-1",
      title: "카드1",
      className: "grid-item col-1",
      sort: 1,
      position: {},
    },
    {
      id: "card-3",
      title: "카드3",
      className: "grid-item col-3",
      sort: 3,
      position: {},
    },
    {
      id: "card-4",
      title: "카드4",
      className: "grid-item col-3",
      sort: 3,
      position: {},
    },
  ];
  const initData = localStorage.getItem("initData");
  if (typeof initData === "string") {
    try {
      console.log(initData);
      return Promise.resolve(JSON.parse(initData));
    } catch (error) {
      return Promise.resolve(data);
    }
  } else {
    return Promise.resolve(data);
  }
}
// 패커리 실행
function initPackery(el) {
  console.log("[initPackery]");
  const pckry = new Packery(el, {
    itemSelector: ".grid-item",
    columnWidth: 100,
    initLayout: false,
  });
  return pckry;
}
                Author And Source
이 문제에 관하여(2021.04.08), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@kyh196201/2021.04.08저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
                                
                                
                                
                                
                                
                                우수한 개발자 콘텐츠 발견에 전념
                                (Collection and Share based on the CC Protocol.)