-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
函数式组件作为页面时如何使用页面配置和页面事件处理函数 #3054
Comments
欢迎提交 Issue~ 如果你提交的是 bug 报告,请务必遵循 Issue 模板的规范,尽量用简洁的语言描述你的问题,最好能提供一个稳定简单的复现。🙏🙏🙏 如果你的信息提供过于模糊或不足,或者已经其他 issue 已经存在相关内容,你的 issue 有可能会被关闭。 Good luck and happy coding~ |
目前我们的想法是像原生小程序一样引入一个配置 JSON 文件 |
CC @luckyadam |
好的,那页面事件处理函数(onPullDownRefresh、onReachBottom 等)是用钩子(usePullDownRefresh、useReachBottom 等)实现吗 |
这种情况我觉得就应该用 Class 来写 |
同样遇到这个问题,react-hooks 无法支撑小程序原生的api |
个人觉得页面的 config 应该改为静态属性而不是实例属性,就像组件一样,反正 config 是编译成静态的 json 文件。 function Index() {
return (
<View className='index'>
<Text>1</Text>
</View>
)
}
Index.config = {
navigationBarBackgroundColor: '#ffffff',
navigationBarTextStyle: 'black',
navigationBarTitleText: '首页',
backgroundColor: '#eeeeee',
backgroundTextStyle: 'light'
}
export default Index |
同时这也比引入一个json配置文件要直观和易维护。 |
close via 08cf9b3 |
下个版本就可以支持你这个写法 |
如果是这样,Hooks 的使用场景势必会受到很大的限制,希望提供相应的自定义 hooks。 在官方提供支持前,可以像下面这样写,将页面拆成容器和内容两部分,容器组件部分依然使用 Class API 以便使用小程序周期方法,内容组件使用 Hooks API编写。 容器组件 export default class extends Taro.Component {
state = { value: 0 }
onPullDownRefresh() {
this.setState(c => c + 1)
}
render () {
return (
<MyPage value={this.state.value}/>
)
}
} 内容组件 function MyPage (props) {
const [value, setValue] = useState(props.value)
return <View>{value}</View>
} |
@yuche 所以该问题的最终定论是如果设计原生生命周期,例如 |
hooks 是运行时才能知道有什么 hooks,而原生钩子函数例如 |
Taro 是否可以为函数组件提前注册原生钩子函数,等到运行时下发对应事件进行处理呢?(下面是我想到的一个示意代码) // 用户代码
function MyPage (props) {
const [value, setValue] = useState(props.value)
usePullDownRefresh(MyPage, () => {
setValue(value + 1)
}, [value])
return <View>{value}</View>
}
// taro 内部
function usePullDownRefresh (MyPage, cb, deps) {
useEffect(() => {
MyPage.addEventlisten('pulldownrefresh', cb)
return () => {
MyPage.removeEventlisten('pulldownrefresh', cb)
}
}, deps)
}
// Taro 在创建组件时,为组件加上监听事件,当对应事件触发时,下发事件,如 MyPage.dispatch('pulldownrefresh') |
把所有的回调保存到组件实例貌似是可行的。 编译后的代码样例: Page({
data: {
text: "This is page data."
},
__eventHooks: {
onPullDownRefresh: [
callback1,
callback2,
callback3,
]
},
onPullDownRefresh: function() {
this.__eventHooks.onPullDownRefresh.forEach(callback => callback(arguments))
},
}) taro/hooks.js 的简单实现样例: // taro/hooks.js
export function usePullDownRefresh (callback) {
const hook = getHooks(Current.index++);
if (!hook.component) {
// 第一次运行此钩子
// 保存组件实例
hook.component = Current.current;
// 设置默认值
if (hook.component.__eventHooks === undefined) {
hook.component.__eventHooks = {}
}
const eventHooks = hook.component.__eventHooks;
if (eventHooks.onPullDownRefresh === undefined) {
eventHooks.onPullDownRefresh = []
// 记录为第一个使用 usePullDownRefresh 的钩子
hook.isFirstEventHook = true;
}
// 在组件中保存此回调
eventHooks.onPullDownRefresh = eventHooks.onPullDownRefresh.concat(callback)
} else {
if (hook.isFirstEventHook) {
// 此为第一个使用 usePullDownRefresh 的钩子,清空旧的钩子
eventHooks.onPullDownRefresh = [];
}
// 在组件中保存此回调
eventHooks.onPullDownRefresh = eventHooks.onPullDownRefresh.concat(callback);
}
} 使用: function Page() {
usePullDownRefresh(() => {
console.log('pull down refresh 1')
})
usePullDownRefresh(() => {
console.log('pull down refresh 2')
})
usePullDownRefresh(() => {
console.log('pull down refresh 3')
})
return (
<View>Test For usePullDownRefresh</View>
)
} |
有计划支持嘛,随便还想问一下如何获取router |
router似乎还是可以通过
不过没有阅读编译代码,不知道会有什么问题。 |
taro 好像没有支持这种多次定义钩子的实现,不知道是为什么 |
通过查看 Taro Hooks 实现的源码部分: 具体的源码在 https://github.com/NervJS/taro/blob/master/packages/taro/src/hooks.js#L40-L91 function usePageLifecycle (callback, lifecycle) {
const hook = getHooks(Current.index++)
if (!hook.marked) {
hook.marked = true
hook.component = Current.current
hook.callback = callback
const component = hook.component
const originalLifecycle = component[lifecycle]
hook.component[lifecycle] = function () {
const callback = hook.callback
originalLifecycle && originalLifecycle.call(component, ...arguments)
return callback && callback.call(component, ...arguments)
}
} else {
hook.callback = callback
}
}
export function useDidShow (callback) {
usePageLifecycle(callback, 'componentDidShow')
} 可以发现 Taro 在第一次运行某一个页面生命周期钩子时是保存了之前的页面生命周期函数,然后重新设置了一遍页面的生命周期函数,会先调用之前保存的页面生命周期函数再调用本次 Hooks 里传递的函数,理论上是支持多次调用的,之前的生命周期函数里已经有回调了,后面的调用依然会保存之前生命周期函数,依然会执行。 |
可以支持 Page 层面的 onLoad 和 onUnload 生命周期吗,或者将 usePageLifecycle API 暴露出来,允许开发人员根据需求使用相应的生命周期 |
useEffect(() => {
console.log('load');
return => {
console.log('unload');
};
}, []); |
比如原来的类组件是:
config 是类的实例属性,不是静态属性,如果这样是不行的:
换成函数式组件应该如何使用
页面配置
,看了下没有提供useConfig
钩子,页面事件处理函数
(onPullDownRefresh
、onReachBottom
等等)也同样面临这个问题,希望能提供一些钩子(usePullDownRefresh
、useReachBottom
等等)来解决这个问题The text was updated successfully, but these errors were encountered: