Skip to content

Commit bd4ffb7

Browse files
xzdadadaxuzhengda
andauthored
feat: taro 支持 ttdom (#18850)
* feat: taro 支持 ttdom * fix: 更新 test snap --------- Co-authored-by: xuzhengda <xuzhengda@bytedance.com>
1 parent 63ab20a commit bd4ffb7

14 files changed

Lines changed: 431 additions & 42 deletions

File tree

packages/shared/src/constants.ts

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,117 @@ export const PLATFORM_CONFIG_MAP = {
3131
type: PLATFORM_TYPE.QUICK
3232
},
3333
}
34+
35+
export const TT_SPECIFIC_COMPONENTS = new Set([
36+
'page-container',
37+
'slot',
38+
'custom-wrapper',
39+
'clue-order-form',
40+
'aweme-group',
41+
'pay-button',
42+
'address-area',
43+
'consume-card',
44+
'aweme-data',
45+
'rate-button',
46+
'store-area',
47+
'inline-payment-panel',
48+
'aweme-user-card',
49+
'aweme-live-book',
50+
'draw-ad',
51+
'lynx-view',
52+
'flow-ad',
53+
'ai-agent-chat',
54+
'component'
55+
])
56+
57+
export const DEFAULT_COMPONENTS = new Set<string>([
58+
'view',
59+
'scroll-view',
60+
'swiper',
61+
'cover-view',
62+
'cover-image',
63+
'icon',
64+
'text',
65+
'rich-text',
66+
'progress',
67+
'button',
68+
'checkbox',
69+
'form',
70+
'input',
71+
'label',
72+
'picker',
73+
'picker-view',
74+
'picker-view-column',
75+
'radio',
76+
'radio-group',
77+
'checkbox-group',
78+
'slider',
79+
'switch',
80+
'textarea',
81+
'navigator',
82+
'audio',
83+
'image',
84+
'video',
85+
'camera',
86+
'live-player',
87+
'live-pusher',
88+
'map',
89+
'canvas',
90+
'open-data',
91+
'web-view',
92+
'swiper-item',
93+
'movable-area',
94+
'movable-view',
95+
'functional-page-navigator',
96+
'ad',
97+
'block',
98+
'import',
99+
'official-account',
100+
'editor'
101+
])
102+
103+
export const UNITLESS_PROPERTIES_SET = new Set([
104+
'animation-iteration-count',
105+
'border-image-outset',
106+
'border-image-slice',
107+
'border-image-width',
108+
'box-flex',
109+
'box-flex-group',
110+
'box-ordinal-group',
111+
'column-count',
112+
'columns',
113+
'flex',
114+
'flex-grow',
115+
'flex-positive',
116+
'flex-shrink',
117+
'flex-negative',
118+
'flex-order',
119+
'grid-area',
120+
'grid-row',
121+
'grid-row-end',
122+
'grid-row-span',
123+
'grid-row-start',
124+
'grid-column',
125+
'grid-column-end',
126+
'grid-column-span',
127+
'grid-column-start',
128+
'font-weight',
129+
'line-clamp',
130+
'line-height',
131+
'opacity',
132+
'order',
133+
'orphans',
134+
'tab-size',
135+
'widows',
136+
'z-index',
137+
'zoom',
138+
// SVG-related properties
139+
'fill-opacity',
140+
'flood-opacity',
141+
'stop-opacity',
142+
'stroke-dasharray',
143+
'stroke-dashoffset',
144+
'stroke-miterlimit',
145+
'stroke-opacity',
146+
'stroke-width',
147+
])

