찾다
웹 프론트엔드JS 튜토리얼깔끔한 React 코드 작성을 위한 10가지 실용적인 팁

깔끔한 React 코드 작성을 위한 10가지 실용적인 팁

Jan 03, 2023 pm 08:18 PM
javascript프런트 엔드react.js

이 글은 더 간단한 React 코드를 작성하기 위한 10가지 실용적인 팁을 모아서 공유합니다. 모든 사람에게 도움이 되기를 바랍니다!

깔끔한 React 코드 작성을 위한 10가지 실용적인 팁

1. JSX 약어

주어진 props에 실제 값을 전달하는 방법은 무엇입니까? [관련 권장 사항: Redis 비디오 튜토리얼, 프로그래밍 비디오]

다음 예에서는 showTitle prop을 사용하여 탐색 모음 구성 요소에 애플리케이션 제목을 표시합니다. showTitle 在导航栏组件中显示应用的标题:

export default function App() {
  return (
    <main>
    <Navbar showTitle={true} />
  </main>
);
}

function Navbar({ showTitle }) {
  return (
    <div>
      {showTitle && <h1 id="标题">标题</h1>}
    </div>
  )
}

这里将 showTitle 显式设置为布尔值 true,其实这是没必要的,因为组件上提供的任何 prop 都具有默认值 true。因此只需要在调用组件时传递一个 showTitle 即可:

export default function App() {
  return (
    <main>
      <Navbar showTitle />
    </main>
  );
}

function Navbar({ showTitle }) {
  return (
    <div>
      {showTitle && <h1 id="标题">标题</h1>}
    </div>
  )
}

另外,当需要传递一个字符串作为 props 时,无需使用花括号 {} 包裹,可以通过双引号包裹字符串内容并传递即可:

export default function App() {
  return (
    <main>
      <Navbar title="标题" />
    </main>
  );
}

function Navbar({ title }) {
  return (
    <div>
      <h1 id="title">{title}</h1>
    </div>
  )
}

2. 将不相关代码移动到单独的组件中

编写更简洁的 React 代码的最简单和最重要的方法就是善于将代码抽象为单独的 React 组件。

下面来看一个例子,应用中最上面会有一个导航栏,并遍历 posts 中的数据将文章标题渲染出来:

export default function App() {
  const posts = [
    {
      id: 1,
      title: "标题1"
    },
    {
      id: 2,
      title: "标题2"
    }
  ];

  return (
    <main>
      <Navbar title="大标题" />
      <ul>
        {posts.map(post => (
          <li key={post.id}>
            {post.title}
          </li>
        ))}
      </ul>
    </main>
  );
}

function Navbar({ title }) {
  return (
    <div>
      <h1 id="title">{title}</h1>
    </div>
  );
}

那我们怎样才能让这段代码更加清洁呢?我们可以抽象循环中的代码(文章标题),将它们抽离到一个单独的组件中,称之为 FeaturedPosts。抽离后的代码如下:

export default function App() {
 return (
    <main>
      <Navbar title="大标题" />
      <FeaturedPosts />
    </main>
  );
}

function Navbar({ title }) {
  return (
    <div>
      <h1 id="title">{title}</h1>
    </div>
  );
}

function FeaturedPosts() {
  const posts = [
    {
      id: 1,
      title: "标题1"
    },
    {
      id: 2,
      title: "标题2"
    }
  ];

  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  );
}

如你所见,在 App 组件中,通过其中的组件名称:NavbarFeaturedPosts

// src/App.js
import Navbar from &#39;./components/Navbar.js&#39;;
import FeaturedPosts from &#39;./components/FeaturedPosts.js&#39;;

export default function App() {
  return (
    <main>
      <Navbar title="大标题" />
      <FeaturedPosts />
    </main>
  );
}

여기서 be showTitle은 부울 값 true로 명시적으로 설정됩니다. 구성 요소에 제공된 모든 prop에는 기본값 . 따라서 구성 요소를 호출할 때 showTitle만 전달하면 됩니다.

