Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: plugin-html支持把div转换成static-view或pure-view #14602

Merged
merged 18 commits into from
Nov 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions packages/shared/src/runtime-hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ type ITaroHooks = {
* @todo: multi
* 修改 Taro DOM 序列化数据
**/
modifyHydrateData:(data: Record<string, any>) => void
modifyHydrateData:(data: Record<string, any>, node) => void
Chen-jj marked this conversation as resolved.
Show resolved Hide resolved
/**
* 自定义处理 Taro DOM 序列化数据,如使其脱离 data 树
*/
Expand Down Expand Up @@ -245,6 +245,10 @@ type ITaroHooks = {

/** 解 Proxy */
proxyToRaw: (proxyObj) => Record<any, any>
/** 元素增加事件监听钩子 */
modifyAddEventListener: (element, sideEffect: boolean, getComponentsAlias: () => Record<string, any>) => void
/** 元素删除事件监听钩子 */
modifyRemoveEventListener: (element, sideEffect: boolean, getComponentsAlias: () => Record<string, any>) => void
}

export const hooks = new TaroHooks<ITaroHooks>({
Expand Down Expand Up @@ -336,5 +340,9 @@ export const hooks = new TaroHooks<ITaroHooks>({

initNativeApi: TaroHook(HOOK_TYPE.MULTI),

patchElement: TaroHook(HOOK_TYPE.MULTI)
patchElement: TaroHook(HOOK_TYPE.MULTI),

modifyAddEventListener: TaroHook(HOOK_TYPE.SINGLE),

modifyRemoveEventListener: TaroHook(HOOK_TYPE.SINGLE),
})
79 changes: 76 additions & 3 deletions packages/taro-plugin-html/src/runtime.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { TaroElement } from '@tarojs/runtime'
import { isHasExtractProp, TaroElement } from '@tarojs/runtime'
import { hooks, Shortcuts, toCamelCase, warn } from '@tarojs/shared'

import { blockElements } from './constant'
import {
defineMappedProp,
ensureHtmlClass,
Expand All @@ -11,14 +12,14 @@ import {
mapNameByContion
} from './utils'

hooks.tap('modifyHydrateData', data => {
hooks.tap('modifyHydrateData', (data, node) => {
Chen-jj marked this conversation as resolved.
Show resolved Hide resolved
const nodeName = data[Shortcuts.NodeName]
if (!isHtmlTags(nodeName)) return

process.env.NODE_ENV !== 'production' && warn(data[Shortcuts.NodeName] === 'select', '请使用 Picker 组件代替 <select>')

// map nodeName
data[Shortcuts.NodeName] = getMappedType(nodeName, data)
data[Shortcuts.NodeName] = getMappedType(nodeName, data, node)

// map attr Key/Value
const attrMapFn = getAttrMapFn(nodeName)
Expand Down Expand Up @@ -73,6 +74,31 @@ hooks.tap('modifySetAttrPayload', (element, key, payload, componentsAlias) => {
payload.path = `${_path}.${Shortcuts.Style}`
payload.value = ensureRect(props, element.style.cssText)
}

if (blockElements.has(element.nodeName)) {
const viewAlias = componentsAlias.view._num
const staticViewAlias = componentsAlias['static-view']._num
const catchViewAlias = componentsAlias['catch-view']._num
const qualifiedNameInCamelCase = toCamelCase(key)
const dataPath = `${_path}.${Shortcuts.NodeName}`
if (qualifiedNameInCamelCase === 'catchMove') {
// catchMove = true: catch-view
// catchMove = false: view or static-view
element.enqueueUpdate({
path: dataPath,
value: payload.value ? catchViewAlias : (
element.isAnyEventBinded() ? viewAlias : staticViewAlias
)
})
} else if (isHasExtractProp(element) && !element.isAnyEventBinded()) {
// pure-view => static-view
// static-view => static-view 因为没有办法分辨之前是不是 pure,所以就算之前是 static 也需要 setData
element.enqueueUpdate({
path: dataPath,
value: staticViewAlias
})
}
}
})

hooks.tap('modifyRmAttrPayload', (element, key, payload, componentsAlias) => {
Expand Down Expand Up @@ -101,6 +127,28 @@ hooks.tap('modifyRmAttrPayload', (element, key, payload, componentsAlias) => {
payload.path = `${_path}.${Shortcuts.Style}`
payload.value = ensureRect(props, element.style.cssText)
}

if (blockElements.has(element.nodeName)) {
const viewAlias = componentsAlias.view._num
const staticViewAlias = componentsAlias['static-view']._num
const pureViewAlias = componentsAlias['pure-view']._num
const qualifiedNameInCamelCase = toCamelCase(key)
const dataPath = `${_path}.${Shortcuts.NodeName}`
if (qualifiedNameInCamelCase === 'catchMove') {
// catch-view => view or static-view or pure-view
element.enqueueUpdate({
path: dataPath,
value: element.isAnyEventBinded() ? viewAlias : (isHasExtractProp(element) ? staticViewAlias : pureViewAlias)
})
} else if (!isHasExtractProp(element)) {
// static-view => pure-view
// pure-view => pure-view 因为没有办法分辨之前是不是 pure,所以就算之前是 pure 也需要 setData
element.enqueueUpdate({
path: dataPath,
value: pureViewAlias
})
}
}
})

hooks.tap('onAddEvent', (type, _handler, _options, node) => {
Expand Down Expand Up @@ -138,3 +186,28 @@ hooks.tap('modifyTaroEvent', (event, element) => {
}
}
})

hooks.tap('modifyAddEventListener', (element, sideEffect, getComponentsAlias) => {
// 如果是从没有事件绑定到有事件绑定,且是 block 元素,则转换为 view
if (blockElements.has(element.nodeName) && sideEffect !== false && !element.isAnyEventBinded()) {
const componentsAlias = getComponentsAlias()
const alias = componentsAlias.view._num
element.enqueueUpdate({
path: `${element._path}.${Shortcuts.NodeName}`,
value: alias
})
}
})

hooks.tap('modifyRemoveEventListener', (element, sideEffect, getComponentsAlias) => {
// 如果已没有绑定事件,且是 block 元素,则转换为 static-view 或 pure-view
if (blockElements.has(element.nodeName) && sideEffect !== false && !element.isAnyEventBinded()) {
const componentsAlias = getComponentsAlias()
const value = isHasExtractProp(element) ? 'static-view' : 'pure-view'
const valueAlias = componentsAlias[value]._num
element.enqueueUpdate({
path: `${element._path}.${Shortcuts.NodeName}`,
value: valueAlias
})
}
})
24 changes: 21 additions & 3 deletions packages/taro-plugin-html/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { isFunction, isString, Shortcuts } from '@tarojs/shared'
import { isHasExtractProp } from '@tarojs/runtime'
import { isFunction, isString, Shortcuts, toCamelCase } from '@tarojs/shared'

import {
blockElements,
Expand All @@ -7,14 +8,16 @@ import {
SpecialMaps
} from './constant'

import type { TaroElement } from '@tarojs/runtime'

export function isHtmlTags (nodeName: string): boolean {
if (inlineElements.has(nodeName) || blockElements.has(nodeName) || specialElements.has(nodeName)) {
return true
}
return false
}

export function getMappedType (nodeName: string, rawProps: Record<string, any>): string {
export function getMappedType (nodeName: string, rawProps: Record<string, any>, node?: TaroElement): string {
if (inlineElements.has(nodeName)) {
return 'text'
} else if (specialElements.has(nodeName)) {
Expand All @@ -25,7 +28,22 @@ export function getMappedType (nodeName: string, rawProps: Record<string, any>):
const { mapName } = mapping
return isFunction(mapName) ? mapName(rawProps) : mapName
} else {
return 'view'
if (node) {
const { props } = node
for (const prop in props) {
const propInCamelCase = toCamelCase(prop)
if (propInCamelCase === 'catchMove' && props[prop] !== false) {
return 'catch-view'
}
}
}
if (!node || node.isAnyEventBinded()) {
return 'view'
} else if (isHasExtractProp(node)) {
return 'static-view'
} else {
return 'pure-view'
}
}
}

Expand Down
6 changes: 5 additions & 1 deletion packages/taro-runtime/src/dom/element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ export class TaroElement extends TaroNode {

public getElementsByClassName (className: string): TaroElement[] {
const classNames = className.trim().split(/\s+/)

return treeToArray(this, (el) => {
const classList = el.classList
return classNames.every(c => classList.contains(c))
Expand Down Expand Up @@ -360,6 +360,8 @@ export class TaroElement extends TaroNode {
delete options.sideEffect
}

hooks.call('modifyAddEventListener', this, sideEffect, getComponentsAlias)

if (sideEffect !== false && !this.isAnyEventBinded() && SPECIAL_NODES.indexOf(name) > -1) {
const componentsAlias = getComponentsAlias()
const alias = componentsAlias[name]._num
Expand All @@ -378,6 +380,8 @@ export class TaroElement extends TaroNode {
const name = this.nodeName
const SPECIAL_NODES = hooks.call('getSpecialNodes')!

hooks.call('modifyRemoveEventListener', this, sideEffect, getComponentsAlias)

if (sideEffect !== false && !this.isAnyEventBinded() && SPECIAL_NODES.indexOf(name) > -1) {
const componentsAlias = getComponentsAlias()
const value = isHasExtractProp(this) ? `static-${name}` : `pure-${name}`
Expand Down
2 changes: 1 addition & 1 deletion packages/taro-runtime/src/hydrate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ export function hydrate (node: TaroElement | TaroText): MiniData {
data[Shortcuts.Style] = cssText
}

hooks.call('modifyHydrateData', data)
hooks.call('modifyHydrateData', data, node)
Chen-jj marked this conversation as resolved.
Show resolved Hide resolved

const nn = data[Shortcuts.NodeName]
const componentAlias = componentsAlias[nn]
Expand Down
2 changes: 1 addition & 1 deletion packages/taro-runtime/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export * from './emitter/emitter'
export { hydrate } from './hydrate'
export { nextTick } from './next-tick'
export { options } from './options'
export { incrementId } from './utils'
export { incrementId, isHasExtractProp } from './utils'
// typings
export * from './dsl/instance'
export * from './interface'