vue修改计算属性的值_使用React hooks实现Vue的“计算属性”

计算属性,是Vue中一个非常重要也无比好用的特性,例如:

var vm = new Vue({
  el: '#example',
  data: {
    message: 'Hello'
  },
  computed: {
    // 计算属性的 getter
    reversedMessage: function () {
      // `this` 指向 vm 实例
      return this.message.split('').reverse().join('')
    }
  }
})

在模版中,即可直接使用reversedMessage

<div id="example">
  <p>Original message: "{{ message }}"</p>
  <p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>

使用计算属性,一方面可以简化语法,也就说我们不需要每次都手动写一遍message.split('').reverse().join('')了,或者是非常麻烦地将其封装成一个函数;另一方面,计算属性会自动被缓存,这样可以让应用的性能更好。

那么说了这么多,有没有办法在React中实现类似的逻辑呢?

当然!

得益于React 16.8新推出的Hooks特性,我们可以对逻辑进行更优雅的封装

首先,我们来介绍一下useMemo

掌握了 useStateuseEffect 其实远远是不够的, useMemo这样的hook看起来小众,但其实用处非常大!

官方对useMemo的介绍在这里, 简而言之,就是我们传入一个回调函数和一个依赖列表,React会在依赖列表中的值变化时,调用这个回调函数,并将回调函数返回的结果进行缓存后,返回给上一层:

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

对应到本文最开始的Vue例子,我们用useMemo的实现就是:

function App (props) {
  const [message, setMessage] = useState('hello')
  const reversedMessage = useMemo(() => (
    message.split('').reverse().join('')
  ), [message])
  
  return (
    <div>
      {message}
      {reversedMessage}
    </div>
  )
}

message发生变化时,React会重新计算message.split('').reverse().join(''),然后把得到的结果进行缓存,并且返回给reversedMessage变量。

是不是没有想象中那么难?

不过,上面的例子中还有一个小问题,那就是对异步逻辑的处理。

const replyMessage = useMemo(() => (
  api.fetchReply(message) // 这里是一个异步的网络请求
), [message])

由于api.fetchReply调用得到的返回值是Promise,所以reversedMessage的类型变成了Promise<string>而非string

这时,我们就需要使用useAsyncMemo了 。(是的,它比useMemo就是多了个async)

由于useAsyncMemo不是React提供的hook ,我们需要先通过npmyarn安装它:

$ npm install use-async-memo --save
# 或者
$ yarn add use-async-memo

然后,我们来使用useAsyncMemo改写上面的逻辑:

import {useAsyncMemo} from 'use-async-memo'

const replyMessage = useAsyncMemo(async () => ( // 这里的回调函数变成了async函数
  await api.fetchReply(message) // 这里也变成了await
), [message])

对比一下就会发现,useAsyncMemo的第一个参数不再是普通的函数了,而变成了一个异步函数,这里我们使用了es6的async function特性。除此之外,和之前useMemo的写法非常相似。这样,我们就可以通过replyMessage变量获取到异步函数返回的值了。

啥是async await?关于async函数的介绍,可以参考这里

其实,useAsyncMemo 的用处远不仅仅是这些。

还记得当年写到脑壳疼的“文本框输入的同时自动搜索”逻辑么?使用useAsyncMemo,分分钟就可以搞定:

const [input, setInput] = useState()
const users = useAsyncMemo(async () => {
  if (input === '') return []
  return await apiService.searchUsers(input)
}, [input], [])

甚至还可以加上防抖动的逻辑:

const [input, setInput] = useState()
const [debouncedInput] = useDebounce(input, 300)
const users = useAsyncMemo(async () => {
  if (debouncedInput === '') return []
  return await apiService.searchUsers(debouncedInput)
}, [debouncedInput], [])

关于useAsyncMemo的详细介绍,可以在GitHub上查看:

awmleer/use-async-memo​github.com
e38a7233cdde1ecd6f3983f6aea03241.png

(如果觉得好用的话,不妨点个Star~)

如果对useMemouseAsyncMemo有任何疑问的话,也欢迎在评论区中一同探讨~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值