2020年10月21日(vue composition api)


  • 逻辑复用及代码整理
  • 更好的Typescript支持

https://vue-composition-api-rfc.netlify.app/#summary

Vue中的是使用依赖追踪的方式去通知变更的,所以在开发Vue组件的时候我们只需要用this.x = y重新赋值某个状态,DOM Tree就会自动响应变更。这是Vue的优势,但在Composition API中就变了一个需要重点关注的点,如果使用不好,甚至会变成缺点。

我是可以从试着从Vue的实现原理去查找此原因。Vue2中是使用Object.defineProperty,而Vue3则使用了Proxy,但无论使用哪种方法,我们在访问和设置某个state的时候实际是调用了他们getter/setter的方法,但是这个state作为一个返回值或者参数的时候,它实际是作为一个传递到了另外要给方法中,所以他的getter/setter将会丢失,数据无法响应。

这涉及到了引用传递及值传递,官方api也说的非常清楚

function changeStuff(a, b, c) {
  a = a * 10
  b.item = 'changed'
  c = { item: 'changed' }
}

var num = 10
var obj1 = { item: 'unchanged' }
var obj2 = { item: 'unchanged' }

changeStuff(num, obje1, obj2)
console.log(num)
console.log(obj1.item)
console.log(obj2.item)

打印结果为

10
changed
unchanged

这说明Javascript中参数传递是以值传递的方式进行传递的,而传递的内容是它自己本身的引用值

image-20201021203338813

解决方法可以使用toRefs

如果你从一个组合函数里返回了响应式对象,在使用函数里把它解构进行使用是会丢失响应性的,解决这个问题你可以把原封不动的返回:

import { toRefs, reactive } from 'vue'
function useCounter () {
    let data = reactive({
        count: 0
    })
    return toRefs(data)
}
export default {
    setup() {
        let {count} = useCounter()
        return {
            count
        }
    }
}

setup函数里返回的数据使用toRefs转换一下是有好处的:

import { toRefs, reactive } from 'vue'
export default {
    setup() {
        let data = reactive({
            count: 0
        })
        return {
            ...toRefs(data)
        }
    }
}

如果这样的话在模板里使用需要通过data.count来引用count的值,如果使用toRefs的话可以直接使用count

另外一个是使用ref去初始化state

import { toRefs, reactive } from 'vue'
function useCounter () {
   let count =ref (0)
   return {count}
}
export default {
    setup() {
        let {count} = useCounter()
        return {
            count
        }
    }
}

vue3的响应式原理(proxy和reflect)可以看

https://www.vuemastery.com/courses/vue-3-reactivity/


Author: wxy
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint policy. If reproduced, please indicate source wxy !
  TOC