// src/components/Navbar.js
export default function Navbar({ title }) {
  return (
    <div>
      <h1 id="title">{title}</h1>
    </div>
  );
}
또한 문자열을 props로 전달해야 하는 경우 curly를 사용할 필요가 없습니다. 중괄호 { } 패키지의 경우 문자열 내용을 큰따옴표로 묶어 전달할 수 있습니다.
// src/components/FeaturedPosts.js
export default function FeaturedPosts() {
  const posts = [
    {
      id: 1,
      title: "标题1"
    },
    {
      id: 2,
      title: "标题2"
    }
  ];

  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  );
}

2 관련 없는 코드를 별도의 구성 요소로 이동하세요

깔끔한 React 코드를 작성하는 가장 간단하고 중요한 방법은 코드를 별도의 React 구성 요소로 추상화하는 데 능숙해지는 것입니다.

예를 살펴보겠습니다. 애플리케이션 상단에 탐색 모음이 있고 게시물의 데이터를 탐색하여 기사 제목을 렌더링합니다.

import React from &#39;react&#39;;

export default function FeaturedPosts() {
  const [posts, setPosts] = React.useState([]); 	
    
  React.useEffect(() => {
    fetch(&#39;https://jsonplaceholder.typicode.com/posts&#39;)
      .then(res => res.json())
      .then(data => setPosts(data));
  }, []);

  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  );
}

그래서 어떻게 만들 수 있나요? 이 코드 클리너? 루프(게시물 제목)의 코드를 추상화하여 이를 FeaturedPosts라고 하는 별도의 구성 요소로 가져올 수 있습니다. 추출된 코드는 다음과 같습니다.
import React from &#39;react&#39;;

export default function useFetchPosts() {
  const [posts, setPosts] = React.useState([]); 	
    
  React.useEffect(() => {
    fetch(&#39;https://jsonplaceholder.typicode.com/posts&#39;)
      .then(res => res.json())
      .then(data => setPosts(data));
  }, []);

  return posts;
}
보시다시피 App 컴포넌트에서는 Navbar, FeaturedPosts라는 컴포넌트 이름을 통해 빠르게 확인할 수 있습니다. 응용 프로그램.

3. 각 구성 요소에 대해 별도의 파일을 생성합니다

위의 예에서는 하나의 파일에 세 개의 구성 요소를 구현했습니다. 컴포넌트 로직이 작으면 이를 작성하는 데 문제가 없지만, 컴포넌트 로직이 더 복잡해지면 이렇게 작성된 코드의 가독성이 매우 떨어집니다. 앱 파일을 더 읽기 쉽게 만들려면 각 구성 요소를 별도의 파일에 넣을 수 있습니다.

이는 지원서에서 우려사항을 분리하는 데 도움이 됩니다. 즉, 각 파일은 하나의 구성 요소만 담당하며 앱에서 이를 재사용하려는 경우 구성 요소의 소스를 난독화하지 않습니다.

import useFetchPosts from &#39;../hooks/useFetchPosts.js&#39;;

export default function FeaturedPosts() {
  const posts = useFetchPosts()

  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  );
}
import useFetchPosts from &#39;../hooks/useFetchPosts.js&#39;;

