>웹 프론트엔드 >JS 튜토리얼 >Hongmeng JavaScript GUI 기술 스택을 살펴 보겠습니다.

Hongmeng JavaScript GUI 기술 스택을 살펴 보겠습니다.

coldplay.xixi
coldplay.xixi앞으로
2020-09-14 13:28:552728검색
<p>Hongmeng JavaScript GUI 기술 스택을 살펴 보겠습니다.

<p>관련 학습 권장 사항: javascript 비디오 튜토리얼

<p>우리 모두 알고 있듯이 새로 오픈 소스인 "Hongmeng 2.0"은 IoT 애플리케이션 개발을 위한 프레임워크 언어로 JavaScript를 사용합니다. 이는 SpaceX가 등장한 이후 JavaScript가 뉴스 네트워크 수준에서 다시 한 번 뜨거운 주제가 되었음을 의미합니다. 이런 좋은 기회에 음과 양만을 활용하는 것은 아쉽습니다. 대중적인 과학으로서 이 기사에서는 결함을 찾기 위해 코드의 결함을 찾기 위해 돋보기를 사용하지 않을 것입니다. 대신에 지원하는 GUI가 무엇인지 대중적으로 설명하고 싶습니다. 컴퓨터 기본 사항에 대한 일반적인 이해가 있는 한 이 기사를 읽는 데 아무런 장애가 없어야 합니다.

<p>우리는 이미 "Hongmeng 2.0"에서 개발자가 Vue 구성 요소 형태로 JavaScript 비즈니스 로직을 작성하여 스마트 시계와 같은 임베디드 하드웨어의 UI 인터페이스로 렌더링하면 된다는 것을 이미 알고 있습니다. 이 프로세스에 어떤 핵심 모듈이 포함되어야 합니까? 이 모듈 중 자체 개발된 모듈은 무엇이며, 이미 만들어진 오픈 소스 프로젝트를 사용하는 모듈은 무엇입니까? 위에서 아래로 3개의 추상 레이어로 나누어 소개합니다.

  • JS 프레임워크 레이어는 매우 단순화된 Vue 스타일 JavaScript 프레임워크로 이해될 수 있습니다.
  • JS 엔진 및 런타임 레이어는 이해될 수 있습니다. 이것은 크게 단순화된 WebKit 스타일 런타임
  • 그래픽 렌더링 레이어로, 매우 단순화된 Skia 스타일 그래픽 드로잉 라이브러리
<p>이 세 가지 추상화 레이어는 전체적으로 GUI 기술 세트를 구성합니다. 임베디드 하드웨어 스택. "불분명/헤아릴 수 없음"을 외치는 많은 대중의 의견과는 다르게, 저는 개인적으로 적어도 GUI 부분에 대해서는 현재의 주류 하이브리드 크로스엔드 솔루션이나 JS 런타임 개발에 노출된 중국의 일선 개발자라면 누구나 쉽게 할 수 있다고 생각합니다. 소스 코드부터 시작하여 이해하세요. 레이어별로 해석하고 분석해 보겠습니다.

JS Framework Layer

<p>최상위 관점에서 "Hongmeng 2.0"을 사용하여 동적 텍스트를 렌더링하려면 다음 HML(XML과 유사한) 형식 코드만 작성하면 됩니다.

<!-- hello.hml --><text onclick="boil">{{hello}}</text>复制代码
<p>그런 다음 같은 레벨 디렉토리 JavaScript를 다음과 같이 작성하세요:

// hello.jsexport default {  data: {    hello: 'PPT'
  },
  boil() {    this.hello = '核武器';
  }
}复制代码
<p>텍스트를 클릭하는 동안 boil 메소드가 호출되어 PPTnuclear로 전환합니다. 무기. boil 方法,让 PPT 变成 核武器

