select 노드 clone 전체 분석

10996 단어 select
개발 ns - log 프로젝트 에서 통계 분 류 는 복제 기능 이 있다.이전 통계 분류 에서 의 데 이 터 는 JS 할당 을 통 해 들 어 갔 기 때문에 나중에 사용자 가 다시 수정 을 했 을 수도 있 습 니 다. 노드 복 제 를 할 때 select 드 롭 다운 상자 값 을 복사 할 수 없 는 이상 한 현상 이 나 타 났 습 니 다.본 고 는 이 괴이 한 현상 에 대해 해석 하고 해결 방법 을 제시한다.
문제 의 현황
노드 의 cloneNode (true / false) 를 사용 하여 복 제 를 진행 할 때 현재 다음 과 같은 상황 입 니 다.
select 는 초기 값 이나 초기 값 을 설정 하 는 것 이 첫 번 째 option 입 니 다.표현: 각 브 라 우 저 는 문제 가 없습니다.
select 초기 값 은 첫 번 째 option 이 아 닙 니 다.표현: IE 에서 복제 할 수 없습니다. 다른 커 널 의 브 라 우 저 는 문제 가 없습니다.
select 의 값 은 사용자 나 JS 에 의 해 수정 되 었 습 니 다.표현: 각 브 라 우 저 는 정확 한 값 으로 복제 할 수 없습니다.값 결 과 는 두 번 째 결과 와 같다.
IE 의 특수 처리
위의 두 번 째 조 에 대해 초기 값 이 첫 번 째 option 에 없 을 때 복제 할 수 없 는 상황 은 IE 의 Bug 이 므 로 많은 사람들 이 이런 문 제 를 겪 었 을 것 이 라 고 믿 습 니 다.또한 IE 에서 cloneNode 방법 을 사용 할 때 이벤트 에 문제 가 있 기 때문에 이 방법 을 포기 할 수 있 는 경우 가 많 지 않 습 니 다.
IE 에서 노드 의 outerHTML 속성 을 사용 하여 이 문 제 를 해결 할 수 있 습 니 다. 이 문 제 는 select 의 값 이 사용자 나 프로그램 에 의 해 바 뀌 더 라 도 실시 간 으로 노드 의 내용 을 얻 을 수 있 습 니 다.간단 한 실현 을 보 여 드 리 겠 습 니 다.
function clone(node) {
    var div = document.createElement('div');
    div.innerHTML = node.outerHTML;
    return div.childNodes[0];
}

기타 커 널 브 라 우 저 처리
IE 커 널 의 브 라 우 저 는 outerHTML 속성 을 통 해 이 문 제 를 해결 할 수 있 으 니 FF 등 브 라 우 저 는 비슷 한 방법 으로 이 루어 질 수 있 습 니까?FF 등 브 라 우 저 는 outerHTML 속성 이 없 지만 innerHTML 속성 을 통 해 이 루어 집 니 다. 예 를 들 어:
function getOuterHTML(node) {
    var div = document.createElement('div');
    div.appendChild(node);
    try {
        return div.innerHTML;
    } catch (e) {
        div = null;
    }
}