packages/shared/src/utils.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,3 +249,25 @@ export function indent (str: string, size: number): string {
249249
})
250250
.join('\n')
251251
}
252+
253+
export enum TTRenderType {
254+
V1 = 1,
255+
V2 = 2,
256+
}
257+
258+
declare const tt: any
259+
let ttUseV2TTDom: boolean | undefined
260+
261+
export function isEnableTTDom() {
262+
// 目前仅对于 react 支持 ttdom
263+
if (process.env.TARO_ENV !== 'tt' || process.env.FRAMEWORK !== 'react' || typeof tt === 'undefined') {
264+
return false
265+
}
266+
if (ttUseV2TTDom !== undefined) return ttUseV2TTDom
267+
268+
const ttMode = tt.getRenderMode ? tt.getRenderMode() : TTRenderType.V1
269+
270+
ttMode === TTRenderType.V2 && tt.__$enableTTDom$__ ? (ttUseV2TTDom = true) : (ttUseV2TTDom = false)
271+
272+
return ttUseV2TTDom
273+
}

packages/taro-react/src/props.ts

Lines changed: 67 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { convertNumber2PX, FormElement } from '@tarojs/runtime'
2-
import { capitalize, internalComponents, isFunction, isNumber, isObject, isString, PLATFORM_TYPE, toCamelCase } from '@tarojs/shared'
1+
import { convertNumber2PX, eventHandlerTTDom, FormElement, setInnerHTML } from '@tarojs/runtime'
2+
import { capitalize, internalComponents, isEnableTTDom, isFunction, isNumber, isObject, isString, PLATFORM_TYPE, toCamelCase, UNITLESS_PROPERTIES_SET } from '@tarojs/shared'
33

44
import type { Style, TaroElement } from '@tarojs/runtime'
55

@@ -8,6 +8,7 @@ import type { Style, TaroElement } from '@tarojs/runtime'
88
export type Props = Record<string, unknown>
99

1010
const IS_NON_DIMENSIONAL = /aspect|acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i
11+
const IS_DATASET_OR_ARIA = /^(data|aria)-/
1112

