새로운 칸트맵 구축: 경험과 교훈과 견해

12598 단어 reactreduxfrontend
지난 6년 동안, 우리의 옛 칸트투는 우리에게 좋은 서비스를 제공했다.그것은 해야 할 일을 설계하고 있지만, 우리가 추가하고 싶은 것들은 불가능하거나, 완성하기 어렵다.예를 들어 기능과 기타 기록을 부모의 날짜에 강제적으로 보존하지 않기 때문에 고객이 데이터에 대해 더 많은 통제권을 가지게 한다.또는 고객이 원하는 방식으로 기록을 주문하고 어떤 기록이 나타나고 어떤 기록이 나타나지 않는지 선택할 수 있도록 허락한다.내부에서, 우리는 여러 보기에서 같은 칸트맵을 반복적으로 사용할 수 있도록 더 많은 데이터 형식을 지원하기를 희망한다.그래서 우리는 그것을 철저히 점검할 때가 됐다고 결정했다.다음은 우리가 이 위대한 도구를 구축할 때 배운 경험과 교훈이다.
모든 코드 예시가 문장의 가독성을 유지하기 위해 크게 간소화되었다.

네, 레드ux 상점에 넣은 건 천박해야 돼요.


우리가 좀 일찍 알고 싶은 것은 Redux의 저장 대상을 가능한 한 얕게 하는 것이다.프로젝트 초기에, 대상은 백엔드와 Redux 상점에서 거의 똑같아 보였다.처음에는 괜찮아 보였지만, 너무 많은 버그와 싸운 후에, 우리는 일부 대상의 속성을 대상 자체에서 옮기고, 저장소에 자신의 키 값 쌍에 넣기로 결정했다.
예시에 들어가기 전에 우리는 비교적 높은 차원에서 데이터 구조를 살펴보자.칸트도에는 속성과 하위 항목의 기록이 있는데 이런 기록 자체가 속성과 하위 항목의 기록 등이다.
records: {
  recordId: {
    ...attributes,
    children: {
      childId: { ...attributes, children: [...] },
      
    },
  },
  
}
Gantt 차트에서 특정 기록을 숨길 수 있는 기능을 살펴보겠습니다.우리의 최초의 천진한 실현은 기록에 isVisible 속성을 추가하는 것이다.
class Record {
  constructor(isVisible = true) {
    this.isVisible = isVisible;
  }
}
언뜻 보기에는 괜찮은 것 같지만, 우리가 기록의 가시성을 갱신하고 싶을 때, 우리는 반드시 기록 트리에 깊이 들어가야 한다.
const setIsVisible = (record, isVisible) => {
  state = state.setIn([records, parent.id, children, record.id, isVisible], isVisible);
};
이것은 한 겹 끼워 넣은 기록이다.더 깊게 중첩된 경우에는 다음과 같은 방법으로 기록의 전체 경로를 찾아야 합니다.
record.parents.map(parent => parent.id).interpose(children)
이것은 결코 가장 읽을 수 있는 코드가 아니다.설령 부모와/또는 조부모가 갱신되고 조종된다 하더라도 우리는 반드시 가치를 유지해야 한다.
우리는 마침내 더 좋은 방법을 찾아 이 문제를 처리했다.개별 숨겨진 레코드 목록을 유지하고 레코드가 표시되는지 확인하려는 경우 해당 목록을 질의하기로 했습니다.
let state = Immutable.fromJS({
  hiddenRecords: Immutable.Set(),
});