<p>这背后发生了什么呢?熟悉 Vue 2.0 的同学应该会立刻联想到下面这几件事:

  • 需要对 XML 的预处理机制,将其转换为 JS 中的嵌套函数结构。这样只需在运行时做一次简单 eval ,即可用 JS 生成符合 XML 结构的 UI。
  • 需要事件机制,使得触发 onclick 事件时能执行相应回调。
  • 需要数据劫持机制,使得对 this.hello 赋值时能执行相应回调。
  • 需要能在回调中更新 UI 对象控件。
<p>这几件事分别是怎么实现的呢?简单说来是这样的:

  • XML 预处理依赖现成的 NPM 开源包,从而把 XML 中的 onclick 属性转换为 JS 对象的属性字段。
  • 事件的注册和触发都直接由 C++ 实现。如上一步所获得的 JS 对象 onclick 属性会在 C++ 中被检查和注册,相当于全部组件均为原生。
  • 数据劫持机制用 JS 实现,是个基于 Object.defineProperty 的(几百行量级的)ViewModel。
  • UI 控件的更新,会在 ViewModel 自动执行的 JS 回调中,调用 C++ 的原生方法实现。这部分完全隐式完成,并未开放 document.createElement 式的标准化 API。
<p>由于大量常见 JS 框架中的能力都直接做进了 C++,所以整套 GUI 技术栈里用纯 JavaScript 所实现的东西(主要见 ace_lite_jsfwk 仓库下的 core/index.jsobserver.jssubject.js

이 뒤에 무슨 일이 일어났나요? Vue 2.0에 익숙한 학생은 즉시 다음 사항을 생각해야 합니다. <p> XML을 JS의 중첩 함수 구조로 변환하려면 XML에 대한 전처리 메커니즘이 필요합니다. 이런 방식으로 런타임 시 간단한 평가만 수행하면 되며, JS를 사용하여 XML 구조에 맞는 UI를 생성할 수 있습니다.

<p>onclick 이벤트가 발생했을 때 해당 콜백이 실행될 수 있도록 이벤트 메커니즘이 필요합니다.

this.hello에 값을 할당할 때 해당 콜백이 실행될 수 있도록 데이터 하이재킹 메커니즘이 필요합니다.

<p>콜백에서 UI 개체 컨트롤을 업데이트할 수 있어야 합니다.

🎜🎜이런 일들은 어떻게 달성되나요? 간단히 말하면, 🎜🎜🎜🎜XML 전처리🎜는 기성 NPM 오픈 소스 패키지를 사용하여 XML의 onclick 속성을 ​​JS 객체의 속성 필드로 변환합니다. 🎜🎜🎜이벤트 등록 및 트리거링🎜은 C++에서 직접 구현됩니다. 이전 단계에서 얻은 JS 객체의 onclick 속성을 ​​확인하고 C++에 등록합니다. 이는 모든 구성 요소가 네이티브인 것과 동일합니다. 🎜🎜🎜데이터 하이재킹 메커니즘🎜은 JS로 구현되며 Object.defineProperty를 기반으로 하는 ViewModel(수백 줄 크기)입니다. 🎜🎜🎜UI 컨트롤 업데이트🎜는 ViewModel에 의해 자동으로 실행되는 JS 콜백에서 C++ 네이티브 메서드를 호출하여 구현됩니다. 이 부분은 완전히 암시적으로 수행되며 document.createElement 스타일의 표준화된 API를 노출하지 않습니다. 🎜🎜🎜일반적인 JS 프레임워크의 많은 기능이 C++에 직접 구현되므로 전체 GUI 기술 스택은 순수 JavaScript로 구현됩니다(주로 ace_lite_jsfwk 웨어하우스 인덱스 아래의 core/ 참조). js, observer.jssubject.js)는 이 기능만 갖는 것과 동일합니다: 🎜🎜🎜감시할 수 있는 ViewModel. 🎜🎜🎜순수한 JS 프레임워크 부분의 구현 복잡성과 품질에 관해서는 객관적으로 말하자면 개인 아마추어 작업이라면 학교 채용 면접에서 좋은 보너스로 사용될 수 있습니다. 🎜🎜JS 엔진 및 런타임 레이어🎜🎜JS 프레임워크 레이어를 이해한 후에는 "Hongmeng 2.0"이 고도로 단순화된 Vue를 C++로 심층적으로 사용자 정의하기로 선택했다고 생각할 수도 있고 고도로 단순화된(그리고 비공개) DOM은 지원하는 프런트엔드 프레임워크를 구현합니다. 따라서 이 GUI의 원리를 계속 탐색하려면 C++ 부분에 들어가 JS 엔진 및 런타임 계층의 구현을 이해해야 합니다. 🎜<p>JS 엔진과 런타임의 차이점과 연관성은 무엇인가요? JS 엔진은 일반적으로 "부작용"이 있는 플랫폼 API를 정의하지 않는 ECMA-262 사양만 준수하면 됩니다. setTimeout에서 document.getElementById, console.log, fs.readFile까지 실제 IO 작업을 수행할 수 있습니다. 기능은 "엔진 API와 플랫폼 API를 함께 접착"하는 런타임에 의해 제공되어야 합니다. 런타임 자체의 원리는 복잡하지 않습니다. 예를 들어 내 개인 기사인 "JS 엔진에서 JS 런타임으로"에서는 이미 만들어진 QuickJS 엔진의 도움으로 직접 런타임을 빌드하는 방법을 볼 수 있습니다. setTimeoutdocument.getElementByIdconsole.log 再到 fs.readFile,这些能执行实际 IO 操作的功能,都需要由「将引擎 API 和平台 API 胶合到一起」的运行时提供。运行时本身的原理并不复杂,譬如在个人的文章《从 JS 引擎到 JS 运行时》中,你就可以看到如何借助现成的 QuickJS 引擎,自己搭建一个运行时。