1213
function isEventName (s: string) {
1314
return s[0] === 'o' && s[1] === 'n'
@@ -125,6 +126,17 @@ function setEvent (dom: TaroElement, name: string, value: unknown, oldValue?: un
125126
eventName = 'tap'
126127
}
127128

129+
if (process.env.TARO_ENV === 'tt' && isEnableTTDom()) {
130+
if (isFunction(oldValue)) {
131+
(dom as any).removeEventListener(`bind${eventName}`, dom[`__${eventName}__`])
132+
}
133+
if (isFunction(value)) {
134+
dom[`__${eventName}__`] = eventHandlerTTDom.bind(null, dom, value)
135+
dom.addEventListener(`bind${eventName}`, dom[`__${eventName}__`], isCapture)
136+
}
137+
return
138+
}
139+
128140
if (isFunction(value)) {
129141
if (oldValue) {
130142
dom.removeEventListener(eventName, oldValue as any, process.env.TARO_PLATFORM !== PLATFORM_TYPE.HARMONY ? false : undefined)
@@ -228,42 +240,50 @@ function setProperty (dom: TaroElement, name: string, value: unknown, oldValue?:
228240
) {
229241
// skip
230242
} else if (name === 'style') {
231-
if (/harmony.*cpp/.test(process.env.TARO_ENV || '')) {
232-
return dom.setAttribute('_style4cpp', value)
233-
}
234-
const style = dom.style
235-
if (isString(value)) {
236-
style.cssText = value
243+
if (process.env.TARO_ENV === 'tt' && isEnableTTDom()) {
244+
if (isString(value)) {
245+
dom.setAttribute('style', value)
246+
} else if (isObject(value)) {
247+
dom.setAttribute('style', styleObjectToCss(value as StyleValue))
248+
}
237249
} else {
238-
if (isString(oldValue)) {
239-
style.cssText = ''
240-
oldValue = null
250+
if (/harmony.*cpp/.test(process.env.TARO_ENV || '')) {
251+
return dom.setAttribute('_style4cpp', value)
241252
}
253+
const style = dom.style
254+
if (isString(value)) {
255+
style.cssText = value
256+
} else {
257+
if (isString(oldValue)) {
258+
style.cssText = ''
259+
oldValue = null
260+
}
242261

243-
if (isObject<StyleValue>(oldValue)) {
244-
for (const i in oldValue) {
245-
if (!(value && i in (value as StyleValue))) {
246-
// Harmony特殊处理
247-
if (process.env.TARO_PLATFORM === PLATFORM_TYPE.HARMONY && i === 'position' && oldValue[i] === 'fixed') {
248-
// @ts-ignore
249-
dom.setLayer(0)
262+
if (isObject<StyleValue>(oldValue)) {
263+
for (const i in oldValue) {
264+
if (!(value && i in (value as StyleValue))) {
265+
// Harmony特殊处理
266+
if (process.env.TARO_PLATFORM === PLATFORM_TYPE.HARMONY && i === 'position' && oldValue[i] === 'fixed') {
267+
// @ts-ignore
268+
dom.setLayer(0)
269+
}
270+
setStyle(style, i, '')
250271
}
251-
setStyle(style, i, '')
252272
}
253273
}
254-
}
255274

256-
if (isObject<StyleValue>(value)) {
257-
for (const i in value) {
258-
if (!oldValue || !isEqual(value[i], (oldValue as StyleValue)[i])) {
259-
// Harmony特殊处理
260-
if (process.env.TARO_PLATFORM === PLATFORM_TYPE.HARMONY && i === 'position') {
261-
if (value[i] === 'fixed' || (value[i] !== 'fixed' && oldValue?.[i])) {
262-
// @ts-ignore
263-
dom.setLayer(value[i] === 'fixed' ? 1 : 0)
275+
if (isObject<StyleValue>(value)) {
276+
for (const i in value) {
277+
if (!oldValue || !isEqual(value[i], (oldValue as StyleValue)[i])) {
278+
// Harmony特殊处理
279+
if (process.env.TARO_PLATFORM === PLATFORM_TYPE.HARMONY && i === 'position') {
280+
if (value[i] === 'fixed' || (value[i] !== 'fixed' && oldValue?.[i])) {
281+
// @ts-ignore
282+
dom.setLayer(value[i] === 'fixed' ? 1 : 0)
283+
}
264284
}
285+
setStyle(style, i, value[i])
265286
}
266-
setStyle(style, i, value[i])
267287
}
268288
}
269289
}
@@ -275,10 +295,17 @@ function setProperty (dom: TaroElement, name: string, value: unknown, oldValue?:
275295
const oldHtml = (oldValue as DangerouslySetInnerHTML)?.__html ?? ''
276296
if (newHtml || oldHtml) {
277297
if (oldHtml !== newHtml) {
278-
dom.innerHTML = newHtml
298+
if (process.env.TARO_ENV === 'tt' && isEnableTTDom()) {
299+
setInnerHTML(dom, newHtml)
300+
} else {
301+
dom.innerHTML = newHtml
302+
}
279303
}
280304
}
281305
} else if (!isFunction(value)) {
306+
if (process.env.TARO_ENV === 'tt' && isEnableTTDom() && !IS_DATASET_OR_ARIA.test(name)) {
307+
name = toCamelCase(name)
308+
}
282309
if (value == null) {
283310
dom.removeAttribute(name)
284311
} else {
@@ -297,3 +324,13 @@ function setPseudo(dom: TaroElement, name: '::after' | '::before', value: StyleV
297324
dom.set_pseudo_before(value)
298325
}
299326
}
327+
328+
function styleObjectToCss(style: StyleValue) {
329+
return Object.entries(style)
330+
.map(([key, value]) => {
331+
const kebabCaseKey = key.replace(/([A-Z])/g, '-$1').toLowerCase()
332+
const cssValue = typeof value === 'number' && !UNITLESS_PROPERTIES_SET.has(kebabCaseKey) ? `${value}px` : value === null ? '' : value
333+
return `${kebabCaseKey}: ${cssValue};`
334+
})
335+
.join(' ')
336+
}

0 commit comments

Comments
 (0)