장기영 (Thomas Jang)
CHEQUER FrontEnd Director
tom@chequer.io
발표자료설명글 : https://goo.gl/YscrRr
액시스제이
구구너드.com
React datagrid component
with ES6, React, TypeScript
React datagrid component
with ES6, React, TypeScript
목차
- 데이터 그리드 란?
- 데이터 그리드를 만드는 이유
- 설계
- 주요코드 살펴보기
- 성능비교
- 후기
데이터 그리드란?
datagrid
데이터 그리드란?
웹에서 엑셀과 비슷한 경험을 주는 컴포넌트로 웹에서 많은 데이터를 표현하기 위해 사용
기존에는 grid라 불렀는데 datagrid로 이름 변경
ax5ui-grid
많은 데이터를
편리하게 보여줘
통일된 UI사용으로
개발편의성과 사용자경험 개선
데이터 그리드의 주요기능
- 원하는 영역 선택 후 클립보드에 저장하기
- 데이터 정렬 / 필터링
- 특정 데이터를 간단하게 수정하기 (inline edit)
- 셀의 데이터를 서식에 맞게 보여주기 (formatter)
- click, keyDown 이벤트 등에 따라 특정 작업 수행하기
- 멀티컬럼헤더(이건 한국인들만 원하는 게 아닐까..)
- 특정열 또는 행까지 틀 고정
- 컬럼의 너비 조정
- 데이터 그룹화 기능
가볍고, 빠르고, 쉽고,
멋지고 ...
데이터 그리드를 만드는 이유
AXISJ - AXGrid
이런 것도 만들었습니다. 2013년 (dev.axisj.com)
AX5UI - ax5ui-grid
이것도 만들었습니다. 2016년 (ax5.io)
새로운 코드가 필요한 시대
React로 개발하고 싶은 욕망
새로운 데이터 그리드 UI가 필요해
ES6, Webpack, React, TypeScript 몽땅 써야겠어.
설계
DOM 구조설계
SCROLL-CONTAINER
왜 이런 복잡한 구조가 필요할까?
왜 이런 복잡한 구조가 필요할까?
aside
left
top
스크롤 포지션
// scrollTop(ST)
// scrollBarTop(BT)
// scrollContainerHeight(SCH)
// scrollHeight(SH)
// scrollBarContainerHeight(BCH)
// scrollBarHeight(BH)
ST : SH - SCH = BT : BH - BCH
BT = ST * (BH - BCH) / (SH - SCH)
ST = (SH - SCH) * BT / (BH - BCH)
프로젝트 폴더 구성
Gulp 활용
요즘 대세는 NPM Script이지만 아직은 Gulp가 익숙합니다.
'gulp-shell'을 활용하면 못하는게 없습니다.
SRC 폴더 구성
- 같은 종류의 파일이 한 개 이상이 되면 폴더를 만든다.
- 하나의 파일로 만들 수 있는 경우라도 가능한 한 잘게 나누고 폴더에 index로 export 한다.
- 파일의 내용이 짧다면 파일로도 충분하다.
주요 코드 살펴보기
Thinking in React
jQuery
- 마우스다운 이벤트 발생
- 마우스이동 이벤트 발생
- 마우스이동량 계산
- scrollBar 엘리먼트 찾기
- scrollBar.style.top 조절
- scrollContent 엘리먼트 찾기
- scrollContent.style.top 조절
- 마우스업 이벤트 발생
- 상황종료
Thinking in React
React
- 마우스다운 이벤트 발생
- 마우스이동 이벤트 발생
- 마우스이동량 계산
- Grid.setState({scrollTop: y});
- 마우스업 이벤트 발생
- 상황종료
Container Dimension
public componentDidMount() {
this.gridRootNode = ReactDOM.findDOMNode(
this.refs.gridRoot
);
}
Container Dimension
public componentDidMount() {
this.gridRootNode = ReactDOM.findDOMNode( this.refs.gridRoot );
this.throttled_updateDimensions = throttle(
this.updateDimensions.bind( this ),
100
);
window.addEventListener(
'resize', this.throttled_updateDimensions
);
this.setState( { mounted: true } );
}
Container Dimension
public componentWillUnmount() {
window.removeEventListener(
'resize',
this.throttled_updateDimensions
);
}
// 이벤트 제거
Convert Columns
Convert Columns
export function makeHeaderTable( _columns, _options ) {
const columns = fromJS( _columns ).toJS();
let table = {
rows: []
};
return table;
}
Convert Columns
export function makeHeaderTable( _columns, _options ) {
const columns = fromJS( _columns ).toJS();
let table = {
rows: []
};
let colIndex = 0;
function maekRows(
_columns: iAXDataGridColumns[],
depth: number,
parentField?: any ): number
{
// https://github.com/axui/datagrid/blob/master/src/util/_makeData.ts#L18
}
maekRows( columns, 0 );
return table;
}
maekRows( columns, 0 );
// set rowspan
table.rows.forEach( ( row, ri ) => {
row.cols.forEach( ( col ) => {
if ( !('columns' in col) ) {
col.rowspan = table.rows.length - ri;
}
} );
} );
return table;
}
export function propsToState( props, state ) {
let dividedObj;
// state 계산영역 시작
state.headerTable = makeHeaderTable( props.columns, state.options );
state.bodyRowTable = makeBodyRowTable( props.columns, state.options );
state.bodyRowMap = makeBodyRowMap( state.bodyRowTable, state.options );
dividedObj = divideTableByFrozenColumnIndex(
state.headerTable,
state.options.frozenColumnIndex,
state.options
);
state.asideHeaderData = dividedObj.asideData;
state.asideColGroup = dividedObj.asideColGroup;
state.leftHeaderData = dividedObj.leftData;
state.headerData = dividedObj.rightData;
// https://github.com/axui/datagrid/blob/master/src/util/_props.ts#L20
}
Virtual Scroll
Virtual Scroll
const sRowIndex =
Math.floor( -scrollTop / bodyTrHeight ) + frozenRowIndex;
let bodyScrollConfig: iAXDataGridBodyPanelScrollConfig = {
frozenRowIndex: frozenRowIndex,
sRowIndex: sRowIndex,
eRowIndex: sRowIndex + Math.ceil( bodyHeight / bodyTrHeight ) + 1
};
성능비교
jQuery
React
후기
webpack.config.js
tsconfig.json
.babelrc
tslint.json
어렵다. 영어공부가 필요하다.
React
만족스럽다.
TypeScript
생각보다는 쉽다.