<p>那么在「鸿蒙 2.0」中,JS 运行时是如何搭建出来的呢?有这么几条重点:

  • JS 引擎选择了 JerryScript,这是一款由三星开发的嵌入式 JS 引擎。
  • 每种形如 <text><p> 的 XML 标签组件,都对应一个绑定到 JerryScript 上的 C++ Component 类,如 TextComponentpComponent 等。
  • 除 UI 原生对象外,还有一系列在 JS 中以 @system 为前缀的 built-in 模块,它们提供了 JS 中可用的 Router / Audio / File 等平台能力(参见 ohos_module_config.h)。
<p>这里特别值得一提的是 Router。它和 vue-router 等常见 Web 平台路由的实现原理有很大区别,是专门在运行时内深度定制的(参见 router_module.cppjs_router.cppjs_page_state_machine.cpp)。简单说来这个「路由」是这样实现的:

  • 在 JS 中调用切换页面的 router.replace 原生方法,走进 C++。
  • C++ 中根据新页面 URI 路径(如 pages/detail
  • 그럼 "홍멍 2.0"에서는 JS 런타임이 어떻게 구축되나요? 몇 가지 핵심 사항이 있습니다:
    • JS 엔진은 삼성에서 개발한 임베디드 JS 엔진인 JerryScript를 선택했습니다.
    • <text><p> 형식의 각 XML 태그 구성 요소는 TextComponent 및 <code>pComponent
    <p>JS에는 UI 기본 개체 외에도 JS에서 사용할 수 있는 라우터/오디오/파일과 같은 플랫폼 기능을 제공하는 @system 접두사가 붙은 일련의 내장 모듈도 있습니다( ohos_module_config.h).

    <p>

    여기서 특히 언급할 가치가 있는 것은 라우터입니다. 이는 vue-router와 같은 일반적인 웹 플랫폼 라우팅의 구현 원칙과 매우 다릅니다. 런타임 중에 특별히 맞춤화됩니다(router_module.cpp, js_router.cppjs_page_state_machine.cpp). 간단히 말해서 이 "라우팅"은 다음과 같이 구현됩니다. <p>

      JS에서 페이지를 전환하는 router.replace 기본 메서드를 호출하고 C++를 입력합니다. <p>

      C++에서는 새 페이지 URI 경로(예: pages/detail)에 따라 새 페이지 JS를 로드하고 새 페이지 상태 머신 인스턴스를 생성한 후 Init 상태로 전환합니다.
      Hongmeng JavaScript GUI 기술 스택을 살펴 보겠습니다.새 상태 머신의 Init 프로세스에서 JS 엔진을 호출하여 새 페이지의 JS 코드를 평가하고 새 페이지의 ViewModel을 얻습니다.
      ViewModel에 경로 매개변수를 추가하고 이전 상태 머신과 그 위의 JS 개체를 삭제합니다.
      <p>

      여기서 소위 "경로 전환"이 실제로 웹 브라우저의 "페이지 새로 고침"에 더 가깝다는 것을 알 수 있습니다. 그렇다면 이 JS 런타임의 기능이 이미 WebKit 수준 브라우저 커널을 벤치마킹할 수 있다고 생각할 수 있습니까? <p>

      물론 아직 갈 길이 멀다. WebKit과 비교할 때 HTML 및 CSS의 구문 분석을 지원하지 않으며(둘 다 개발 단계에서 동일한 실행 효과로 구문 분석되고 JS로 변환됨) 리소스를 지속적으로 동적으로 로드, 구문 분석 및 실행해야 하는 과제도 없습니다. 브라우저(작은 프로그램은 몇 개의 로컬 정적 JS 파일에 지나지 않습니다). 조판, 레이아웃, 렌더링에 관해서는 당연히 큰 격차가 있는데, 이는 마지막 섹션에서 언급하겠습니다. 🎜🎜그리고 많은 학생들이 JerryScript 엔진에 대해 궁금해할 거라 믿습니다. 이 섹션은 이 문제에 대한 일부 개인 정보를 공유하는 것으로 마무리됩니다. 🎜🎜JerryScript 엔진은 임베디드 하드웨어용으로 특별히 구현된 JS 인터프리터이며 ES5.1 표준만 지원합니다. QuickJS 벤치마크에서 성능 비교 결과를 볼 수 있습니다. 🎜🎜🎜🎜🎜🎜🎜성능 측면에서 JerryScript는 JIT가 없는 엔진에서 QuickJS 및 Hermes보다 훨씬 약하다는 것을 알 수 있습니다. JIT를 켠 V8과 비교하면 두 배 정도 느려집니다. 따라서 이는 저사양 장치를 위한 매우 구체적인 엔진입니다. React 및 Vue(또는 해당 제품군 버킷)와 같은 중대형 프런트 엔드 프로젝트에서 표준인 기본 라이브러리를 지원해야 하는 경우에도 여전히 필요할 수 있습니다. 더 강력한 엔진을 사용하기 위해 🎜🎜 JerryScript 사용과 관련하여, RT-Thread 창립자 @midnightbear는 의심할 여지없이 동일한 시나리오에서 풍부한 응용 경험을 갖고 있는 사람입니다. 그들이 국내 1차 제조업체와 협력하여 개발한 스마트 워치는 JerryScript를 사용하여 UI를 구현했습니다. 제품이 곧 출시될 예정입니다. JerryScript 사용에 대한 팀의 일부 피드백도 위의 평가와 일치합니다. 🎜
      • JerryScript 在体积和内存占用上,相比 QuickJS 有更好的表现。
      • JerryScript 的稳定性弱于 QuickJS,有一些难以绕过的问题。
      • JerryScript 面对稍大(1M 以上)的 JS 代码库,就有些力不从心了。
      <p>那么师出名门的 QuickJS 和 Facebook 的 Hermes,是否就是无 JIT 式 JS 引擎的下一代标杆了吗?倒也未必如此。这方面可以参考个人的知乎回答:随着 TypeScript 继续普及,会不会出现直接跑 TypeScript 的运行时?这里提到的微软为教育项目 MakeCode 研发的 Static TypeScript,就相当有潜力成为下一代的高性能 JS 系语言环境。通过限定 TypeScript 的静态强类型子集并为其搭建工具链,STS 可以做到无需 JIT 也能接近 V8 的性能水平,同时内存占用比 V8 少两个数量级。这使得 STS 不光能用于开发普通 app 这类 IO 密集的应用,还能顺利在嵌入式硬件上开发小游戏这类更偏计算密集(需逐帧更新渲染)的应用,在工程能力上是一项很大的突破。

      <p>所以说,当「鸿蒙 2.0」还需要熟练开发者勉强搭建出环境跑通 Hello World 时,微软已经让上百万小朋友都能用 TypeScript 在网页里给教学用的掌上游戏机写小游戏入门编程了。这里没什么唱反调的意思,只希望提醒一下我们在为国产「里程碑」欢呼时,也要清醒地看到业界前沿的动向,仅此而已。

      图形绘制层

      <p>理解 JS 运行时之后,还剩最后一个问题,即 JS 运行时中的各种 Component 对象,是如何被绘制为手表等设备上的像素的呢?

      <p>这就涉及「鸿蒙 2.0」中的另一个 graphic_lite 仓库了。可以认为,这里才是真正执行实际绘制的 GUI。像之前的 TextComponent 等原生组件,都会对应到这里的某种图形库 View。它以一种相当经典的方式,在 C++ 层实现并提供了「Canvas 风格的立即模式 GUI」和「DOM 风格的保留模式 GUI」两套 API 体系(对于立即模式和保留模式 GUI 的区别与联系,可参见个人这篇 IMGUI 科普回答)。概括说来,这个图形子系统的要点大致如下:

      • 图形库提供了 UIView 这个 C++ 控件基类,其中有一系列形如 OnClick / OnLongPress / OnDrag 的虚函数。基本每种 JS 中可用的原生 Component 类,都对应于一种 UIView 的子类。
      • 除了各种定制化 View 之外,它还开放了一系列形如 DrawLine / DrawCurve / DrawText 等命令式的绘制方法。
      • 这个图形库具备名为 GFX 的 GPU 加速模块,但它目前似乎只有象征性的 FillArea 矩形单色填充能力。
      <p>在基础 UI 控件方面,不难找到一些值得一提的自研模块特性:

      • 支持了简易的 RecycleView 长列表。
      • 支持了简易的 Flex 布局。
      • 支持了内部的 Invalidate 脏标记更新机制。
      <p>至于 2D UI 渲染中的几项关键能力,则基本可分为路径、位图和文字三类。这个图形库在这几个方面都有涉及,最后简单介绍一下。

      <p>首先对于位图,这个图形库依赖了 libpnglibjpeg 做图像解码,然后即可使用内存中的 bitmap 图像做绘制。

      <p>然后对于路径,这个图形库自己实现了各种 CPU 中的像素绘制方法,典型的例子就是这个贝塞尔曲线的绘制源码:

    void DrawCurve::DrawCubicBezier(const Point& start, const Point& control1, const Point& control2, const Point& end,    const Rect& mask, int16_t width, const ColorType& color, OpacityType opacity)
    {    if (width == 0 || opacity == OPA_TRANSPARENT) {        return;
        }
    
        Point prePoint = start;    for (int16_t t = 1; t <= INTERPOLATION_RANGE; t++) {
            Point point;
            point.x = Interpolation::GetBezierInterpolation(t, start.x, control1.x, control2.x, end.x);
            point.y = Interpolation::GetBezierInterpolation(t, start.y, control1.y, control2.y, end.y);        if (prePoint.x == point.x && prePoint.y == point.y) {            continue;
            }
    
            DrawLine::Draw(prePoint, point, mask, width, color, opacity);
            prePoint = point;
        }
    }复制代码
    <p>基于高中的数学知识,我们不难明白这种曲线是如何绘制出来的:取足够多的点(也就是那个默认 1000 的 INTERPOLATION_RANGE)作为插值输入,逐点计算出曲线表达式的 XY 坐标,然后直接修改像素位置所在的 framebuffer 内存即可。这种教科书式的实现是最经典的,不过如果要拿它对标 Skia 里的黑魔法,还是不要勉为其难了吧。

    <p>最后对于文字的绘制,会涉及一些字体解析、定位、RTL和折行等方面的处理。这部分实际上也是组合使用了一些业界通用的开源基础库来实现的。比如对于「牢」这个字,就可以找到图形库的这么几个开源依赖,它们各自扮演不同的角色:

    • harfbuzz - 用来告诉调用者,应该把「牢」的 glyph 字形放在哪里。
    • freetype - 从宋体、黑体等字体文件中解码出「牢」的 glyph 字形,将其光栅化为像素。
    • icu - 处理 Unicode 中许多奇葩的特殊情况,这块个人不了解,略过。
    <p>到这里,我们就可以理出一个非常概括性的渲染流程了:

    • JS에서 this.hello = 'PPT'와 같은 코드를 실행하여 종속성 추적을 트리거합니다.
    • JS 종속성 추적 콜백은 기본 함수를 트리거하여 C++ 구성 요소 구성 요소 상태를 업데이트합니다.
    • Component는 바인딩된 UIView 하위 클래스의 상태를 업데이트하여 그래픽 라이브러리 업데이트를 트리거합니다.
    • 그래픽 라이브러리는 메모리의 픽셀 상태를 업데이트하여 그림을 완성합니다.
    <p>이것은 "홍멍 2.0"의 GUI 기술 스택에 대한 개인적인 해석입니다. 시간이 부족하여 더 자세히 다루지는 않았으며, (문명적인) 비판과 수정은 환영합니다.

    요약

    <p>특별 설명: 이 주관적인 리뷰는 현재 "홍멍 2.0"의 GUI 프레임워크에만 해당됩니다. 임의로 오해하지 마십시오.

    <p>GUI 부분에서 "홍멍 2.0"의 하이라이트는 개인적으로 다음과 같이 생각할 수 있습니다.

    • 실용적인(그러나 당시 PPT 소개와는 완전히 다른) 코드가 있습니다.
    • WebView 셸이 아니며 레이아웃과 그리기가 직접 수행됩니다.
    • 원활하게 읽고 이해하기 위해서는 학부 수준 이상의 컴퓨터 지식이 필요하지 않습니다.
    <p>명백한(그저 보기 흉한 코드 라인이 아닌) 결함이나 문제에 관해서는 현재 다음과 같은 것이 있는 것 같습니다.

    • JS 프레임워크 레이어
      • 에는 기본 구성 요소 간 통신(예: props/emit 등) 기능
      • 기본 사용자 정의 구성 요소 기능 없음
      • 기본 종속성 추적 이외의 상태 관리 기능 없음
    • JS 엔진 및 런타임 레이어
      • 표준 지원이 너무 낮아 Vue 3.0 및 like Proxy가 필요한 차세대 프론트엔드 프레임워크
      • 는 성능이 약하고 중대형 JS 애플리케이션 지원이 어렵습니다
      • 개방형 DOM 스타일의 객체 모델 API가 없어 차이를 완화하는 데 도움이 되지 않습니다. 상위 레이어에
    • 그래픽 렌더링 레이어
      • 에는 실체가 없습니다. 사용 가능한 GPU 가속
      • SVG 및 서식 있는 텍스트와 같은 고급 렌더링 기능이 없습니다.
      • 캔버스는 완성도가 낮고 상태 스택이 부족하며 많은 API가 없습니다
    <p>단점이 많은 것 같은데, 제트엔진이 없다고 자동차를 탓하시겠습니까? 복잡성이 다른 시나리오의 경우 자연스럽게 최적의 아키텍처 설계가 다릅니다. 현재 이 디자인은 임베디드 하드웨어와 간단한 "소형 프로그램" 시나리오에 매우 적합한 것으로 보입니다. 그러나 소위 "분산 전체 시나리오 크로스 플랫폼" 요구 사항에 따라 살펴보면 이 아키텍처의 복잡성은 최신 웹 브라우저나 iOS 및 Android GUI와 완전히 비교할 수 없습니다. 휴대폰에 구현하려면 수많은 복잡한 모듈을 추가하고 상당한 아키텍처 진화와 재설계를 거쳐야 할 것이 거의 확실합니다.

    <p>물론 자동차 제조사들이 비행기를 만든다고는 하지 않겠죠?

    <p>간단히 말하면 이것은 집에서 만든 마파두부 한 접시이지만, 어떤 사람들이 말하는 것처럼 만주한잔은 아닙니다.

    <p>마지막으로 개인적 주관적 코멘트:

    <p>우선 이 GUI 기술 스택은 오픈소스 제품을 조립하고 빌려와서 얻을 수 있는 주류 수준에 이르렀습니다. 그러나 성능과 표현력 측면에서 핵심 모듈과 Microsoft MakeCode와 같은 업계 최고의 산학연 최첨단 솔루션 사이에는 여전히 세대 차이가 있습니다.

    <p>둘째, 다수의 전문가들의 정밀한 계산이 필요한 로켓사이언스라고 생각하지 마세요. 독립적인 연구개발을 폄하하는 것이 아니라, "나도 실제로 " 운영체제와 GUI는 그다지 신비롭지 않습니다. 학습, 사용, 기여가 가능한 국내의 성숙한 오픈소스 제품이 많이 있습니다. (그런데 경험하기 쉽고, 사용하기 매우 쉬운 RT-Thread를 추천합니다. 또한 얼리 어답터로서 중국에서 제조되었습니다). 결국, 제품이 기술적으로 어떤 것인지 진정으로 이해하는 경우에만, 숨은 동기를 가진 사람들이 제품을 조작할 가능성이 줄어들겠죠?

    <p>마지막으로 JavaScript에 익숙한 프론트엔드 개발자 여러분, 왜 아직도 홍멍을 이상하게 비웃나요? Hongmeng은 중국 JavaScript의 자산 코드입니다! JavaScript는 Hongmeng과 같은 "국가적 무기"에 채택되어 프런트 엔드의 도로 자신감, 이론적 자신감, 문화적 자신감 및 기술 스택 자신감을 크게 향상시킬 수 있습니다. 이런 식으로 접합과 자기 연구를 결합하면 단숨에 전국적으로 높은 위상을 얻을 수 있습니다. 이 길은 정말 매력적입니다. (소곤소곤)

    <p>우리는 자바스크립트를 뭉쳐서 활발하게 홍보하고 홍보해야 전공과 경쟁할 수 있습니다. 중국에서 핵 억제 수준에 도달하려면 JavaScript를 작성할 수 있다고 말하면 모두가 당신을 존경할 것입니다. 당신이 프론트 엔드 프로그래머라면 티켓을 구입할 때 줄을 서서 포기할 수 있습니다. 버스 탈 땐 자리에 앉고, 호텔 예약할 땐 무료로 섹스… …좋은 시절이 온다!

    <p>나라의 기둥이 되고 싶나요? 자바스크립트를 작성해보자!

    <p>더 이상 말이 필요 없습니다. 나라를 부흥시키기 위해 열심히 노력하겠습니다!

    <p>프로그래밍 학습에 대해 더 자세히 알고 싶다면 php training 칼럼을 주목해주세요!

    위 내용은 Hongmeng JavaScript GUI 기술 스택을 살펴 보겠습니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

    성명:
    이 기사는 juejin.im에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제