Skip to content

Commit

Permalink
fix(miniprogram): 修复循环 ref 问题,fix #5052
Browse files Browse the repository at this point in the history
小程序循环 ref 可以使用 createRef 了
  • Loading branch information
Chen-jj committed Dec 19, 2019
1 parent d67dfc2 commit af9d81c
Show file tree
Hide file tree
Showing 12 changed files with 67 additions and 38 deletions.
3 changes: 2 additions & 1 deletion packages/taro-alipay/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
internal_get_original,
interceptors,
RefsArray,
handleLoopRef,
useEffect,
useLayoutEffect,
useReducer,
Expand Down Expand Up @@ -64,7 +65,7 @@ export const Taro = {
internal_get_original,
interceptors,
RefsArray,
getElementById,
handleLoopRef: handleLoopRef(getElementById),
genCompid,
useEffect,
useLayoutEffect,
Expand Down
1 change: 1 addition & 0 deletions packages/taro-alipay/src/lifecycle.js
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ function doUpdate (component, prevProps, prevState) {
} else if (component.$componentType === 'PAGE' && component['$$hasLoopRef']) {
// 解决初始化时 onLoad 最先触发,但拿不到子组件 ref 的问题
Current.current = component
Current.index = 0
component._disableEffect = true
component._createData(component.state, component.props, true)
component._disableEffect = false
Expand Down
3 changes: 2 additions & 1 deletion packages/taro-jd/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
internal_get_original,
interceptors,
RefsArray,
handleLoopRef,
useEffect,
useLayoutEffect,
useReducer,
Expand Down Expand Up @@ -60,7 +61,7 @@ export const Taro = {
internal_inline_style,
createComponent,
internal_get_original,
getElementById,
handleLoopRef: handleLoopRef(getElementById),
propsManager,
interceptors,
RefsArray,
Expand Down
3 changes: 2 additions & 1 deletion packages/taro-qq/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
internal_get_original,
interceptors,
RefsArray,
handleLoopRef,
useEffect,
useLayoutEffect,
useReducer,
Expand Down Expand Up @@ -60,7 +61,7 @@ export const Taro = {
internal_inline_style,
createComponent,
internal_get_original,
getElementById,
handleLoopRef: handleLoopRef(getElementById),
propsManager,
interceptors,
RefsArray,
Expand Down
3 changes: 2 additions & 1 deletion packages/taro-swan/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
internal_get_original,
interceptors,
RefsArray,
handleLoopRef,
useEffect,
useLayoutEffect,
useReducer,
Expand Down Expand Up @@ -62,7 +63,7 @@ export const Taro = {
internal_get_original,
interceptors,
RefsArray,
getElementById,
handleLoopRef: handleLoopRef(getElementById),
propsManager,
genCompid,
useEffect,
Expand Down
2 changes: 1 addition & 1 deletion packages/taro-transformer-wx/src/constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export const INTERNAL_INLINE_STYLE = 'internal_inline_style'

export const INTERNAL_GET_ORIGNAL = 'internal_get_original'

export const GEL_ELEMENT_BY_ID = 'getElementById'
export const HANDLE_LOOP_REF = 'handleLoopRef'

export const PROPS_MANAGER = 'propsManager'

Expand Down
6 changes: 3 additions & 3 deletions packages/taro-transformer-wx/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import {
THIRD_PARTY_COMPONENTS,
INTERNAL_GET_ORIGNAL,
setLoopOriginal,
GEL_ELEMENT_BY_ID,
HANDLE_LOOP_REF,
lessThanSignPlacehold,
COMPONENTS_PACKAGE_NAME,
quickappComponentName,
Expand Down Expand Up @@ -716,7 +716,7 @@ export default function transform (options: Options): TransformResult {
t.importSpecifier(t.identifier(INTERNAL_SAFE_GET), t.identifier(INTERNAL_SAFE_GET)),
t.importSpecifier(t.identifier(INTERNAL_GET_ORIGNAL), t.identifier(INTERNAL_GET_ORIGNAL)),
t.importSpecifier(t.identifier(INTERNAL_INLINE_STYLE), t.identifier(INTERNAL_INLINE_STYLE)),
t.importSpecifier(t.identifier(GEL_ELEMENT_BY_ID), t.identifier(GEL_ELEMENT_BY_ID)),
t.importSpecifier(t.identifier(HANDLE_LOOP_REF), t.identifier(HANDLE_LOOP_REF)),
t.importSpecifier(t.identifier(GEN_COMP_ID), t.identifier(GEN_COMP_ID)),
t.importSpecifier(t.identifier(GEN_LOOP_COMPID), t.identifier(GEN_LOOP_COMPID))
)
Expand Down Expand Up @@ -767,7 +767,7 @@ export default function transform (options: Options): TransformResult {
t.importSpecifier(t.identifier(INTERNAL_SAFE_GET), t.identifier(INTERNAL_SAFE_GET)),
t.importSpecifier(t.identifier(INTERNAL_GET_ORIGNAL), t.identifier(INTERNAL_GET_ORIGNAL)),
t.importSpecifier(t.identifier(INTERNAL_INLINE_STYLE), t.identifier(INTERNAL_INLINE_STYLE)),
t.importSpecifier(t.identifier(GEL_ELEMENT_BY_ID), t.identifier(GEL_ELEMENT_BY_ID)),
t.importSpecifier(t.identifier(HANDLE_LOOP_REF), t.identifier(HANDLE_LOOP_REF)),
t.importSpecifier(t.identifier(GEN_COMP_ID), t.identifier(GEN_COMP_ID)),
t.importSpecifier(t.identifier(GEN_LOOP_COMPID), t.identifier(GEN_LOOP_COMPID))
]
Expand Down
39 changes: 14 additions & 25 deletions packages/taro-transformer-wx/src/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ import {
THIRD_PARTY_COMPONENTS,
LOOP_ORIGINAL,
INTERNAL_GET_ORIGNAL,
GEL_ELEMENT_BY_ID,
HANDLE_LOOP_REF,
PROPS_MANAGER,
GEN_COMP_ID,
ALIPAY_BUBBLE_EVENTS,
Expand Down Expand Up @@ -1799,38 +1799,27 @@ export class RenderParser {
throw codeFrameError(component.node, '在循环中使用 ref 必须暴露循环的第二个参数 `index`')
}
const id = typeof ref.id === 'string' ? t.binaryExpression('+', t.stringLiteral(ref.id), indexId) : ref.id
const refDeclName = '__ref'
const args: any[] = [
t.identifier('__scope'),
t.binaryExpression('+', t.stringLiteral('#'), id)
]
if (ref.type === 'component') {
args.push(t.stringLiteral('component'))
}
const callGetElementById = t.callExpression(t.identifier(GEL_ELEMENT_BY_ID), args)
const refDecl = buildConstVariableDeclaration(refDeclName,
isTestEnv ? callGetElementById : t.logicalExpression('&&', t.identifier('__scope'), t.logicalExpression('&&', t.identifier('__isRunloopRef'), callGetElementById))
)
const callRef = t.callExpression(ref.fn, [t.identifier(refDeclName)])
const callRefFunc = t.expressionStatement(
isTestEnv ? callRef : t.logicalExpression('&&', t.identifier(refDeclName), callRef)
)
if (Adapter.type === Adapters.tt) {
body.push(
t.expressionStatement(
t.logicalExpression(
'&&',
t.logicalExpression('&&', t.identifier('__scope'), t.identifier('__isRunloopRef')),
t.callExpression(
t.memberExpression(t.identifier('Taro'), t.identifier('handleLoopRef')),
args.length === 2 ? [...args, t.nullLiteral(), ref.fn] : [...args, ref.fn]
)
)
)
)
} else {
body.push(refDecl, callRefFunc)
args.push(t.stringLiteral('dom'))
}
args.push(ref.fn)
const callHandleLoopRef = t.callExpression(t.identifier(HANDLE_LOOP_REF), args)

const loopRefStatement = t.expressionStatement(
t.logicalExpression(
'&&',
t.logicalExpression('&&', t.identifier('__scope'), t.identifier('__isRunloopRef')),
callHandleLoopRef
)
)

body.splice(body.length - 1, 0, loopRefStatement)
}

if (isNewPropsSystem()) {
Expand Down
19 changes: 16 additions & 3 deletions packages/taro-tt/src/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -242,19 +242,32 @@ export function getUniqueKey () {
return _loadTime + (_i++)
}

export function handleLoopRef (component, id, type, handler = function () {}) {
function triggerLoopRef (that, dom, handler) {
const handlerType = typeof handler
if (handlerType !== 'function' && handlerType !== 'object') {
return console.warn(`循环 Ref 只支持函数或 createRef(),当前类型为:${handlerType}`)
}

if (handlerType === 'object') {
handler.current = dom
} else if (handlerType === 'function') {
handler.call(that, dom)
}
}

export function handleLoopRef (component, id, type, handler) {
if (!component) return null

let res
if (type === 'component') {
component.selectComponent(id, function (res) {
res = res ? res.$component || res : null
res && handler.call(component.$component, res)
res && triggerLoopRef(component.$component, res, handler)
})
} else {
const query = wx.createSelectorQuery().in(component)
res = query.select(id)
res && handler.call(component.$component, res)
res && triggerLoopRef(component.$component, res, handler)
}

return null
Expand Down
3 changes: 2 additions & 1 deletion packages/taro-weapp/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
internal_get_original,
interceptors,
RefsArray,
handleLoopRef,
useEffect,
useLayoutEffect,
useReducer,
Expand Down Expand Up @@ -60,7 +61,7 @@ export const Taro = {
internal_inline_style,
createComponent,
internal_get_original,
getElementById,
handleLoopRef: handleLoopRef(getElementById),
propsManager,
interceptors,
RefsArray,
Expand Down
4 changes: 3 additions & 1 deletion packages/taro/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { getOriginal as internal_get_original } from './internal/get-original'
import { getEnv, ENV_TYPE } from './env'
import Events from './events'
import render from './render'
import { createRef, commitAttachRef, detachAllRef, RefsArray } from './ref'
import { createRef, commitAttachRef, detachAllRef, RefsArray, handleLoopRef } from './ref'
import Link from './interceptor'
import * as interceptors from './interceptor/interceptors'
import {
Expand Down Expand Up @@ -76,6 +76,7 @@ export {
Link,
interceptors,
RefsArray,
handleLoopRef,
Current,
useEffect,
useLayoutEffect,
Expand Down Expand Up @@ -123,6 +124,7 @@ export default {
Link,
interceptors,
RefsArray,
handleLoopRef,
Current,
useEffect,
useLayoutEffect,
Expand Down
19 changes: 19 additions & 0 deletions packages/taro/src/ref.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,22 @@ export class RefsArray extends Array {
!isExist && this.push(ref)
}
}

export function handleLoopRef (getElementById) {
return (component, id, type, handler) => {
if (!component) return null

const dom = getElementById(component, id, type)

const handlerType = typeof handler
if (handlerType !== 'function' && handlerType !== 'object') {
return console.warn(`循环 Ref 只支持函数或 createRef(),当前类型为:${handlerType}`)
}

if (handlerType === 'object') {
handler.current = dom
} else if (handlerType === 'function') {
handler.call(component.$component, dom)
}
}
}

0 comments on commit af9d81c

Please sign in to comment.