0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線(xiàn)課程
  • 觀(guān)看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
电子发烧友
开通电子发烧友VIP会员 尊享10大特权
海量资料免费下载
精品直播免费看
优质内容免费畅学
课程9折专享价
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Taro鴻蒙技術(shù)內(nèi)幕系列(一):如何將React代碼跑在A(yíng)rkUI上

京東云 ? 來(lái)源:jf_75140285 ? 2024-10-25 17:24 ? 次閱讀

作者:京東零售 朱鳴輝

基于 Taro 打造的京東鴻蒙 APP 已跟隨鴻蒙 Next 系統(tǒng)公測(cè),本系列文章將深入解析 Taro 如何實(shí)現(xiàn)使用 React 開(kāi)發(fā)高性能鴻蒙應(yīng)用的技術(shù)內(nèi)幕

背景

隨著鴻蒙操作系統(tǒng)的快速發(fā)展,開(kāi)發(fā)者們期待將現(xiàn)有跨平臺(tái)應(yīng)用遷移到鴻蒙平臺(tái)。Taro作為一個(gè)流行的跨平臺(tái)開(kāi)發(fā)框架,其支持鴻蒙系統(tǒng)的可能性引起了廣泛關(guān)注。

然而,鴻蒙系統(tǒng)采用全新的ArkUI框架作為原生UI開(kāi)發(fā)方案,與Taro原本支持的平臺(tái)存在顯著差異。將Taro的React開(kāi)發(fā)模式與ArkUI的聲明式UI開(kāi)發(fā)范式進(jìn)行有效對(duì)接成為了一個(gè)技術(shù)難題。

本文將探討Taro框架如何通過(guò)創(chuàng)新方案實(shí)現(xiàn)React代碼在A(yíng)rkUI上的運(yùn)行。我們將解析Taro的運(yùn)行時(shí)原理,剖析其如何將React組件轉(zhuǎn)換為ArkUI可識(shí)別的結(jié)構(gòu),以及相關(guān)技術(shù)挑戰(zhàn)和解決方案。

Taro運(yùn)行時(shí)原理介紹

為了理解Taro適配ArkUI的核心機(jī)制,我們首先需要深入了解Taro的運(yùn)行時(shí)原理。Taro通過(guò)巧妙的設(shè)計(jì),將React代碼轉(zhuǎn)換為各平臺(tái)可執(zhí)行的形式,其中包括對(duì)鴻蒙平臺(tái)的適配。下面將詳細(xì)介紹 Taro 是如何將 React 代碼轉(zhuǎn)換為ArkUI可執(zhí)行的形式,以及節(jié)點(diǎn)轉(zhuǎn)換的流程細(xì)節(jié)。

wKgaoWcXQA-AX6UzABGMbiseADc620.png

1. 從 React 到 Taro

React 跨平臺(tái)的秘訣

在 Taro 的運(yùn)行時(shí)中,首先執(zhí)行的是開(kāi)發(fā)者編寫(xiě)的 React 業(yè)務(wù)代碼。這些代碼定義了業(yè)務(wù)應(yīng)用的結(jié)構(gòu)、邏輯和狀態(tài)管理。那么既然要對(duì)接React,那肯定先得了解它的核心架構(gòu),React是怎么運(yùn)作的:

wKgZoWcXQBOAUyutABPiFdo-BPA686.png

?

了解了React的基本架構(gòu)后,我們可以清晰地看到,Renderer 作為渲染器,負(fù)責(zé)將React的虛擬節(jié)點(diǎn)操作最終映射到相應(yīng)的平臺(tái)上。例如,react-dom將這些操作對(duì)接到瀏覽器上,而react-native則將其對(duì)接到iOSAndroid平臺(tái)。這種設(shè)計(jì)使得React能夠適配不同的運(yùn)行環(huán)境。

wKgZoWcXQBaAXIhDABLU5H_VvK4697.png

正是基于這種思路,Taro 團(tuán)隊(duì)設(shè)計(jì)了 Taro Renderer。這個(gè)渲染器充當(dāng)了 React 與 Taro 虛擬節(jié)點(diǎn)樹(shù)之間的橋梁,使得 React 的操作可以被轉(zhuǎn)換為 Taro 的中間表示。