const setIsVisible = (record, isVisible) => {
  state = state.update(hiddenRecords, set => isVisible ? set.delete(record.id) : set.add(record.id);
};

const isVisible = (record) => {
  return !state.get(hiddenRecords).has(record.id);
};
일단 우리가 우연히 이런 모델을 발견하면, 우리는 그것을 많은 다른 부동산에 응용하여 큰 성공을 거두었다.확장 레코드, 활성 레코드, 선택 레코드 등의 목록이 추가되었습니다.
우리가 심지 모델을 조정하고 대상 시스템에서 기능이 더욱 강한 혼합 시스템으로 조정할 때 적응하는 데 시간이 필요하다.

SVG는 그리기에 적합


Gantt 그림을 자세히 보면, 주를 구분하는 수직선, 주말의 어두운 구역, 그리고 오늘의 위치를 표시하는 붉은 선을 볼 수 있습니다.
우리는 우리가 원하는 결과를 실현하기 위해 수백 개의 서로 다른 경계의div로 DOM을 채웠다.실험으로서 우리는 SVG 이미지를 동태적으로 구축하려고 시도했는데 결과가 매우 좋았다. 그것은 실현하기 쉽고 코드가 뚜렷하며 이전의 DIV 솔루션에 비해 출력량이 적었다.
// All the shapes that make the final SVG image
const shapes = [];

// week dividers
for(let week = firstWeek, x = 0; week <= lastWeek; week++, x += pixelsPerWeek) {
  shapes.push(
    `<line id="week-${week}" x1="${x}" x2="${x}" y1="0" y2="100" stroke="rgb(204,204,204)" stroke-width="0.5" />`
  );
}

// today
shapes.push(
  `<rect id="today" x="${pixelsToToday}" y="0" width="2" height="100" fill="rgba(255,0,0,0.3)" />`
);

// ...and finally build the CSS style
return {
  background: `url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="${timelineWidth}" height="100">${shapes.join(‘’)}</svg>') repeat-y`,
};

원래 Gantt 맵에서 새 Gantt 맵으로 마이그레이션


우리의 새로운 칸트맵은 많은 중요한 측면에서 서로 다르고 데이터 구조도 원시 칸트맵과 다르다. 그러면 우리는 어떻게 새로운 사용자로 하여금 그것을 사용하게 합니까?우리는 그들로 하여금 새로운 데이터에 같은 데이터를 다시 입력하게 하고 싶지 않다. 왜냐하면 그들 대부분은 이렇게 하지 않기 때문이다.우리도 원래의 하나를 보류하고 두 개를 동시에 보류하고 싶지 않다.유일한 해결 방법은 원래의 '이전'에서 새로운 방법으로 전환하는 것이다.
이를 실현하기 위해, 우리는 이전 서비스를 만들었습니다. 누군가가 원본 감트맵에 접근하려고 시도할 때, 자동으로 실행되고, 그것을 새 감트맵으로 전환한 다음, 그것으로 바꿉니다.우리는 이 두 가지 실현 중의 모든 설정 속성을 살펴보고 그들 사이의 매핑 방식을 찾았으며 논리를 실현했다.오류가 발생하지 않도록 원래 구성을 유지합니다.(별일 없었다.)마이그레이션 서비스는 Rails 데이터베이스 마이그레이션에서 영감을 얻었습니다.그 모양은 다음과 같습니다.
class LegacyGanttChartMigration
  def upgrade
    preserve_legacy_configuration
    convert_date_attributes
    convert_expanded_records
    # … a few more convert calls
    hide_features_without_dates
  end

  def downgrade
    # revert the configuration preserved above
  end
end

# and to migrate, all we had to do was call this
gantt_chart = LegacyGanttChartMigration.new(gantt_chart).upgrade
이런 이동은 테스트하기 쉽고 읽기 쉬우며 효과도 매우 좋다.

React 가상화를 사용하지 않는 이유


React Virtualized 의 설명을 읽을 때, Gantt도와 매우 일치해 보입니다.그들은 심지어 MultiGrid의 시범을 보여 주었다. 그것은 우리가 찾는 것과 매우 가깝다. 맨 위의 잠금(또는 동결) 줄, 왼쪽의 잠금 열, 그리고 양방향으로 굴러가서 잠긴 줄과 열을 정렬할 수 있는 메인 격자이다.이것이 바로 우리가 최초로 그것으로 새로운 칸트도를 실현한 원인이다.불행히도, 우리는 모든 부품의 양호한 작업을 유지하는 데 많은 어려움을 겪었다.판넬에 있는 스크롤 막대에 문제가 생겨서 정렬이 혼란스러워 어떤 시도를 해도 이 문제를 해결할 수 없습니다.우리는 심지어 ScrollSync만 사용하려고 시도했지만, 항상 약간의 지연이 있어서, 이것은 칸트도에서 이동하는 것을 매우 나쁘게 느끼게 했다.
그래서 결국 우리는 이 창고를 완전히 포기하고 우리가 필요로 하는 것을 실현했다.감트맵은 세 개의 주요 패널로 나뉜다.사용자가 스크롤할 때, 우리가 해야 할 일은 스크롤 위치를 관련 패널과 동기화하는 것이다.드래그 앤 드롭과 같은 성능 집약적 기능에 대해 우리는 화면에 보이는 내용만 렌더링하여 보이지 않는 대상에 대해 비싼 계산을 하지 않도록 했다.

이거 아직 안 끝났어요.


Gantt 차트에 기능을 추가하고 오류를 수정합니다.우리가 새로운 모델과 일하는 방식을 발견함에 따라, 우리는 이미 우리가 개선하고 싶은 많은 것을 축적했다.우리의 고객도 우리에게 귀중한 피드백을 제공했다. 우리는 다음에 무엇을 할 것인지를 결정할 때 항상 이런 피드백을 고려한다.만약 우리의 칸트도let us know에 무엇이 부족하다면.만약 당신이 우리가 건설하는 것을 돕기를 원한다면we’re always looking for new talent.

좋은 웹페이지 즐겨찾기