export default function FeaturedPosts() {
  const posts = useFetchPosts()

  return (
    <ul>
      {posts.map((post) => (
        <li onClick={event => {
          console.log(event.target, &#39;clicked!&#39;);
        }} key={post.id}>{post.title}</li>
      ))}
    </ul>
  );
}
import useFetchPosts from &#39;../hooks/useFetchPosts.js&#39;;

export default function FeaturedPosts() {
  const posts = useFetchPosts()
  
  function handlePostClick(event) {
    console.log(event.target, &#39;clicked!&#39;);   
  }

  return (
    <ul>
      {posts.map((post) => (
        <li onClick={handlePostClick} key={post.id}>{post.title}</li>
      ))}
    </ul>
  );
}

또한 각 개별 구성 요소를 자체 파일에 포함하면 다음과 같은 문제를 피할 수 있습니다. a 파일이 너무 커집니다.

4. 공유 기능을 React 후크로 이동

FeaturedPosts 구성 요소에서 가짜 데이터를 사용하는 대신 API에서 기사 데이터를 가져오고 싶다고 가정해 보겠습니다. fetch API를 사용하여 이를 달성할 수 있습니다.

export default function App() {
  return (
    <main style={{ textAlign: &#39;center&#39; }}>
      <Navbar title="大标题" />
    </main>
  );
}

function Navbar({ title }) {
  return (
    <div style={{ marginTop: &#39;20px&#39; }}>
      <h1 id="title">{title}</h1>
    </div>
  )
}

하지만 여러 구성 요소에 대해 이 데이터 요청을 수행하려면 어떻게 해야 할까요?

FeaturedPosts 구성 요소 외에도 동일한 데이터를 포함하는 Posts라는 또 다른 구성 요소가 있다고 가정해 보겠습니다. 데이터를 가져오기 위한 로직을 복사하여 구성 요소에 붙여넣어야 합니다. 코드 중복을 방지하려면 useFetchPosts를 호출할 수 있는 새로운 React 후크를 정의할 수 있습니다.
export default function App() {
  const styles = {
    main: { textAlign: "center" }
  };

  return (
    <main style={styles.main}>
      <Navbar title="大标题" />
    </main>
  );
}

function Navbar({ title }) {
  const styles = {
    div: { marginTop: "20px" },
    h1: { fontWeight: "bold" }
  };

  return (
    <div style={styles.div}>
      <h1 id="title">{title}</h1>
    </div>
  );
}
이렇게 하면 FeaturedPosts 구성 요소를 포함한 모든 구성 요소에서 이를 재사용할 수 있습니다.

export default function EditButton({ post }) {
  const user = useAuthUser();  
  const isPostAuthor = post.author.userId !== user && user.userId;
    
  return isPostAuthor ? <EditButton /> : null;
}

5 JSX에서 JS 제거

구성 요소를 단순화하는 또 다른 방법은 JSX에서 가능한 한 많은 JavaScript를 제거하는 것입니다. 다음 예를 살펴보십시오.

export default function EditButton({ post }) {
  const user = useAuthUser();  
  const isPostAuthor = post.author.userId !== user?.userId;
    
  return isPostAuthor ? <EditButton /> : null;
}

여기서 기사의 클릭 이벤트를 처리하려고 하면 JSX가 읽기 어려워지는 것을 볼 수 있습니다. 함수가 인라인 함수로 포함되어 있으면 이 구성 요소의 목적과 관련 기능이 모호해집니다. 이 문제를 해결하는 방법은 무엇입니까? onClick이 포함된 인라인 함수를 별도의 핸들러 함수로 추출하고 이름을 handlerPostClick으로 지정할 수 있습니다. 이렇게 하면 JSX의 가독성이 높아집니다.

export default function App() {
  return (
    <Layout>
      <Routes />
    </Layout>
  );
}

6. 인라인 스타일 형식 지정

🎜JSX에 인라인 스타일을 너무 많이 작성하면 코드를 읽기가 더 어려워지고 커집니다. 🎜
const App = () => (
  <Layout>
    <Routes />
  </Layout>
);

export default App;
🎜 가능할 때마다 인라인 스타일을 CSS 스타일 시트로 옮기고 싶습니다. . 또는 개체로 구성하세요. 🎜
function PostList() {
  const posts = usePostData();  
    
  return posts.map(post => (
    <PostListItem key={post.id} post={post} />  
  ))
}
🎜 일반적으로 이러한 스타일을 CSS 스타일 시트에 작성하는 것이 가장 좋습니다. 스타일을 동적으로 생성해야 하는 경우 개체에 정의할 수 있습니다. 🎜🎜🎜7. 선택적 연결 연산자 사용🎜🎜🎜JavaScript에서는 해당 속성에 액세스하기 전에 먼저 개체가 존재하는지 확인해야 합니다. 객체의 값이 정의되지 않았거나 null이면 유형 오류가 발생합니다. 🎜🎜아래에서 사용자가 게시된 게시물을 편집할 수 있는 예를 살펴보세요. EditButton 구성 요소는 isPostAuthor가 true인 경우, 즉 인증된 사용자의 ID가 게시물 작성자의 ID와 동일한 경우에만 표시됩니다. 🎜
export default function EditButton({ post }) {
  const user = useAuthUser();  
  const isPostAuthor = post.author.userId !== user && user.userId;
    
  return isPostAuthor ? <EditButton /> : null;
}

这段代码的问题是 user 可能是 undefined. 这就是为什么我们必须在尝试获取 userId 属性之前使用 && 运算符来确保 user 是一个对象。如果我要访问一个对象中的另一个对象,就不得不再包含一个 && 条件。 这会导致代码变得复杂、难以理解。

JavaScript 可选链运算符(?.)允许我们在访问属性之前检查对象是否存在。用它来简化上面的代码:

export default function EditButton({ post }) {
  const user = useAuthUser();  
  const isPostAuthor = post.author.userId !== user?.userId;
    
  return isPostAuthor ? <EditButton /> : null;
}

这样将防止任何类型错误,并允许我们编写更清晰的条件逻辑。

8. 带括号的隐式返回

在 React 应用中可以使用 function 关键字的函数声明语法编写组件,也可以使用设置为变量的箭头函数。使用 function 关键字的组件必须在返回任何 JSX 之前使用 return 关键字。

export default function App() {
  return (
    <Layout>
      <Routes />
    </Layout>
  );
}

通过将返回的代码包裹在一组括号中,可以通过隐式返回(不使用 return 关键字)从函数返回多行 JavaScript 代码。

对于使用箭头函数的组件,不需要包含 return 关键字,可以只返回带有一组括号的 JSX。

const App = () => (
  <Layout>
    <Routes />
  </Layout>
);

export default App;

此外,当使用 .map() 迭代元素列表时,还可以跳过 return 关键字并仅在内部函数的主体中使用一组括号返回 JSX。

function PostList() {
  const posts = usePostData();  
    
  return posts.map(post => (
    <PostListItem key={post.id} post={post} />  
  ))
}

9. 使用空值合并运算符

在 JavaScript 中,如果某个值是假值(如 null、undefined、0、''、NaN),可以使用 || 条件来提供一个备用值。

例如,在产品页面组件需要显示给定产品的价格,可以使用 || 来有条件地显示价格或显示文本“产品不可用”。

export default function ProductPage({ product }) {    
  return (
     <>
       <ProductDetails />
       <span>
          {product.price || "产品不可用"}
       </span>
     </>
  );
}

现有的代码存在一个问题,如果商品的价格为0,也不会显示产品的价格而显示"产品不可用"。如果左侧为null或者undefined,而不是其他假值,就需要一个更精确的运算符来仅返回表达式的右侧。

这时就可以使用空值合并运算符,当左侧操作数为null或者 undefined 时,将返回右侧操作数。 否则它将返回其左侧操作数:

null ?? &#39;callback&#39;;
// "callback"

0 ?? 42;
// 0

可以使用空值合并运算符来修复上面代码中的问题:

export default function ProductPage({ product }) {    
  return (
     <>
       <ProductDetails />
       <span>{product.price ?? "产品不可用"}
     </>
  );
}

10. 使用三元表达式

在 React 组件中编写条件时,三元表达式是必不可少的,经常用于显示或隐藏组件和元素。

当然,我们用可以使用三元表达式和模板字符串来给 React 元素动态添加或删除类名。

export default function App() {
  const { isDarkMode } = useDarkMode();
    
  return (
    <main className={`body ${isDarkMode ? "body-dark" : "body-light"}`}>
      <Routes />
    </main>
  );
}

这种条件逻辑也可以应用于任何 props:

export default function App() {
  const { isMobile } = useDeviceDetect();
    
  return (
    <Layout height={isMobile ? &#39;100vh&#39; : &#39;80vh&#39;}>
      <Routes />
    </Layout>
  );
}

【推荐学习:javascript视频教程

위 내용은 깔끔한 React 코드 작성을 위한 10가지 실용적인 팁의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명
이 기사는 掘金社区에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제
JavaScript 엔진 이해 : 구현 세부 사항JavaScript 엔진 이해 : 구현 세부 사항Apr 17, 2025 am 12:05 AM

보다 효율적인 코드를 작성하고 성능 병목 현상 및 최적화 전략을 이해하는 데 도움이되기 때문에 JavaScript 엔진이 내부적으로 작동하는 방식을 이해하는 것은 개발자에게 중요합니다. 1) 엔진의 워크 플로에는 구문 분석, 컴파일 및 실행; 2) 실행 프로세스 중에 엔진은 인라인 캐시 및 숨겨진 클래스와 같은 동적 최적화를 수행합니다. 3) 모범 사례에는 글로벌 변수를 피하고 루프 최적화, Const 및 Lets 사용 및 과도한 폐쇄 사용을 피하는 것이 포함됩니다.

Python vs. JavaScript : 학습 곡선 및 사용 편의성Python vs. JavaScript : 학습 곡선 및 사용 편의성Apr 16, 2025 am 12:12 AM

Python은 부드러운 학습 곡선과 간결한 구문으로 초보자에게 더 적합합니다. JavaScript는 가파른 학습 곡선과 유연한 구문으로 프론트 엔드 개발에 적합합니다. 1. Python Syntax는 직관적이며 데이터 과학 및 백엔드 개발에 적합합니다. 2. JavaScript는 유연하며 프론트 엔드 및 서버 측 프로그래밍에서 널리 사용됩니다.

Python vs. JavaScript : 커뮤니티, 라이브러리 및 리소스Python vs. JavaScript : 커뮤니티, 라이브러리 및 리소스Apr 15, 2025 am 12:16 AM

Python과 JavaScript는 커뮤니티, 라이브러리 및 리소스 측면에서 고유 한 장점과 단점이 있습니다. 1) Python 커뮤니티는 친절하고 초보자에게 적합하지만 프론트 엔드 개발 리소스는 JavaScript만큼 풍부하지 않습니다. 2) Python은 데이터 과학 및 기계 학습 라이브러리에서 강력하며 JavaScript는 프론트 엔드 개발 라이브러리 및 프레임 워크에서 더 좋습니다. 3) 둘 다 풍부한 학습 리소스를 가지고 있지만 Python은 공식 문서로 시작하는 데 적합하지만 JavaScript는 MDNWebDocs에서 더 좋습니다. 선택은 프로젝트 요구와 개인적인 이익을 기반으로해야합니다.

C/C에서 JavaScript까지 : 모든 것이 어떻게 작동하는지C/C에서 JavaScript까지 : 모든 것이 어떻게 작동하는지Apr 14, 2025 am 12:05 AM

C/C에서 JavaScript로 전환하려면 동적 타이핑, 쓰레기 수집 및 비동기 프로그래밍으로 적응해야합니다. 1) C/C는 수동 메모리 관리가 필요한 정적으로 입력 한 언어이며 JavaScript는 동적으로 입력하고 쓰레기 수집이 자동으로 처리됩니다. 2) C/C를 기계 코드로 컴파일 해야하는 반면 JavaScript는 해석 된 언어입니다. 3) JavaScript는 폐쇄, 프로토 타입 체인 및 약속과 같은 개념을 소개하여 유연성과 비동기 프로그래밍 기능을 향상시킵니다.