通過(guò)實(shí)現(xiàn) Taro Renderer 生成 Taro 虛擬節(jié)點(diǎn)樹(shù)

wKgaoWcXQBeASkU4AAU2ooqu32s867.png

HostConfig接口實(shí)現(xiàn)

?

要實(shí)現(xiàn) Taro 的 Renderer,我們需要實(shí)現(xiàn) React Reconciler 所需的 hostConfig 接口。這個(gè)接口定義了一系列方法,用于創(chuàng)建、更新和管理渲染目標(biāo)平臺(tái)的元素。以下是一些關(guān)鍵的 hostConfig 方法:

?createElement:創(chuàng)建ArkUI對(duì)應(yīng)的元素。

?createTextInstance:創(chuàng)建文本節(jié)點(diǎn)。

?appendChild:將子元素添加到父元素。

?removeChild:從父元素中移除子元素。

?insertBefore:在指定位置插入元素。

?commitUpdate:更新元素屬性。

通過(guò)實(shí)現(xiàn)這些方法,Taro Renderer 能夠?qū)?strong> React 的操作轉(zhuǎn)換為 Taro 虛擬節(jié)點(diǎn)樹(shù)的相應(yīng)操作。這個(gè)虛擬節(jié)點(diǎn)樹(shù)是 Taro 實(shí)現(xiàn)跨平臺(tái)的核心,它為不同平臺(tái)的渲染提供了統(tǒng)一的中間表示。

// 部分HostConfig接口實(shí)現(xiàn)的代碼

const hostConfig: HostConfig {
    // 創(chuàng)建Taro虛擬節(jié)點(diǎn)
  createInstance (type, props: Props, _rootContainerInstance, _hostContext, internalInstanceHandle: Fiber) {
    const element: TaroElement = TaroNativeModule.createTaroNode(type)
    precacheFiberNode(internalInstanceHandle, element)
    updateFiberProps(element, props)
    return element
  },
  // 更新屬性
    commitUpdate (dom, updatePayload, _, oldProps, newProps) {
      updatePropsByPayload(dom, oldProps, updatePayload)
      updateFiberProps(dom, newProps)
    },
    // 插入節(jié)點(diǎn)
    insertBefore (parent: TaroElement, child: TaroElement, refChild: TaroElement) {
      parent.insertBefore(child, refChild)
    },
    // 移除節(jié)點(diǎn)
    removeChild (parent: TaroElement, child TaroElement) {
      parent.removeChild(child)
    },
    // ...
}

2. 從 Taro 到 ArkUI

在將 Taro 虛擬節(jié)點(diǎn)樹(shù)轉(zhuǎn)換為 ArkUI 的過(guò)程中,我們需要進(jìn)行幾個(gè)關(guān)鍵步驟:

?

wKgZoWcXQBuAXDLKAAiIYMZZYbo181.png

Taro Element轉(zhuǎn)換 ArkUI過(guò)程

首先,我們需要在 ArkUI 層面實(shí)現(xiàn)一套與 Taro 組件對(duì)應(yīng)的組件庫(kù)。這個(gè)步驟至關(guān)重要,因?yàn)樗⒘?Taro 組件和 ArkUI 組件之間的映射關(guān)系。例如,我們需要為 Taro 的 View、Text、Image 等基礎(chǔ)組件創(chuàng)建對(duì)應(yīng)的 ArkUI 組件。這樣,當(dāng)我們遍歷 Taro 虛擬節(jié)點(diǎn)樹(shù)時(shí),就能找到每個(gè)節(jié)點(diǎn)在 ArkUI 中的對(duì)應(yīng)實(shí)現(xiàn)。

?

在節(jié)點(diǎn)映射的過(guò)程中,我們注意到 Taro 虛擬節(jié)點(diǎn)樹(shù)與實(shí)際 ArkUI 視圖結(jié)構(gòu)存在差異。這些差異主要體現(xiàn)在以下幾個(gè)方面:

?復(fù)合組件結(jié)構(gòu):某些 Taro 組件在 ArkUI 中可能需要多個(gè)組件配合實(shí)現(xiàn)。例如,ScrollView 組件在 ArkUI 中可能需要一個(gè) Scroll 節(jié)點(diǎn)搭配一個(gè) Stack 來(lái)實(shí)現(xiàn)完整功能。

?層級(jí)位置調(diào)整:一些特殊定位的節(jié)點(diǎn)(如 Fixed 定位的元素)在最終渲染時(shí)的位置可能與其在虛擬節(jié)點(diǎn)樹(shù)中的層級(jí)不一致。這需要在生成渲染樹(shù)時(shí)進(jìn)行特殊處理。

?平臺(tái)特定組件:某些 Taro 組件可能需要使用 ArkUI 特有的組件或布局方式來(lái)實(shí)現(xiàn),這要求我們?cè)谵D(zhuǎn)換過(guò)程中進(jìn)行適當(dāng)?shù)恼{(diào)整和映射。

wKgaoWcXQB2AKlzcAAkvMJEcN_w449.png

因此,在生成渲染樹(shù)時(shí),我們需要一個(gè)更復(fù)雜的轉(zhuǎn)換過(guò)程,不僅要考慮簡(jiǎn)單的一對(duì)一映射,還要處理這些結(jié)構(gòu)性的差異,確保最終生成的 ArkUI 組件樹(shù)能夠正確反映預(yù)期的視圖結(jié)構(gòu)和布局。因此,在Taro > ArkUI的節(jié)點(diǎn)對(duì)接中,我們需要維護(hù)一棵 Render Tree,用于做中間的橋梁。

?

1. 根據(jù)組件類(lèi)型 創(chuàng)建 Taro Element

在創(chuàng)建 Taro Element 的過(guò)程中,我們根據(jù)組件的類(lèi)型來(lái)實(shí)例化相應(yīng)的 Taro 元素。這一步驟是將 React 組件轉(zhuǎn)換為 Taro 內(nèi)部表示的關(guān)鍵。

// 根據(jù)組件類(lèi)型創(chuàng)建對(duì)應(yīng)的Taro節(jié)點(diǎn)
std::shared_ptr TaroDocument::CreateElement(napi_value &node) {
        // 獲取組件類(lèi)型
    TAG_NAME tag_name_ = TaroDOM::TaroElement::GetTagName(node);
    // 根據(jù)組件類(lèi)型,創(chuàng)建對(duì)應(yīng)的實(shí)例
    std::shared_ptr item;
    switch (tag_name_) {
        case TAG_NAME::SCROLL_VIEW: {
            item = std::make_shared(node);
            break;
        }
        case TAG_NAME::IMAGE:
            item = std::make_shared(node);
            break;
        }
        case TAG_NAME::SPAN:
        case TAG_NAME::TEXT: {
            item = std::make_shared(node);
            break;
        }
        case TAG_NAME::SWIPER: {
            item = std::make_shared(node);
            break;
        }
        // ...
    }
    return item;
}

2. Taro Element 創(chuàng)建 Taro RenderNode

在創(chuàng)建完 Taro Element 之后,下一步是將其轉(zhuǎn)換為 Taro RenderNode。這個(gè)過(guò)程是將 Taro 的內(nèi)部表示進(jìn)一步轉(zhuǎn)化為更接近 ArkUI 結(jié)構(gòu)的渲染節(jié)點(diǎn)。

// 創(chuàng)建 Taro RenderNode
void TaroSwiper::Build() {
    if (!is_init_) {
        // create render node
        TaroElementRef element = std::static_pointer_cast(shared_from_this());
        auto render_swiper = std::make_shared(element);
        render_swiper->Build();
    }
}

3. Taro RenderNode 創(chuàng)建 ArkUI Node

最后一步是將 Taro RenderNode 轉(zhuǎn)換為實(shí)際的 ArkUI 節(jié)點(diǎn)。這個(gè)過(guò)程涉及到直接與 ArkUI 的底層 API 交互,創(chuàng)建和配置 ArkUI 的原生節(jié)點(diǎn)。實(shí)現(xiàn)了從 Taro 的渲染節(jié)點(diǎn)到 ArkUI 實(shí)際可渲染節(jié)點(diǎn)的最終轉(zhuǎn)換。

 // 創(chuàng)建 ArkUI Node