정 답 은 부정 이다.
왜 이러 지?혹시 FF 등 브 라 우 저의 bug 인가요?
다음은 W3C 에서 cloneNode 방법, select 태그, 속성의 정 의 를 설명 합 니 다.
아래 에 인 용 된 자 료 는 모두 HTML 5 초안 에서 나 온 것 으로 HTML 4 나 XHTML 은 이에 대해 상세 한 정 의 를 내리 지 않 았 다.HTML 5 이지 만 이 노드 들 은 이전 과 변 함 이 없다.
W3C 의 cloneNode
구체 적 인 링크: http://www.w3.org/TR/DOM-Level-2-Core/core.html
안 에는 두 가지 가 중요 하 다.
복제 할 때 노드 의 모든 속성 과 대응 하 는 값 을 복사 합 니 다.
clone Node 방법의 매개 변수 가 true 라면 재 귀적 인 방법 으로 하위 노드 를 복제 합 니 다.
W3C 의 select 노드
구체 적 인 링크: http://dev.w3.org/html5/spec/forms.html#the-select-element
W3C 의 속성 에 대한 정 의 는 2 가지 가 있 는데 하 나 는 내용 성 속성 (Content attributes) 이 고 다른 하 나 는 조작 성 속성 (구체 적 인 이름 을 제시 하지 않 았 습 니 다. 이 이름 을 잠시 사용 합 니 다) 입 니 다.
select 태그 에 대해 내용 성 속성 은 주로 Global attributes, autofocus, disabled, form, multiple, name, size 가 있 습 니 다.그 중에서 Global attributes 는 자주 사용 하 는 속성 (accesskey, class, contenteditable, contextmenu, dir, draggable, hidden, id, itemid, itemprop, itemref, itemscope, itemtype, lang, spellcheck, style, tabindex, title) 을 포함 하고 있 습 니 다. 이 속성 들 은 모든 탭 에 포함 되 어 있 습 니 다. 구체 적 으로 보면 http://dev.w3.org/html5/spec/dom.html#global-attributes
그리고 selected Index 와 value 는 모두 조작 성 속성 에 속 합 니 다. 이 두 속성 이 값 을 얻 는 방식 은 다음 과 같 습 니 다.
select . 
selectedIndex [ = 
value ]
Returns the index of the first selected item, if any, or −1 if there is no selected item. Can be set, to change the selection.
select . 
value  [ = 
value ]
Returns the 
value  of the first selected item, if any, or the empty string if there is no selected item. Can be set, to change the selection.
내용 성 속성 과 조작 성 속성의 차이
노드 에 속성 을 추가 하 는 방법 은 두 가지 가 있 습 니 다. 아래 와 같 습 니 다.
var div = document.createElement('div')
div.id = 'welefen'; //     
div.setAttribute('id','welefen'); //  setAttribute      

내용 성 속성 에 대해 이 두 가지 방법 은 완전히 같다.
그러나 조작 성 속성 에 대해 첫 번 째 방식 은 속성 을 조작 범위 에 만 추가 하고 노드 를 DOM 에 추가 하면 속성 이 효력 을 잃 습 니 다.
selected Index 와 value 는 모두 조작 성 속성 이기 때문에 select 의 값 이 사용자 나 프로그램 에 의 해 바 뀌 면 clone 의 현재 값 은 가 져 갈 수 없습니다. 따라서 값 을 복제 할 수 없 는 상황 이 발생 합 니 다. 또한 innerHTML 을 사용 하여 값 을 복제 할 수도 없습니다. innerHTML 의 원 리 는 이것 과 같 기 때 문 입 니 다.
innerHTML 실현 원 리 는 여 기 를 보십시오.
FF 등 브 라 우 저 솔 루 션
현재 2 가지 솔 루 션 이 있 습 니 다. 첫 번 째 는 select 바 인 딩 change 이벤트 입 니 다. change 를 실행 할 때 options 의 selected 속성 을 바 꾸 는 것 입 니 다. 물론 이 방법 은 바람 직 하지 않 습 니 다. 다른 방안 은 복제 할 때 요소 의 값 을 가 져 온 다음 복제 후의 대상 에 값 을 부여 하 는 것 입 니 다.
총결산
현재 이 상황 이 발생 했 을 때 FF 등 브 라 우 저의 bug 인 줄 알 았 습 니 다. 나중에 곰 곰 이 생각해 보면 그렇지 않 을 것 같 습 니 다. 나중에 W3C 관련 문 서 를 반복 적 으로 살 펴 보고 이 문 제 를 확 인 했 습 니 다. 다음은 완전한 해결 방안 을 제시 합 니 다.
function cloneSelect(select) { if (document.all) { var html = select.outerHTML, div = document.createElement('div');
        div.innerHTML = html;
        return div.childNodes[0];
    }
    var cloneSelect = select.cloneNode(true);
    cloneSelect.selectedIndex = select.selectedIndex;
    cloneSelect.value = select.value;
    return cloneSelect;
}

링크: http://www.welefen.com/select-clone.html

좋은 웹페이지 즐겨찾기