JavaScript 엔진 : 구현 비교JavaScript 엔진 : 구현 비교Apr 13, 2025 am 12:05 AM

각각의 엔진의 구현 원리 및 최적화 전략이 다르기 때문에 JavaScript 엔진은 JavaScript 코드를 구문 분석하고 실행할 때 다른 영향을 미칩니다. 1. 어휘 분석 : 소스 코드를 어휘 단위로 변환합니다. 2. 문법 분석 : 추상 구문 트리를 생성합니다. 3. 최적화 및 컴파일 : JIT 컴파일러를 통해 기계 코드를 생성합니다. 4. 실행 : 기계 코드를 실행하십시오. V8 엔진은 즉각적인 컴파일 및 숨겨진 클래스를 통해 최적화하여 Spidermonkey는 유형 추론 시스템을 사용하여 동일한 코드에서 성능이 다른 성능을 제공합니다.

브라우저 너머 : 실제 세계의 JavaScript브라우저 너머 : 실제 세계의 JavaScriptApr 12, 2025 am 12:06 AM

실제 세계에서 JavaScript의 응용 프로그램에는 서버 측 프로그래밍, 모바일 애플리케이션 개발 및 사물 인터넷 제어가 포함됩니다. 1. 서버 측 프로그래밍은 Node.js를 통해 실현되며 동시 요청 처리에 적합합니다. 2. 모바일 애플리케이션 개발은 재교육을 통해 수행되며 크로스 플랫폼 배포를 지원합니다. 3. Johnny-Five 라이브러리를 통한 IoT 장치 제어에 사용되며 하드웨어 상호 작용에 적합합니다.

