Jetpack Compose对比React Hooks API相似度

目录

React Component vs Composable

JSX vs DSL

loop

If statement

key component

Children Prop vs Children Composable

Context vs Ambient(CompositionLocal)

createContext : ambientOf

Provider : Provider

useContext : Ambient.current

useState vs State

useMemo vs remember

useEffect vs SideEffect

useEffect(callback, deps) :DisposableEffect

Clean-up function : onDispose

Hook vs Effect

众所周知Jetpack Compose设计理念甚至团队成员很多都来自React,在API方面参考了很多React(Hooks) 的设计,通过与React进行对比可以更好地熟悉Compose的相关功能。

Compose目前处于alpha版,虽然API还会调整,但是从功能上已经基本对齐了React,不会有大变化,本文基于1.0.0-alpha11。

React Component vs Composable

React中Component成为分割UI的基本单元,特别是16.8之后Hooks引入的函数组件,相对于类组件更利于UI与逻辑解耦。函数组件是一个接受Props作为参数并返回JSX node的函数:

function Greeting(props) { return <span>Hello {props.name}!</span>; }

Compose同样使用函数作为组件:添加了@Composable注解的函数。而且借助Kotlin的DSL实现声明式语法,而无需额外引入JSX等其他标记语言,相对于React更加简洁:

@Composable fun Greeting(name: String) { Text(text = "Hello $name!") } JSX vs DSL

DSL相对于JSX更加简洁,可以直接使用原生语法表示各种逻辑。

loop

例如在JSX中实现一个循环逻辑,需要两种语言混编

function NumberList(props) { return ( <ul> {props.numbers.map((number) => ( <ListItem value={number} /> ))} </ul> ); }

DSL中的循环就是普通的for循环

@Composable fun NumberList(numbers: List<Int>) { Column { for (number in numbers) { ListItem(value = number) } } } If statement

JSX 使用三元运算符表示条件

function Greeting(props) { return ( <span> {props.name != null ? `Hello ${props.name}!` : 'Goodbye.'} </span> ); }

DSL直接使用IF表达式

@Composable fun Greeting(name: String?) { Text(text = if (name != null) { "Hello $name!" } else { "Goodbye." }) } key component

React和Compose都可以通过key来标记列表中的特定组件,缩小重绘范围。

JSX使用key属性

<ul> {todos.map((todo) => ( <li key={todo.id}>{todo.text}</li> ))} </ul>

DSL使用key组件来标识Component

Column { for (todo in todos) { key(todo.id) { Text(todo.text) } } } Children Prop vs Children Composable

前面提到,React与Compose都使用函数组件创建UI,区别在于一个使用DSL,另一个依靠JSX。

React中,子组件通过props的children字段传入

function Container(props) { return <div>{props.children}</div>; } <Container> <span>Hello world!</span> </Container>;

Compose中,子组件以@Composable函数的形式传入

@Composable fun Container(children: @Composable () -> Unit) { Box { children() } } Container { Text("Hello world"!) } Context vs Ambient(CompositionLocal)

对于函数组件来说,建议使用props/parameter传递数据,但是允许一些全局数据在组件间共享。React使用Context存放全局数据,Compose使用Ambient(alpha12中已改名CompositionLocal)存放全局数据

createContext : ambientOf

React使用createContext创建Context:

const MyContext = React.createContext(defaultValue);

Compose使用ambientOf创建Ambient:

val myValue = ambientOf<MyAmbient>() Provider : Provider

React和Compose中都使用Provider注入全局数据,供子组件访问

<MyContext.Provider value={myValue}> <SomeChild /> </MyContext.Provider> Providers(MyAmbient provides myValue) { SomeChild() } useContext : Ambient.current

React中子组件使用useContext hook访问Context

const myValue = useContext(MyContext);

Compose中子组件通过单例对象访问Ambient

val myValue = MyAmbient.current useState vs State

无论React还是Compose,状态管理都是至关重要的。

React使用useState hook创建State

const [count, setCount] = useState(0); <button onClick={() => setCount(count + 1)}> You clicked {count} times </button>

Compose使用mutableStateOf创建一个state,还可以通过by代理的方式获取

val count = remember { mutableStateOf(0) } Button(onClick = { count.value++ }) { Text("You clicked ${count.value} times") }

还可以通过解构分别获取get/set

val (count, setCount) = remember { mutableStateOf(0) } Button(onClick = { setCount(count + 1) }) { Text("You clicked ${count} times") }

或者通过by代理

var count : Int by remember { mutableStateOf(false) } Button(onClick = { count++ }) { Text("You clicked ${count} times") }

