Для меня большая честь быть соавтором адаптации Таро к разработке Хунмэн.Вот некоторые из моих опытов во время разработки. Он также столкнулся со многими ямами, через которые нужно было перелезть.
Принцип адаптации Таро для Хунмэн
HarmonyOS — это новая распределенная операционная система эпохи Интернета всего.
Taro — это открытое кросс-энд и кросс-платформенное решение, которое поддерживает использование таких фреймворков, как React/Vue/Nerv, для разработки WeChat/JD/Baidu/Alipay/ByteDance/QQ Mini Programs/H5/RN и других приложений.
Существует три типа разработки HarmonyOS: Java, Js, Native. Развитие Hongmeng Js похоже на развитие Taro. Его можно преобразовать в код Хунмэн в соответствии с нашим кодом Таро. Основные принципы заключаются в следующем:
принцип
общий принцип
компилировать
общий принцип
Принцип @tarojs/mini-runner
При компиляции Hongmeng CLI вызовет@tarojs/mini-runner
Пакет, этот пакет в основном для компиляции кода.mini-runner
Делайте в основном следующие вещи:
- Отвечает за настройку конфигурации Webpack в соответствии с конфигурацией компиляции разработчика.
- Добавляйте пользовательские плагины PostCSS. (например, postcss-pxtransform)
- Вставьте пользовательский плагин Webpack.
- Внедрить пользовательские загрузчики Webpack. (Погрузчики находятся в
@tarojs/taro-loader
в сумке) - Вызовите Webpack, чтобы начать компиляцию.
- Измените продукт компиляции Webpack и скорректируйте окончательный результат компиляции.
Тогда согласно@tarojs/plugin-platform-harmony
Внесите коррективы для компонентов, API и маршрутов, они будут сглажены в этом плагине.
правильноmini-runner
анализировать
├── src
| ├── config 项目配置文件
| ├── dependencies 项目依赖文件
| ├── loader 自定义loader
| | ├── quickappStyleLoader 快应用
| | └── miniTemplateLoader 小程序模版解析器
| ├── plugins 自定义插件
| ├── prerender 自定义的代码结构
| ├── template 自定义模版
| | ├── comp 组件模版
| | ├── component 自定义组件模版
| | └── custom-wrapper 自定义小程序插件
| ├── utils 公共配置
| ├── webpack webpack配置
| | ├── base.conf 基础配置
| | ├── build.conf 打包配置
| | ├── chain 插件和解析器
| | └── postcss.conf 对css转换的配置
| └── index webpack的启动
└── index 入口文件
Примечание: Babel использует плагины
вавилонское использование | инструкция |
---|---|
@babel/core | Разберите код, чтобы получить AST |
@babel/types | Определения узлов AST, генерирующие узлы |
@babel/traverse | Рекурсивный обход AST |
@babel/generator | AST генерирует исходный код |
исходный код --> конечный код
<View className="flex items-center h-44 pb-40">
<SlPrice price={ price } />
{
tags.length !== 0 &&
tags.map(tag =>
<View className="px-20 py-6 mx-12 bg-red-light text-yellow text-22 rounded-20" key={ tag }>{tag}</View>
)
}
</View>
(_tarojs_components__WEBPACK_IMPORTED_MODULE_1__[/* View */ "d"], {
className: "flex items-center h-44 pb-40",
children: [/*#__PURE__*/Object(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__["jsx"])(_jd_selling_c_ui__WEBPACK_IMPORTED_MODULE_2__[/* SlPrice */ "e"], {
price: price
}), tags.length !== 0 && tags.map(function (tag) {
return /*#__PURE__*/Object(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__["jsx"])(_tarojs_components__WEBPACK_IMPORTED_MODULE_1__[/* View */ "d"], {
className: "px-20 py-6 mx-12 bg-red-light text-yellow text-22 rounded-20",
children: tag
}, tag);
})]
})
Обработка шаблона
бегать
Чтобы такие фреймворки, как React и Vue, могли работать непосредственно на Hongmeng, нам необходимо имитировать среду браузера на логическом уровне апплета, включая реализацию DOM, BOM API и т. д.
@tarojs/runtime
Это ядро адаптера времени выполнения Taro, которое реализует упрощенную DOM, BOM API, систему событий, связующий уровень веб-фреймворка и фреймворка апплета и т. д. Этот пакет в основном предназначен для адаптации апплета и операции h5, поскольку ReactDOM большой и содержит много кода совместимости. Таким образом, Taro реализует собственный рендерер вместо ReactDOM с помощью react-reconciler. Рендер находится в пакете @tarojs/react.
Веб-фреймворк может визуализировать дерево DOM Taro с помощью смоделированного API Taro, но все это выполняется на логическом уровне апплета. И шаблон xml апплета нужно заранее прописать до смерти, Таро решил использовать апплет<template>
могу привести другие<template>
, который отображает каждый узел DOM дерева DOM Таро как соответствующий<template>
. В настоящее время вам нужно только setData сериализованные данные дерева DOM Таро для запуска<template>
взаимные ссылки для отображения окончательного пользовательского интерфейса.
А у Хунмэна нет<template>
концепция, мы используем нестандартные компонентыelement
заменять.
Во время выполнения мы будем рассматривать DOM-дерево Taro, упомянутое выше, как целую переменную.root
для запуска кода. Тогда согласноroot.cn
Следующий массив для обхода и рекурсии нашего пользовательского компонента
содержание страницы
<element name="container" src="../../container/index.hml"></element>
<element name="navbar" src="../../container/components-harmony/navbar/index.hml"></element>
<element name="tabbar" src="../../container/components-harmony/tabbar/index.hml"></element>
<div class="container">
<navbar title="{{taroNavBar.title}}" background="{{taroNavBar.background}}" text-style="{{taroNavBar.textStyle}}" st="{{taroNavBar.style}}"></navbar>
<div class="body" style="padding-top: 44px;padding-bottom: {{isShowTaroTabBar ? '56px' : '0'}}">
<refresh if="{{enablePullDownRefresh}}" type="pulldown" refreshing="{{isRefreshing}}" onrefresh="onPullDownRefresh">
<container root="{{root}}"></container>
</refresh>
<container else root="{{root}}"></container>
</div>
<tabbar if="{{isShowTaroTabBar}}" data="{{taroTabBar}}" selected="{{selected}}"></tabbar>
</div>
корневые данные
{
"root": {
"cn": [
{
"cl": "layout bg-gray-lightbg",
"cn": [
{
"cn": [
{
"nn": "#text",
"v": "订单"
}
],
"nn": "view",
"uid": "_n_885"
},
{
"cl": "layout-area-slot w-full h-210 area-slot",
"cn": [],
"nn": "pure-view",
"uid": "_n_888"
}
],
"nn": "pure-view",
"uid": "_n_886"
}
],
"uid": "pages/tab-bar/order/index?$taroTimestamp=1636613920366"
},
}
содержимое контейнера
<element name="container" src="./index.hml"></element>
<element name="taro-textarea" src="./components-harmony/textarea/index.hml"></element>
<block for="{{i in root.cn}}">
<block if="{{i.nn == 'view'}}">
<div hover-class="{{i.hoverClass===undefined?'none':i.hoverClass}}" hover-stop-propagation="{{i.hoverStopPropagation===undefined?false:i.hoverStopPropagation}}" hover-start-time="{{i.hoverStartTime===undefined?50:i.hoverStartTime}}" hover-stay-time="{{i.hoverStayTime===undefined?400:i.hoverStayTime}}" @touchstart="{{eh}}" @touchmove="{{eh}}" @touchend="{{eh}}" @touchcancel="{{eh}}" @longtap="{{eh}}" animation="{{i.animation}}" @animationstart="{{eh}}" @animationiteration="{{eh}}" @animationend="{{eh}}" @transitionend="{{eh}}" style="{{i.st}}" class="{{i.cl}}" @click="{{eh}}" id="{{i.uid}}">
<container root="{{i}}"></container>
</div>
</block>
<block if="{{i.nn == 'textarea'}}">
<taro-textarea value="{{i.value}}" placeholder="{{i.placeholder}}" placeholder-style="{{i.placeholderStyle}}" placeholder-class="{{i.placeholderClass===undefined?'textarea-placeholder':i.placeholderClass}}" disabled="{{i.disabled}}" maxlength="{{i.maxlength===undefined?140:i.maxlength}}" auto-focus="{{i.autoFocus===undefined?false:i.autoFocus}}" focus="{{i.focus===undefined?false:i.focus}}" auto-height="{{i.autoHeight===undefined?false:i.autoHeight}}" fixed="{{i.fixed===undefined?false:i.fixed}}" cursor-spacing="{{i.cursorSpacing===undefined?0:i.cursorSpacing}}" cursor="{{i.cursor===undefined?-1:i.cursor}}" selection-start="{{i.selectionStart===undefined?-1:i.selectionStart}}" selection-end="{{i.selectionEnd===undefined?-1:i.selectionEnd}}" @focus="{{eh}}" @blur="{{eh}}" @linechange="{{eh}}" @input="{{eh}}" @confirm="{{eh}}" name="{{i.name}}" headericon="{{i.headericon}}" showcounter="{{i.showcounter===undefined?false:i.showcounter}}" menuoptions="{{i.menuoptions===undefined?[]:i.menuoptions}}" softkeyboardenabled="{{i.softkeyboardenabled===undefined?true:i.softkeyboardenabled}}" @translate="{{eh}}" @share="{{eh}}" @search="{{eh}}" @optionselect="{{eh}}" @selectchange="{{eh}}" style="{{i.st}}" class="{{i.cl}}" @click="{{eh}}" id="{{i.uid}}">
</taro-textarea>
</block>
...
</block>
компоненты
Taro реализует базовую библиотеку компонентов, соответствующую спецификации апплета WeChat на стороне Hongmeng.
будет использоваться по умолчанию@tarojs/components
Предоставляет библиотеку компонентов веб-компонентов.
В настоящее время необходимо соединить библиотеку компонентов Taro с библиотекой компонентов, поставляемой с Hongmeng, и последовательно выравнивать свойства и события в компонентах. Для компонентов, которых нет у Hongmeng, разработайте пользовательское выравнивание компонентов. Поскольку теги Hongmeng аналогичны тегам в Интернете, все теги в настоящее время необходимо переупаковывать. Существуют в основном два типа ситуаций:
- заключается в преобразовании базового компонента в наш целевой компонент
Базовый компонент предназначен для прямой адаптации базовых компонентов Taro к библиотеке базовых компонентов Hongmeng, как показано в следующем коде:
buildStandardComponentTemplate (comp) {
let nodeName = ''
switch (comp.nodeName) {
case 'slot':
case 'slot-view':
case 'cover-view':
case 'view':
case 'swiper-item':
nodeName = 'div'
break
case 'static-text':
nodeName = 'text'
break
case 'static-image':
nodeName = 'image'
break
default:
nodeName = comp.nodeName
break
}
return this.generateComponentTemplateSrc(comp, nodeName)
}
generateComponentTemplateSrc (comp, nodeName?): string {
const children = this.voidElements.has(comp.nodeName)
? ''
: `<block for="{{i.cn}}">
<container i="{{$item}}"></container>
</block>`
if (!nodeName) {
nodeName = comp.nodeName
}
if (this.nativeComps.includes(nodeName)) {
nodeName = `taro-${nodeName}`
}
const res = `
<block if="{{i.nn == '${comp.nodeName}'}}">
<${nodeName} ${this.buildAttrs(comp.attributes, comp.nodeName)} id="{{i.uid}}">
${children}
</${nodeName}>
</block>
`
return res
}
- Хунмэн и Таро имеют одинаковый состав, но разные атрибуты. В этом случае мы переписываем компонент как пользовательский компонент.В пользовательском компоненте атрибуты компонента будут выровнены с атрибутами Hongmeng.Если Hongmeng не имеет соответствующих атрибутов, его можно отбросить. Для компонентов Hongmeng есть свойства, которых нет в Taro, в файле конфигурации компонента
/components/index.ts
добавить соответствующие атрибуты.
// program.ts
platform = 'harmony'
globalObject = 'globalThis'
runtimePath = `${PACKAGE_NAME}/dist/runtime`
taroComponentsPath = `${PACKAGE_NAME}/dist/components/components-react`
fileType = {
templ: '.hml',
style: '.css',
config: '.json',
script: '.js'
}
// components-harmony文件夹下
├── components-harmony
├──image
├──input
└──...
API
разработчик из@tarojs/taro
Ссылайтесь на объект Taro и используйте предоставляемый им API.
В среде Хунмэн,@tarojs/taro
Будет получать независимые от платформы API из @tarojs/api, из@tarojs/plugin-platform-harmony
API-интерфейсы, реализованные в соответствии со спецификацией HarmonyOS, окончательно собираются в объект Taro и предоставляются разработчикам.
Для разработки системы Hongmeng функции API аналогичны API Taro, но имена и атрибуты отличаются. позвонивinitNativeApi
Метод Мы напрямую заменяем методы API внутри таро и используем собственные методы API для реализации методов Hongmeng API.
// /apis/index.ts
import { noop, current } from './utils'
import * as apis from './apis'
export function initNativeApi (taro) {
current.taro = taro
taro.initPxTransform = noop
Object.assign(taro, apis)
}
// apis文件夹下
├── apis
├── interactive
├── navbar
├── ...
└── index.ts
маршрутизация
в соответствии сapp.config
Страницы разделены на страницы, и в настоящее время сгенерированный код используется по умолчанию. Вам нужно вручную изменить проект Hongmengconfig.json
Исправлять
Описание плагина
публичный
дорожка | инструкция |
---|---|
@tarojs/cli | Инструменты CLI (инициализация/сборка) |
@tarojs/taro-loader | Webpack loaders |
@tarojs/helper | Библиотека инструментов, в основном для CLI, использование времени компиляции |
@tarojs/runner-utils | Библиотека инструментов, в основном используемая для небольших программ и инструментов компиляции H5. |
@tarojs/shared | Библиотека инструментов, в основном для использования во время выполнения |
@tarojs/taro | Раскройте предметы Таро, необходимые каждой стороне |
@tarojs/api | Бесконечный API Таро |
babel-preset-taro | Babel preset |
eslint-config-taro | Правила ESLint |
postcss-pxtransform | Плагин PostCSS для преобразования px в адаптивный размер с каждой стороны |
Хунмэн
дорожка | инструкция |
---|---|
@tarojs/plugin-platform-harmony | Составление и адаптация Hongmeng |
@tarojs/mini-runner | компиляция апплета |
развивать
Адаптация Таро к Хунмэн находится в стадии разработки и может быть выполненаfeat/harmony
Разветвите код и скомпилируйте его для использования.
1. Загрузите исходный код Taro и скомпилируйте его.
Нужно связать адаптацию Hongmeng
# 下载源码
$ git clone git@github.com:NervJS/taro.git
$ git checkout feat/harmony
# 安装依赖
$ yarn
# 编译
$ yarn build
# yarn link (harmony 基于 Taro v3.4,但 v3.4 暂时还未发布,所以需要把 3.4 改动的包都进行软链)
$ cd packages/taro-cli
$ yarn link
$ cd ../taro-runtime
$ yarn link
$ cd ../taro-harmony
$ yarn link
$ cd ../taro-plugin-react
$ yarn link
$ cd ../taro-plugin-vue2
$ yarn link
$ cd ../taro-plugin-vue3
$ yarn link
$ cd ../taro-mini-runner
$ yarn link
$ cd ../taro
$ yarn link
$ cd ../taro-api
$ yarn link
$ cd ../shared
$ yarn link
$ cd ../taro-loader
$ yarn link
2. Установите @tarojs/cli, создайте проект Taro и создайте мягкую цепочку.
Установите @tarojs/cli (если он был установлен локально, вы можете пропустить этот шаг)
# 使用 npm 安装 CLI
$ npm install -g @tarojs/cli
# OR 使用 yarn 安装 CLI
$ yarn global add @tarojs/cli
# OR 安装了 cnpm,使用 cnpm 安装 CLI
$ cnpm install -g @tarojs/cli
Создайте проект Таро и постройте мягкую цепочку
taro init myApp
cd myApp
yarn link @tarojs/runtime
yarn link @tarojs/plugin-platform-harmony
yarn link @tarojs/plugin-framework-react
yarn link @tarojs/plugin-framework-vue2
yarn link @tarojs/plugin-framework-vue3
yarn link @tarojs/mini-runner
yarn link @tarojs/taro
yarn link @tarojs/api
yarn link @tarojs/shared
yarn link @tarojs/taro-loader
# OR
yarn link @tarojs/runtime @tarojs/plugin-platform-harmony @tarojs/plugin-framework-react @tarojs/plugin-framework-vue2 @tarojs/plugin-framework-vue3 @tarojs/mini-runner @tarojs/taro @tarojs/api @tarojs/shared @tarojs/taro-loader
3. Скомпилируйте конфигурацию
// config/index.js
config = {
// 配置输出路径,输出到鸿蒙 JS FA 的对应目录下。(支持绝对路径、相对路径)
// 例如鸿蒙应用名称为 MyApplication,JS FA 名称为默认的 default,那么 outputRoot 需要设置为:
// 'MyApplication/entry/src/main/js/default'
outputRoot: '...',
// 配置使用插件
plugins: ['@tarojs/plugin-platform-harmony'],
mini: {
// 如果使用开发者工具的预览器(previewer)进行预览的话,需要使用 development 版本的 react-reconciler。
// 因为 previewer 对长串的压缩文本解析有问题。(真机/远程真机没有此问题)
debugReact: true,
// 如果需要真机断点调试,需要关闭 sourcemap 的生成
enableSourceMap: false
}
}
4. Конфигурация проекта Хунмэн
Подробная документация файла конфигурации Hongmeng:Элементы файла конфигурации
4.1 Настройка маршрутизации
Предполагая, что существует проект Hongmeng MyApplication, если вам нужно настроить маршрутизацию, вы можете изменитьMyApplication/entry/src/main/config.json
изmodules.js
конфигурация.
4.2 Закройте верхнюю панель навигации, которая поставляется вместе с системой
ИсправлятьMyApplication/entry/src/main/config.json
изmodules
Конфигурация, добавьте следующее:
"metaData": {
"customizeData":[
{
"name": "hwc-theme",
"value": "androidhwext:style/Theme.Emui.NoTitleBar"
}
]
}
5. Скомпилируйте
taro build --type harmony --watch
6. Беги
6.1 Создайте проект Hongmeng JS, например MyApplication
Инструменты разработчика Huawei:developer.harmony OS.com/talent/develop/…Документация по разработке Hongmeng:developer.harmony OS.com/talent/document…
6.2 Используйте средство предварительного просмотра, реальную машину и удаленную реальную машину инструментов разработчика Hongmeng для предварительного просмотра
документация по предварительному просмотру:developer.harmony OS.com/talent/docs/doc…
sudo launchctl unload /Library/LaunchDaemons/com.terminal.plist
关掉公司电脑自动删除 adb 服务的启动项
安装 adb 工具:
brew install android-platform-tools
demo
Проект Хунмэн Таро:содержание
Я хотел бы поблагодарить авторов Таро за их помощь и внимательное обучение. Разрабатываемая версия Таро, адаптированная к Хунмэн, будет выпущена в конце этого месяца, надеюсь, вы меня поправите.