Next.js (백엔드 통합)로 멀티 테넌트 SAAS 애플리케이션 구축Next.js (백엔드 통합)로 멀티 테넌트 SAAS 애플리케이션 구축Apr 11, 2025 am 08:23 AM

일상적인 기술 도구를 사용하여 기능적 다중 테넌트 SaaS 응용 프로그램 (Edtech 앱)을 구축했으며 동일한 작업을 수행 할 수 있습니다. 먼저, 다중 테넌트 SaaS 응용 프로그램은 무엇입니까? 멀티 테넌트 SAAS 응용 프로그램은 노래에서 여러 고객에게 서비스를 제공 할 수 있습니다.

Next.js (Frontend Integration)를 사용하여 멀티 테넌트 SaaS 응용 프로그램을 구축하는 방법Next.js (Frontend Integration)를 사용하여 멀티 테넌트 SaaS 응용 프로그램을 구축하는 방법Apr 11, 2025 am 08:22 AM

이 기사에서는 Contrim에 의해 확보 된 백엔드와의 프론트 엔드 통합을 보여 주며 Next.js를 사용하여 기능적인 Edtech SaaS 응용 프로그램을 구축합니다. Frontend는 UI 가시성을 제어하기 위해 사용자 권한을 가져오고 API가 역할 기반을 준수하도록합니다.

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
1 몇 달 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
1 몇 달 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
1 몇 달 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 채팅 명령 및 사용 방법
1 몇 달 전By尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

