-
Notifications
You must be signed in to change notification settings - Fork 382
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]rn-relatons #1679
[feat]rn-relatons #1679
Changes from 6 commits
503e927
4418593
4ded781
a2fd798
c5fe79c
a215026
a998767
6f6774d
c44dc0c
9cecc80
0f7fc85
d3ccb55
6ec95f0
81e85fe
5bf606f
f227571
64853bb
c7d477d
41a8415
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
import relationsMixin from './relationsMixin.ios' | ||
export default relationsMixin |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import { BEFORECREATE, MOUNTED, BEFOREUNMOUNT } from '../../core/innerLifecycle' | ||
|
||
const relationTypeMap = { | ||
parent: 'child', | ||
ancestor: 'descendant' | ||
} | ||
|
||
export default function relationsMixin (mixinType) { | ||
if (mixinType === 'component') { | ||
return { | ||
[BEFORECREATE] () { | ||
this.__mpxRelations = {} | ||
this.__mpxRelationNodesMap = {} | ||
}, | ||
[MOUNTED] () { | ||
this.__mpxCollectRelations() | ||
this.__mpxExecRelations('linked') | ||
}, | ||
[BEFOREUNMOUNT] () { | ||
this.__mpxExecRelations('unlinked') | ||
this.__mpxRelations = {} | ||
this.__mpxRelationNodesMap = {} | ||
}, | ||
methods: { | ||
getRelationNodes (path) { | ||
return this.__mpxRelationNodesMap[path] || null | ||
}, | ||
__mpxCollectRelations () { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 感觉这个循环还有this.__mpxRelations有点多余,如果下面的this.__relation是按需生成的这里可以省略很多逻辑 |
||
const relations = this.__mpxProxy.options.relations | ||
if (!relations) return | ||
Object.keys(relations).forEach(path => { | ||
const relation = relations[path] | ||
this.__mpxCheckParent(this, relation, path) | ||
}) | ||
}, | ||
__mpxCheckParent (current, relation, path) { | ||
const type = relation.type | ||
const relationMap = current.__relation | ||
if (!relationMap) return | ||
|
||
if (relationMap[path]) { | ||
const target = relationMap[path] | ||
const targetRelation = target.__mpxProxy.options.relations?.[this.__componentPath] | ||
if (targetRelation && targetRelation.type === relationTypeMap[type] && target.__componentPath) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. target.__componentPath 这个判断为啥需要 |
||
this.__mpxRelations[path] = { | ||
target, | ||
targetRelation, | ||
relation | ||
} | ||
this.__mpxRelationNodesMap[path] = [target] | ||
} | ||
} | ||
}, | ||
__mpxExecRelations (type) { | ||
Object.keys(this.__mpxRelations).forEach(path => { | ||
const { target, targetRelation, relation } = this.__mpxRelations[path] | ||
const currentPath = this.__componentPath | ||
if (type === 'linked') { | ||
this.__mpxLinkRelationNodes(target, currentPath) | ||
} else if (type === 'unlinked') { | ||
this.__mpxRemoveRelationNodes(target, currentPath) | ||
} | ||
if (typeof targetRelation[type] === 'function') { | ||
targetRelation[type].call(target, this) | ||
} | ||
if (typeof relation[type] === 'function') { | ||
relation[type].call(this, target) | ||
} | ||
}) | ||
}, | ||
__mpxLinkRelationNodes (target, path) { | ||
target.__mpxRelationNodesMap[path] = target.__mpxRelationNodesMap[path] || [] // 父级绑定子级 | ||
target.__mpxRelationNodesMap[path].push(this) | ||
}, | ||
__mpxRemoveRelationNodes (target, path) { | ||
const arr = target.__mpxRelationNodesMap[path] || [] | ||
const index = arr.indexOf(this) | ||
if (index !== -1) arr.splice(index, 1) | ||
} | ||
} | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
import { useEffect, useLayoutEffect, useSyncExternalStore, useRef, useMemo, useState, useCallback, createElement, memo, forwardRef, useImperativeHandle, useContext, Fragment, cloneElement } from 'react' | ||
import { useEffect, useLayoutEffect, useSyncExternalStore, useRef, useMemo, useState, useCallback, createElement, memo, forwardRef, useImperativeHandle, useContext, Fragment, cloneElement, createContext } from 'react' | ||
import * as ReactNative from 'react-native' | ||
import { ReactiveEffect } from '../../observer/effect' | ||
import { watch } from '../../observer/watch' | ||
|
@@ -193,7 +193,7 @@ const instanceProto = { | |
} | ||
} | ||
|
||
function createInstance ({ propsRef, type, rawOptions, currentInject, validProps, components, pageId, intersectionCtx }) { | ||
function createInstance ({ propsRef, type, rawOptions, currentInject, validProps, components, pageId, intersectionCtx, relation }) { | ||
const instance = Object.create(instanceProto, { | ||
dataset: { | ||
get () { | ||
|
@@ -233,6 +233,18 @@ function createInstance ({ propsRef, type, rawOptions, currentInject, validProps | |
}, | ||
enumerable: false | ||
}, | ||
__componentPath: { | ||
get () { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 这里也限定组件再挂载吧,否则会取到其他组件的值很奇怪 |
||
return currentInject.componentPath || '' | ||
}, | ||
enumerable: false | ||
}, | ||
__relation: { | ||
get () { | ||
return relation | ||
}, | ||
enumerable: false | ||
}, | ||
__injectedRender: { | ||
get () { | ||
return currentInject.render || noop | ||
|
@@ -374,6 +386,43 @@ function usePageStatus (navigation, pageId) { | |
}, [navigation]) | ||
} | ||
|
||
const RelationsContext = createContext(null) | ||
|
||
const needRelationContext = (options) => { | ||
const relations = options.relations | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. relations的分析可以createComponent里做完直接存在闭包里,没有必要在render里做 |
||
if (!relations) return false | ||
return Object.keys(relations).some((path) => { | ||
const relation = relations[path] | ||
const type = relation.type | ||
return type === 'child' || type === 'descendant' | ||
}) | ||
} | ||
|
||
const provideRelation = (instance) => { | ||
const componentPath = instance.__componentPath | ||
const relation = instance.__relation | ||
if (relation) { | ||
if (!relation[componentPath]) { | ||
relation[componentPath] = instance | ||
} | ||
return relation | ||
} else { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 需要返回一个新对象,而不是修改原有对象 |
||
return { | ||
[componentPath]: instance | ||
} | ||
} | ||
} | ||
|
||
const wrapRelationProvider = (element, instance) => { | ||
if (needRelationContext(instance.__mpxProxy.options)) { | ||
return createElement(RelationsContext.Provider, { | ||
value: provideRelation(instance) | ||
}, element) | ||
} else { | ||
return element | ||
} | ||
} | ||
|
||
export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) { | ||
rawOptions = mergeOptions(rawOptions, type, false) | ||
const components = Object.assign({}, rawOptions.components, currentInject.getComponents()) | ||
|
@@ -384,11 +433,12 @@ export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) { | |
const propsRef = useRef(null) | ||
const intersectionCtx = useContext(IntersectionObserverContext) | ||
const pageId = useContext(RouteContext) | ||
const relation = useContext(RelationsContext) | ||
propsRef.current = props | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 解析放到mount中进行,render中简单透传relation即可 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if(hasDescendantRelation || hasAncestorRelation) { |
||
let isFirst = false | ||
if (!instanceRef.current) { | ||
isFirst = true | ||
instanceRef.current = createInstance({ propsRef, type, rawOptions, currentInject, validProps, components, pageId, intersectionCtx }) | ||
instanceRef.current = createInstance({ propsRef, type, rawOptions, currentInject, validProps, components, pageId, intersectionCtx, relation }) | ||
} | ||
const instance = instanceRef.current | ||
useImperativeHandle(ref, () => { | ||
|
@@ -472,9 +522,9 @@ export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) { | |
const rootProps = getRootProps(props, validProps) | ||
rootProps.style = Object.assign({}, root.props.style, rootProps.style) | ||
// update root props | ||
return cloneElement(root, rootProps) | ||
return wrapRelationProvider(cloneElement(root, rootProps), instance) | ||
} | ||
return root | ||
return wrapRelationProvider(root, instance) | ||
})) | ||
|
||
if (rawOptions.options?.isCustomText) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
现在不需要加这个额外的.android了,文件条件编译找不到.android会自动去找.ios