비돔 속성?
dangerouslySetInnerHTML,ref,key
dom 표준이 아닌 속성, 즉 dom 표준에 지정된 속성이 없습니다. React는 위와 같이 세 가지 non-dom 속성을 도입합니다.
dangerouslySetInnerHTML: 말 그대로 위험하게 내부 html을 설정하는 속성입니다. 이 속성의 기능은 jsx에 html 코드를 직접 삽입하는 것입니다. HTML 코드를 삽입하기 위해 이 속성을 사용하는 이유는 무엇입니까? 코드를 작성할 때 직접 작성하는 대신? 때로는 코드를 작성할 때 어떤 코드를 삽입할지 확인할 수 없기 때문에 html 코드의 이 부분이 동적으로 생성된다는 의미입니다. 즉, 우리가 작성한 것이 아닌데 이런 행위가 왜 위험한가? Cross-Site Attack이라는 말이 있는데, Cross-Site Attack이 발생하는 이유는 바로 코드를 작성하는 기능 때문이다. , 페이지에 표시할 콘텐츠가 있는 경우 이 콘텐츠는 사용자의 입력에서 가져온 것입니다. 테스트 없이 직접 사용하는 경우 사용자의 입력에 이 DOM을 포함한다고 가정합니다. 그런 다음 다른 사람이 페이지를 방문하면 이 사람이 작성한 코드가 실행됩니다. 사용자의 의도를 판단할 수 없으므로 이 페이지를 방문하는 사용자는 트로이 목마에 연결을 추가하는 등 매우 위험한 코드를 작성할 수 있습니다. 자신도 모르게 바이러스에 감염되거나 트로이 목마를 다운로드하게 됩니다. 이는 매우 위험하지만 때로는 동적으로 코드를 작성해야 하므로 React는 이 속성을 계속 제공하지만 이름에는 이 속성이 명확하게 명시되어 있습니다. 매우 위험하므로 사용하지 마십시오.
ref의 약어: 참조. 상위 구성 요소는 하위 구성 요소를 참조합니다. 구성 요소를 작성할 때 상위 구성 요소에 중첩된 하위 구성 요소가 있는 경우 상위 구성 요소는 하위 구성 요소를 참조합니다. ref를 사용해야 합니다. 실제로 ref는 상위 구성 요소에 많은 참조를 유지하며, 각 참조는 해당 하위 구성 요소를 참조하므로 상위 구성 요소에서 이러한 참조를 통해 하위 구성 요소를 작동할 수 있습니다. 상위 구성 요소의 상위 구성 요소를 작동할 수 없는 이유는 무엇입니까? 이건 사실 코드 문제가 아니라 디자인 문제입니다. React에서 컴포넌트를 사용하는 목적은 코드를 모듈화하는 것입니다. 각 컴포넌트는 자체 기능과 로직만 고려하면 되며, 누가 사용하는지 신경 쓸 필요가 없습니다. 따라서 구성 요소는 자체 상위 구성 요소를 참조할 필요가 없으며 상위 구성 요소와 구성 요소 간의 상호 작용은 나중에 설명할 속성 전송을 통해 이루어집니다. 그러나 이러한 전송은 단방향입니다. 즉, 속성은 항상 위에서 아래로 전송되며 아래 구성 요소는 위 구성 요소를 제어하지 않습니다. 이는 논리를 더 명확하게 하기 위한 것입니다.
키: 개선 렌더링 성능. React의 특징 중 하나는 성능이 좋다는 것입니다. 이는 수동 DOM 작업을 제거하고 완전히 자동으로 구현하기 때문입니다. 그러나 자동 구현은 일련의 알고리즘이 있음을 의미하므로 페이지가 변경되면 React를 적용해야 합니다. 해당 변경 사항을 반영하기 위해 페이지를 효율적으로 수정하는 방법을 결정하는 알고리즘입니다. 이 알고리즘은 일반적으로 diff라고 불리며, 이는 두 상태 간의 차이를 계산하는 것을 의미합니다.
반응 비교 알고리즘
React diff 알고리즘의 흐름도
우선 지금 비교하고 있는 것이 두 가지 구성 요소라는 점을 분명히 해야 합니다. 비교, 나머지 구조는 비교를 위해 구성 요소로 나눌 수 있습니다.
가장 왼쪽이 시작입니다. 시작 후 첫 번째 판단은 노드가 동일한지 여부입니다. 이는 div와 div가 동일한지, div와 p가 다른지 또는 맞춤화된 HelloMessage와 HelloMessage가 동일한지를 의미합니다. , HelloMessage와 HelloWorld는 동일한 구성 요소가 아닙니다. 노드가 동일하면 후속 비교가 수행됩니다. 노드가 다르면 React는 이전 노드를 직접 삭제하고 새로운 노드를 생성합니다. 두 노드가 다르다면 그 내용은 크게 다릅니다. 노드가 다른 경우 비교를 직접 종료하고 새로운 노드를 생성합니다. 노드가 동일하면 다음 단계는 해당 포인트가 사용자 정의 노드인지 표준 노드인지, 즉 노드인지 여부입니다. divs 또는 HelloWorld.Custom 노드가 아니라 표준 노드라고 하면 React가 해야 할 다음 단계는 두 노드의 속성(class, id 등)을 비교하는 것입니다. 속성이 정확히 같다면 두 노드가 동일하고 비교가 종료된다는 의미입니다. ; 속성이 다르다면 다른 속성을 적어두고 변경 사항을 적용합니다. 속성이 하나 누락된 경우 유사한 작업을 삭제합니다. 즉, React는 이전 노드를 삭제하지 않고 해당 노드에서만 작동합니다. 사용자 정의 노드인 경우 React는 이를 다시 렌더링합니다. 구성 요소에 여러 상태가 있으면 새 구성 요소는 이전 구성 요소의 상태일 수 있습니다. Reac 새 상태가 이전 구성 요소에 전달된 다음 구성 요소의 렌더링 결과가 비교되고 변경됩니다. 즉, React는 여전히 구성 요소를 재생성하지 않지만 이전 구성 요소를 변경합니다. 이것이 diff 알고리즘입니다. 그렇다면 열쇠의 용도는 무엇입니까? 키의 역할은 주로 노드 비교에 반영됩니다. 즉, 상위 노드에 여러 개의 하위 노드가 있다고 가정해 보겠습니다. 키가 없고 변경하면 React는 다음과 같이 어리석게 비교합니다. 왼쪽에서 오른쪽으로. 예를 들어 변경 전에는 노드 1만 있었습니다. 변경 후에는 노드 2를 삽입하면 노드 2와 노드 1이 됩니다. 그러면 React에서 수행하는 작업은 노드 1을 삭제하고 노드를 추가하는 것입니다. 2, 그리고 노드 1을 추가합니다. 즉, React는 새로운 상태의 노드 1이 상태의 노드 1과 동일한지 여부를 확인할 수 없으므로 서로 다른 노드를 모두 삭제할 수만 있습니다. 성능 문제가 발생할 경우 키를 도입하는 목적은 각 노드에 고유 식별자를 추가하는 것입니다. 이러한 방식으로 키를 비교하여 반응은 어떤 노드가 원래 노드이고 어떤 노드가 새로 추가된 노드인지 알 수 있습니다. 방금 언급한 예에서는 노드 1이 노드 2가 됩니다. 1. 이때 React는 노드 2를 삽입하는 작업 하나만 수행하면 됩니다. 노드 1의 키가 동일하므로 동일하다는 의미입니다. 노드에는 변화가 없습니다.
이 원리를 이해하면 리액트 컴포넌트를 작성하는 것이 우리에게 어떤 영감을 주나요?
첫 번째 요점은 두 구성 요소가 매우 유사한 경우 하나의 구성 요소로 작성하는 것입니다. 왜냐하면 두 구성 요소의 내용이 매우 유사하더라도 두 개의 다른 구성 요소가 확실히 재생성된다는 것을 프로세스에서 확인했기 때문입니다. 두 번째 발견은 유사한 목록을 사용하여 요소를 표시하는 경우 요소에 키를 추가하면 효율성이 크게 향상되고 불필요한 성능 손실을 피할 수 있다는 것입니다.
dom이 아닌 속성을 어떻게 사용하나요?
위험한 인스턴스
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>hello world</title> </head> <body> <script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/react.js"></script> <script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/JSXTransformer.js"></script> <script type="text/jsx"> var style={ color:"red", border:"1px solid #f09", }; var rawHTML={ __html:"<h1>I am inner HTML</h1>" }; var HelloWorld=React.createClass({ render: function(){ return <p>Hello,world</p> } }); React.render(<div style={style} dangerouslySetInnerHTML={rawHTML}></div>,document.body); </script> </body> </html>
ref 인스턴스, 참조를 통해 얻는 것은 dom 노드 자체가 아니므로 텍스트 설정과 같은 dom 간의 작업을 수행할 수 없다는 점에 유의하세요. 불가능합니다. 우리가 얻는 것은 단지 가상 DOM 노드입니다. 이는 우리에게 표시되는 DOM 노드입니다. 실제 DOM 노드를 얻으려면 나중에 설명하겠지만 반응해야 합니다. 그렇지 않습니다. 특별한 상황이 아닌 이상 dom 노드를 작동해야 하는 경우를 제외하고는 React가 이를 작동하는 데 도움이 될 것입니다.
이 예제는 완전하지 않습니다. 나중에 계속 설명해주세요.
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>hello world</title> </head> <body> <script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/react.js"></script> <script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/JSXTransformer.js"></script> <script type="text/jsx"> var style={ color:"red", border:"1px solid #f09", }; var rawHTML={ __html:"<h1>I am inner HTML</h1>" }; var HelloWorld=React.createClass({ render: function(){ this.refs.childp return <p ref="childp">Hello,world</p> } }); React.render(<div style={style} dangerouslySetInnerHTML={rawHTML}></div>,document.body); </script> </body> </html>
키 인스턴스: 각 구성 요소 내에서 키 값은 구성 요소 내부에 달라야 합니다. 두 구성 요소 간에는 그러한 제한이 없습니다.
두 가지 사항을 기억하세요. 1. 유사한 내용을 가진 구성 요소를 동일한 구성 요소로 병합해 보세요. 2. 목록 유형 요소는 고유한 키를 사용하여 추가해야 합니다. 이 두 가지 사항을 수행하면 많은 성능 문제를 피할 수 있습니다.
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>hello world</title> </head> <body> <script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/react.js"></script> <script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/JSXTransformer.js"></script> <script type="text/jsx"> var style={ color:"red", border:"1px solid #f09", }; var rawHTML={ __html:"<h1>I am inner HTML</h1>" }; var HelloWorld=React.createClass({ render: function(){ return <ul> <li key="1">1</li> <li key="2">2</li> <li key="3">3</li> </ul> } }); React.render(<div style={style} dangerouslySetInnerHTML={rawHTML}></div>,document.body); </script> </body> </html>