안전한 시험 브라우저

안전한 시험 브라우저

안전한 시험 브라우저는 온라인 시험을 안전하게 치르기 위한 보안 브라우저 환경입니다. 이 소프트웨어는 모든 컴퓨터를 안전한 워크스테이션으로 바꿔줍니다. 이는 모든 유틸리티에 대한 액세스를 제어하고 학생들이 승인되지 않은 리소스를 사용하는 것을 방지합니다.

WebStorm Mac 버전

WebStorm Mac 버전

유용한 JavaScript 개발 도구

mPDF

mPDF

mPDF는 UTF-8로 인코딩된 HTML에서 PDF 파일을 생성할 수 있는 PHP 라이브러리입니다. 원저자인 Ian Back은 자신의 웹 사이트에서 "즉시" PDF 파일을 출력하고 다양한 언어를 처리하기 위해 mPDF를 작성했습니다. HTML2FPDF와 같은 원본 스크립트보다 유니코드 글꼴을 사용할 때 속도가 느리고 더 큰 파일을 생성하지만 CSS 스타일 등을 지원하고 많은 개선 사항이 있습니다. RTL(아랍어, 히브리어), CJK(중국어, 일본어, 한국어)를 포함한 거의 모든 언어를 지원합니다. 중첩된 블록 수준 요소(예: P, DIV)를 지원합니다.