Compose创建state时往往会remeber{ } 避免重绘时的反复创建state,相当于useMemo

useMemo vs remember

React使用useMemo hook用来保存那些不能随重绘反复计算的值,只有参数变化时才会重新计算。

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

Compose中同样功能使用remember实现,同样通过参数作为重新计算的判断条件

val memoizedValue = remember(a, b) { computeExpensiveValue(a, b) } useEffect vs SideEffect

函数组件满足纯函数的要求:无副作用、无状态、即使多次运行也不会产生影响。但是总有一些逻辑不能以纯函数执行,例如 生命周期回调、日志、订阅、计时等,只能在特定时机执行,不能像一个纯函数那样可以执行多次而不产生副作用。

React中,useEffect 提供一个hook点,会在每次render时执行。注意 这不同于直接写在外面,当diff没有变化时不需要重新render,就不需要执行useEffect了

useEffect(() => { sideEffectRunEveryRender(); });

Compose中使用SideEffect处理副作用(早期版本是onCommit{ })

SideEffect { sideEffectRunEveryComposition() } useEffect(callback, deps) :DisposableEffect

跟useMemo一样可以接受参数,每次render时,只有当参数变化时才执行:

useEffect(() => { sideEffect(); }, [dep1, dep2]);

只在第一次render时执行的逻辑(相当于onMount),可以使用如下形式处理:

useEffect(() => { sideEffectOnMount(); }, []);

Compose中使用DisposableEffect:

DisposableEffect( key1 = "", ... ) { onDispos{} } Clean-up function : onDispose

useEffect通过返回一个function进行后处理

useEffect(() => { const subscription = source.subscribe(); return () => { subscription.unsubscribe(); }; });

DisposableEffect通过一个DisposableEffectDisposable进行后处理:

DisposableEffect() { val dispose = source.subscribe() onDispose { //返回DisposableEffectDisposable dispose.dispose() } } Hook vs Effect

React允许自定义Hooks封装可复用逻辑。Hooks可以调用useState、useEffect等其他hooks放方法,在特定的生命周期完成逻辑。自定义Hooks都使用useXXX的形式来命名

function useFriendStatus(friendID) { const [isOnline, setIsOnline] = useState(null); useEffect(() => { function handleStatusChange(status) { setIsOnline(status.isOnline); } ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange); return () => { ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange); }; }); return isOnline; }

Compose没有命名上的要求,任何一个@Composable函数即可被用来实现一段可复用的处理Effect的逻辑:

@Composable fun friendStatus(friendID: String): State<Boolean?> { val isOnline = remember { mutableStateOf<Boolean?>(null) } DisposableEffect { val handleStatusChange = { status: FriendStatus -> isOnline.value = status.isOnline } ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange) onDispose { ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange) } } return isOnline }

以上就是Jetpack Compose对比React Hooks API相似度的详细内容,更多关于Jetpack Compose对比React的资料请关注易知道(ezd.cc)其它相关文章!

推荐阅读

    React解决长列表方案|react-virtualized

    React解决长列表方案|react-virtualized,元素,过程,github地址高效渲染大型列表的响应式组件 使用窗口特性,即在一个滚动的范围内,呈现你

    启用wapi是什么意思

    启用wapi是什么意思,鉴别,用户,安全机制,开启,网络,客户端,启用wapi是手机连接无线局域网时的一项可选功能选项,开启它可以提高使用无线网络的安

    google地图api接口

    google地图api接口,地图,接口,开发者,地理编码,调用,地址,Google地图API接口是由Google提供的一种开放式接口,用于开发者通过调用相应的API来集

    api是什么

    api是什么,开发人员,应用程序,网站,浏览器,控制,硬件,api全称“Application Programming Interface”,中文意思为“应用程序编程接口”,是一些预

    wapi是什么

    wapi是什么,产品,破解,协议,加密技术,传输协议,美国,wapi是无线局域网鉴别和保密基础结构,是一种安全协议,同时也是中国无线局域网安全强制性标准

    .Net Core Api 跨域配置

    .Net Core Api 跨域配置,两个,标签,.Net Core 和Asp.Net 不同,不需要再去引用其他的跨域组件。创建项目时,就有了。让接口实现跨域,需要配置

    WAPI是什么

    WAPI是什么,传输协议,宋体,协议,安全机制,保密,流行,  WAPI是WLAN Authentication and Privacy Infrastructure的英文缩写。它像红外线、蓝牙

    百度地图API是什么

    百度地图API是什么,百度,中国,服务,地图,百度地图,公益事业,  百度地图API是一套有javascript语言编写的应用程序接口,他能帮助您在网站中构建