Skip to content

Commit

Permalink
fix(runtime): 修复组件切换属性和事件时出现的问题, fix #8520
Browse files Browse the repository at this point in the history
  • Loading branch information
Chen-jj committed Jan 14, 2021
1 parent fb057d3 commit bc94aed
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 26 deletions.
1 change: 1 addition & 0 deletions packages/taro-runtime/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export const PROPERTY_THRESHOLD = 2046
export const TARO_RUNTIME = 'Taro runtime'
export const SET_DATA = '小程序 setData'
export const PAGE_INIT = '页面初始化'
export const SPECIAL_NODES = ['view', 'text', 'image']
47 changes: 42 additions & 5 deletions packages/taro-runtime/src/dom/element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { isArray, isUndefined, Shortcuts, EMPTY_OBJ, warn, isString, toCamelCase
import { TaroNode } from './node'
import { NodeType } from './node_types'
import { TaroEvent, eventSource } from './event'
import { isElement } from '../utils'
import { isElement, isHasExtractProp } from '../utils'
import { Style } from './style'
import { PROPERTY_THRESHOLD } from '../constants'
import { PROPERTY_THRESHOLD, SPECIAL_NODES } from '../constants'
import { CurrentReconciler } from '../reconciler'
import { treeToArray } from './tree'
import { ClassList } from './class-list'
Expand Down Expand Up @@ -93,16 +93,21 @@ export class TaroElement extends TaroNode {
eventSource.set(value as string, this)
qualifiedName = 'uid'
} else {
this.props[qualifiedName] = value as string
if (qualifiedName === 'class') {
qualifiedName = Shortcuts.Class
}
if (qualifiedName.startsWith('data-')) {
} else if (qualifiedName.startsWith('data-')) {
if (this.dataset === EMPTY_OBJ) {
this.dataset = Object.create(null)
}
this.dataset[toCamelCase(qualifiedName.replace(/^data-/, ''))] = value
} else if (this.nodeName === 'view' && !isHasExtractProp(this) && !this.isAnyEventBinded()) {
// pure-view => static-view
this.enqueueUpdate({
path: `${this._path}.${Shortcuts.NodeName}`,
value: 'static-view'
})
}
this.props[qualifiedName] = value as string
}

CurrentReconciler.setAttribute?.(this, qualifiedName, value)
Expand All @@ -126,6 +131,14 @@ export class TaroElement extends TaroNode {
path: `${this._path}.${toCamelCase(qualifiedName)}`,
value: ''
})

if (this.nodeName === 'view' && !isHasExtractProp(this) && !this.isAnyEventBinded()) {
// static-view => pure-view
this.enqueueUpdate({
path: `${this._path}.${Shortcuts.NodeName}`,
value: 'pure-view'
})
}
}

public getAttribute (qualifiedName: string): string {
Expand Down Expand Up @@ -217,4 +230,28 @@ export class TaroElement extends TaroNode {
}
}
}

public addEventListener (type, handler, options) {
const name = this.nodeName
if (!this.isAnyEventBinded() && SPECIAL_NODES.indexOf(name) > -1) {
this.enqueueUpdate({
path: `${this._path}.${Shortcuts.NodeName}`,
value: name
})
}

super.addEventListener(type, handler, options)
}

public removeEventListener (type, handler) {
super.removeEventListener(type, handler)

const name = this.nodeName
if (!this.isAnyEventBinded() && SPECIAL_NODES.indexOf(name) > -1) {
this.enqueueUpdate({
path: `${this._path}.${Shortcuts.NodeName}`,
value: isHasExtractProp(this) ? `static-${name}` : `pure-${name}`
})
}
}
}
33 changes: 12 additions & 21 deletions packages/taro-runtime/src/hydrate.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { isText } from './utils'
import { isText, isHasExtractProp } from './utils'
import { TaroElement } from './dom/element'
import { TaroText } from './dom/text'
import { SPECIAL_NODES } from './constants'
import { Shortcuts, toCamelCase } from '@tarojs/shared'
import type { PageConfig } from '@tarojs/taro'

Expand Down Expand Up @@ -40,35 +41,25 @@ export type HydratedData = () => MiniData | MiniData[]
* it's a vnode traverser and modifier: that's exactly what Taro's doing in here.
*/
export function hydrate (node: TaroElement | TaroText): MiniData {
const nodeName = node.nodeName

if (isText(node)) {
return {
[Shortcuts.Text]: node.nodeValue,
[Shortcuts.NodeName]: node.nodeName
[Shortcuts.NodeName]: nodeName
}
}

const data: MiniElementData = {
[Shortcuts.NodeName]: node.nodeName,
[Shortcuts.NodeName]: nodeName,
uid: node.uid
}
const { props, childNodes } = node

if (!node.isAnyEventBinded()) {
if (node.nodeName === 'view') {
const isExtractProp = Object.keys(props).find(prop => {
return !(/class|style|id/.test(prop) || prop.startsWith('data-'))
})
if (isExtractProp) {
data[Shortcuts.NodeName] = 'static-view'
} else {
data[Shortcuts.NodeName] = 'pure-view'
}
}
if (node.nodeName === 'text') {
data[Shortcuts.NodeName] = 'static-text'
}
if (node.nodeName === 'image') {
data[Shortcuts.NodeName] = 'static-image'
if (!node.isAnyEventBinded() && SPECIAL_NODES.indexOf(nodeName) > -1) {
data[Shortcuts.NodeName] = `static-${nodeName}`
if (nodeName === 'view' && !isHasExtractProp(node)) {
data[Shortcuts.NodeName] = 'pure-view'
}
}

Expand All @@ -83,7 +74,7 @@ export function hydrate (node: TaroElement | TaroText): MiniData {
) {
data[propInCamelCase] = props[prop]
}
if (node.nodeName === 'view' && propInCamelCase === 'catchMove' && props[prop] !== 'false') {
if (nodeName === 'view' && propInCamelCase === 'catchMove' && props[prop] !== 'false') {
data[Shortcuts.NodeName] = 'catch-view'
}
}
Expand All @@ -96,7 +87,7 @@ export function hydrate (node: TaroElement | TaroText): MiniData {
data[Shortcuts.Class] = node.className
}

if (node.cssText !== '' && node.nodeName !== 'swiper-item') {
if (node.cssText !== '' && nodeName !== 'swiper-item') {
data[Shortcuts.Style] = node.cssText
}

Expand Down
7 changes: 7 additions & 0 deletions packages/taro-runtime/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,10 @@ export function isElement (node: TaroNode): node is TaroElement {
export function isText (node: TaroNode): node is TaroText {
return node.nodeType === NodeType.TEXT_NODE
}

export function isHasExtractProp (el: TaroElement): boolean {
const res = Object.keys(el.props).find(prop => {
return !(/class|style|id/.test(prop) || prop.startsWith('data-'))
})
return Boolean(res)
}

0 comments on commit bc94aed

Please sign in to comment.