일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 메르페이
- node.js
- 체코
- PostgreSQL
- PayPay
- 熱海
- Python
- 카마츠루
- Selenium
- typescript
- 페이페이
- react.js
- 釜つる
- CSV
- 프라하
- javascript
- terraform
- 뮌헨
- 三井住友カード
- 태국
- 방콕
- duckdb
- 미츠이 스미토모
- local
- codebuild
- vba
- pyenv
- 아타미
- documentdb
- JenkinsFile
- Today
- Total
도쿄사는 외노자
사이드바를 통한 패널 이동 구현 (jQuery 사용) 본문
그동안 react.js와 jQuery를 같이 쓰지 않는다는 룰이 있어서
You don't need jQuery를 참고해 가며 꾸역꾸역 javascript로 코딩을 해 왔는데...
드디어 conponentDidMount() 이후에 한해 jQuery를 사용해도 된다는 허가가 떨어졌다.
하여, 몇몇 코드에 대대적인 공사가 들어갔고...
나 또한 이전의 leftNavigation를 jQuery로 갈아치우게 되었다.
디자인 수정도 겸해서, 거의 새로 만들다시피 하는 꼴이 되었는데...
하는 김에 MaterialUI의 drawer를 빼버리고, 그냥 div로 다 해결해 버렸다.
코드는 다음과 같다.
일단 componentDidMount() 이후, Navigation의 item을 만들기로 한다.
1 2 3 4 5 6 7 8 9 | constructor(props, context) { super(props, context); this.state = { menuItems: undefined, }; } componentDidMount() { this.makeMenuItems(); } | cs |
makeMenuItems에서는 이전과 동일하게 화면상의 panel을 긁어온다.
이후 각 패널을 for로 돌려서 menu div를 만들고, onClick function을 부여한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | makeMenuItems = () => { const panelList = $('div.accordionwrapper'); if (panelList.length === 0) return; const menuItems = []; [].forEach.call(panelList, (panel) => { const item = this.createItem(panel); menuItems.push(item); }); this.setState({ menuItems }); } createItem = (panel) => { const styles = this.getStyles(this.props, this.context); const panelTitle = panel.getElementsByClassName('paneltitle')[0]; return ( <MenuItem style={styles.item} onClick={() => this.setFocus(panel)} key={uuid()} > {panelTitle.textContent} </MenuItem> ); } | cs |
클릭 이벤트에서는, 받아온 패널을 조작하고, 스크롤 이동을 한다.
이전 코드에서의 길고 긴 삽질이, animate() 한줄로 해결되었다.
이 때, 마우스 호버 반복으로 애니메이션이 축적되는 일이 없도록, stop()을 거는 것을 잊지 말자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | setFocus = (panel) => { event.preventDefault(); // Panelを開く const panelarrow = $(panel).find('i.fa')[0]; const paneldata = $(panel).find('li.paneldata')[0]; $(panelarrow).removeClass('fa-angle-double-down'); $(panelarrow).addClass('fa-angle-double-up'); $(paneldata).slideDown(); // Scroll移動 const panelPosition = this.getOffset(panel); $('html, body').animate({ scrollTop: panelPosition.top }, 1000, 'swing'); } getOffset = (element) => { const box = element.getBoundingClientRect(); return { top: (box.top + window.pageYOffset) - document.documentElement.clientTop - 40, left: (box.left + window.pageXOffset) - document.documentElement.clientLeft }; } | cs |
이후 마우스 호버시 네비게이션을 넣었다 뺐다 할 수 있도록 준비해준다.
버튼은 냅두고 네비게이션 본체만 숨겼다 꺼내도록 해야 하며,
네비게이션의 길이가 패널 타이틀에 따라 변하는 관계로
네비게이션의 outerWidth를 구해서 marginLeft를 시켜야 한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | openNavi = (event) => { event.preventDefault(); const target = event.currentTarget; $(target).stop().animate({ marginLeft: '0px' }, 300); $(this.navArrow).removeClass('fa-angle-double-right'); $(this.navArrow).addClass('fa-angle-double-left'); } closeNavi = (event) => { event.preventDefault(); const target = event.currentTarget; const slideWidth = $(target).outerWidth(); $(target).stop().animate({ marginLeft: `-${slideWidth}px` }, 300); $(this.navArrow).addClass('fa-angle-double-right'); $(this.navArrow).removeClass('fa-angle-double-left'); } | cs |
render에 위의 기능을 붙여주기만 하면 끝.
FontAwesome의 클래스를 바꿔주어야 하므로, ref를 걸어주었다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | render() { const styles = this.getStyles(this.props, this.context); return ( <div className="leftNavi" style={styles.root} onMouseEnter={this.openNavi} onMouseLeave={this.closeNavi} > {this.state.menuItems} <div style={styles.itemBtn}> <i className="fa fa-angle-double-right fa-lg" aria-hidden="true" style={{ paddingTop: '20px' }} ref={(c) => { this.navArrow = c; }} /> </div> </div> ); } | cs |
이 상태에선 네비게이션이 나와 있는 상태로 화면이 떠 버리기에...
render이후 componentDidUpdate()에서 한번 네비게이션을 숨겨주도록 한다.
1 2 3 4 5 6 7 8 | componentDidUpdate() { this.initLeftNavi(); } initLeftNavi = () => { const leftNavi = $('div.leftNavi'); const slideWidth = $(leftNavi).outerWidth(); $(leftNavi).animate({ marginLeft: `-${slideWidth}px` }, 0); } | cs |
코드 내에서 getStyle()은 커스텀 테마에 적어 둔 CSS를 받아오는 부분인데...
딱히 CSS까지 공개할 필요는 없을 것 같으니 자세히는 적지 않겠다.
다만, 네비게이션인 이상 스크롤 이동시에도 따라와야 하므로...
zIndex와 position fixed는 꼭 넣어주도록 하자.
나머지는 자유롭게...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | ... navigation: { root: { zIndex: 1099, position: 'fixed', top: '25%', ... }, item: { position: 'relative', ... }, itemBtn: { position: 'absolute', ... }, }, ... | cs |
'Tech > React.js' 카테고리의 다른 글
react-router Link Tag에서의 disabled 적용 (0) | 2017.10.20 |
---|---|
Key-Break (0) | 2017.04.27 |
사이드바를 통한 패널 이동 구현 (0) | 2017.02.17 |
Warning: 'td' was passed a style object that has previously been mutated. (0) | 2017.02.09 |
props의 데이터가 파괴되는 문제 (0) | 2017.02.08 |