void TaroSwiperNode::Build() {
    NativeNodeApi *nativeNodeApi = NativeNodeApi::getInstance();
    // 創(chuàng)建一個(gè)Swiper的ArkUI節(jié)點(diǎn)
    SetArkUINodeHandle(nativeNodeApi->createNode(ARKUI_NODE_SWIPER));
}

通過(guò)這三個(gè)步驟,我們?cè)?C++ 層面成功實(shí)現(xiàn)了 React 組件結(jié)構(gòu)到 ArkUI 原生組件結(jié)構(gòu)的映射。這一過(guò)程使 Taro 應(yīng)用能夠在鴻蒙系統(tǒng)上準(zhǔn)確地渲染和運(yùn)行,為跨平臺(tái)開(kāi)發(fā)提供了有力支持。

總結(jié)

最后總結(jié)下,本文探討了Taro框架如何將React代碼成功運(yùn)行在鴻蒙系統(tǒng)的ArkUI上。這個(gè)過(guò)程主要分為兩個(gè)關(guān)鍵部分:

wKgaoWcXQB-AfkaKAAmbVAbNNpQ388.png

React > ArkUI 架構(gòu)圖

1. Taro對(duì)接React

Taro通過(guò)實(shí)現(xiàn)自定義的Renderer來(lái)對(duì)接React。這個(gè)Renderer包含了一系列方法,如createInstance、commitUpdate等,用于將React的操作轉(zhuǎn)換為T(mén)aro虛擬節(jié)點(diǎn)樹(shù)的操作。這個(gè)虛擬節(jié)點(diǎn)樹(shù)是Taro實(shí)現(xiàn)跨平臺(tái)的核心,為不同平臺(tái)的渲染提供了統(tǒng)一的中間表示。

2. Taro對(duì)接ArkUI

Taro通過(guò)自定義Renderer將React操作轉(zhuǎn)換為虛擬節(jié)點(diǎn)樹(shù),然后通過(guò)三步轉(zhuǎn)換過(guò)程將其映射到ArkUI結(jié)構(gòu)。這個(gè)過(guò)程涉及Taro Element、Taro RenderNode和ArkUI Node這三棵樹(shù)的維護(hù),主要通過(guò)這三個(gè)流程步驟實(shí)現(xiàn):

1.創(chuàng)建Taro Element:這一步將React組件轉(zhuǎn)換為T(mén)aro內(nèi)部表示。

2.創(chuàng)建Taro RenderNode:將Taro的內(nèi)部表示進(jìn)一步轉(zhuǎn)化為更接近ArkUI層級(jí)結(jié)構(gòu)的渲染節(jié)點(diǎn)。

3.創(chuàng)建ArkUI Node:最后一步是將Taro RenderNode轉(zhuǎn)換為實(shí)際的ArkUI節(jié)點(diǎn),直接與ArkUI的底層API交互。

通過(guò)這種方式,Taro成功地將React組件結(jié)構(gòu)映射到ArkUI原生組件結(jié)構(gòu),使得Taro應(yīng)用能夠在鴻蒙系統(tǒng)上準(zhǔn)確地渲染和運(yùn)行,同時(shí)也為跨平臺(tái)開(kāi)發(fā)提供了有力支持。

?
系列往期精選:

?《京東鴻蒙上線(xiàn)前瞻——使用 Taro 打造高性能原生應(yīng)用》?

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀(guān)點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 操作系統(tǒng)
    +關(guān)注

    關(guān)注

    37

    文章

    6978

    瀏覽量

    124449
  • APP
    APP
    +關(guān)注

    關(guān)注

    33

    文章

    1583

    瀏覽量

    73453
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4866

    瀏覽量

    69815
收藏 0人收藏

    評(píng)論

    相關(guān)推薦

    鴻蒙開(kāi)發(fā)學(xué)習(xí):初探【ArkUI-X】

    **簡(jiǎn)單來(lái)說(shuō),ArkTS + ArkUI-X 對(duì)標(biāo)的框架為 flutter,代碼,編譯為 native 全平臺(tái)運(yùn)行**
    的頭像 發(fā)表于 05-13 15:58 ?1347次閱讀
    <b class='flag-5'>鴻蒙</b>開(kāi)發(fā)學(xué)習(xí):初探【<b class='flag-5'>ArkUI</b>-X】

    鴻蒙開(kāi)發(fā)ArkUI-X基礎(chǔ)知識(shí):【ArkUI代碼工程及構(gòu)建介紹】

    ArkUI作為OpenHarmony的默認(rèn)開(kāi)發(fā)框架,本項(xiàng)目(ArkUI-X)中需要做到代碼同時(shí)支持多平臺(tái)構(gòu)建,所以會(huì)采取共倉(cāng)開(kāi)發(fā)的方式
    的頭像 發(fā)表于 05-25 16:45 ?2431次閱讀
    <b class='flag-5'>鴻蒙</b>開(kāi)發(fā)<b class='flag-5'>ArkUI</b>-X基礎(chǔ)知識(shí):【<b class='flag-5'>ArkUI</b><b class='flag-5'>代碼</b>工程及構(gòu)建介紹】

    鴻蒙Flutter實(shí)戰(zhàn):07混合開(kāi)發(fā)

    # 鴻蒙Flutter實(shí)戰(zhàn):混合開(kāi)發(fā) 鴻蒙Flutter混合開(kāi)發(fā)主要有兩種形式。 ## 1.基于har flutter module打包成har包,原生
    發(fā)表于 10-23 16:00

    鴻蒙Taro實(shí)戰(zhàn):01-搭建開(kāi)發(fā)環(huán)境

    ,點(diǎn)擊右下角 Apply, OK, 完成簽名 運(yùn)行 DevEcho 中,點(diǎn)擊運(yùn)行按鈕,待控制臺(tái)執(zhí)行完成,查看設(shè)備,頁(yè)面中將輸出以下內(nèi)容 首頁(yè) Hello world! 注意事項(xiàng) 運(yùn)動(dòng) Taro
    發(fā)表于 11-06 16:42

    Taro下拉加載更多,拉刷新是什么

    Taro下拉加載更多,拉刷新
    發(fā)表于 06-15 17:10

    如何將RF與數(shù)模電路設(shè)計(jì)PCB

    如何將RF與數(shù)模電路設(shè)計(jì)PCB
    發(fā)表于 01-12 21:59 ?17次下載

    如何將手機(jī)系統(tǒng)升級(jí)為鴻蒙系統(tǒng)

    如何將手機(jī)系統(tǒng)升級(jí)為鴻蒙系統(tǒng)?具體操作還是很簡(jiǎn)單的,下面就跟小編起來(lái)學(xué)學(xué)看吧!
    的頭像 發(fā)表于 07-07 10:03 ?6097次閱讀

    如何在鴻蒙系統(tǒng)個(gè)ArkUI應(yīng)用

    ? ? ? 大家可以看到很明顯這是個(gè) ArkUI 的應(yīng)用,遠(yuǎn)程模擬器目前還只可以 P4
    的頭像 發(fā)表于 11-15 09:28 ?3216次閱讀
    如何在<b class='flag-5'>鴻蒙</b>系統(tǒng)<b class='flag-5'>上</b>弄<b class='flag-5'>一</b>個(gè)<b class='flag-5'>ArkUI</b>應(yīng)用

    鴻蒙ArkUI開(kāi)發(fā)-Tabs組件的使用

    鴻蒙ArkUI開(kāi)發(fā)-Tabs組件的使用
    的頭像 發(fā)表于 01-19 16:01 ?2265次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>ArkUI</b>開(kāi)發(fā)-Tabs組件的使用

    使用 Taro 開(kāi)發(fā)鴻蒙原生應(yīng)用 —— 快速上手,鴻蒙應(yīng)用開(kāi)發(fā)指南

    鴻蒙原生應(yīng)用。 《使用 Taro 開(kāi)發(fā)鴻蒙原生應(yīng)用》 系列文章中,我們已經(jīng)介紹了 鴻蒙的基
    的頭像 發(fā)表于 02-02 16:09 ?1142次閱讀
    使用 <b class='flag-5'>Taro</b> 開(kāi)發(fā)<b class='flag-5'>鴻蒙</b>原生應(yīng)用 —— 快速上手,<b class='flag-5'>鴻蒙</b>應(yīng)用開(kāi)發(fā)指南

    鴻蒙ArkUI:【從代碼到UI顯示的整體渲染流程】

    方舟開(kāi)發(fā)框架(簡(jiǎn)稱(chēng)ArkUI)是鴻蒙開(kāi)發(fā)的UI框架,提供如下兩種開(kāi)發(fā)范式,我們 **只學(xué)聲明式開(kāi)發(fā)范式**
    的頭像 發(fā)表于 05-13 16:06 ?1232次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>ArkUI</b>:【從<b class='flag-5'>代碼</b>到UI顯示的整體渲染流程】

    鴻蒙跨平臺(tái)框架:【ArkUi-X】創(chuàng)建工程

    鴻蒙推出了鴻ArkUi-X 框架所以就寫(xiě)個(gè)文章分享
    的頭像 發(fā)表于 05-13 17:48 ?1225次閱讀
    <b class='flag-5'>鴻蒙</b>跨平臺(tái)框架:【<b class='flag-5'>ArkUi</b>-X】創(chuàng)建工程

    鴻蒙ArkUI-X跨平臺(tái)開(kāi)發(fā):【 編寫(xiě)第個(gè)ArkUI-X應(yīng)用】

    通過(guò)構(gòu)建個(gè)簡(jiǎn)單的ArkUI頁(yè)面跳轉(zhuǎn)示例,快速了解資源創(chuàng)建引用,路由代碼編寫(xiě)和UI布局編寫(xiě)等應(yīng)用開(kāi)發(fā)流程。
    的頭像 發(fā)表于 05-21 17:36 ?956次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>ArkUI</b>-X跨平臺(tái)開(kāi)發(fā):【 編寫(xiě)第<b class='flag-5'>一</b>個(gè)<b class='flag-5'>ArkUI</b>-X應(yīng)用】

    Taro 鴻蒙技術(shù)內(nèi)幕系列(二):如何讓 W3C 標(biāo)準(zhǔn)的 CSS鴻蒙

    作者:京東零售 馬銀濤 ? 基于 Taro 打造的京東鴻蒙 APP 已跟隨鴻蒙 Next 系統(tǒng)公測(cè),本系列文章深入解析
    的頭像 發(fā)表于 10-31 10:54 ?336次閱讀
    <b class='flag-5'>Taro</b> <b class='flag-5'>鴻蒙</b><b class='flag-5'>技術(shù)</b><b class='flag-5'>內(nèi)幕</b><b class='flag-5'>系列</b>(二):如何讓 W3C 標(biāo)準(zhǔn)的 CSS<b class='flag-5'>跑</b><b class='flag-5'>在</b><b class='flag-5'>鴻蒙</b>上

    Taro 鴻蒙技術(shù)內(nèi)幕系列(三) - 多語(yǔ)言場(chǎng)景下的通用事件系統(tǒng)設(shè)計(jì)

    作者:京東零售 朱天健 基于 Taro 打造的京東鴻蒙 APP 已跟隨鴻蒙 Next 系統(tǒng)公測(cè),本系列文章深入解析
    的頭像 發(fā)表于 11-27 11:42 ?416次閱讀
    <b class='flag-5'>Taro</b> <b class='flag-5'>鴻蒙</b><b class='flag-5'>技術(shù)</b><b class='flag-5'>內(nèi)幕</b><b class='flag-5'>系列</b>(三) - 多語(yǔ)言場(chǎng)景下的通用事件系統(tǒng)設(shè)計(jì)

    電子發(fā)燒友

    中國(guó)電子工程師最喜歡的網(wǎng)站

    • 2931785位工程師會(huì)員交流學(xué)習(xí)
    • 獲取您個(gè)性化的科技前沿技術(shù)信息
    • 參加活動(dòng)獲取豐厚的禮品