vue2和vue3 依赖注入 provide inject

1,251 阅读3分钟

vue2

普通方式


// 祖先

export default {
    data () {
        obj: {
            url: []
        }
    },
    provide () {
       obj: this.obj
    }
}

然后 子组件 这么接

export default {
    inject: ['obj']
}

然后 子组件 就可以拿来用

<template>
    {{ obj }}
    
    {{ obj.url }}
</template>

那有的小伙伴说了,我改一下obj里面的url的值,子组件拿到的obj.url的值还是旧的值。

官方解释:provide 和 inject 绑定并不是可响应的。这里刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的property还是可响应的。

那么,到这里就要用到 响应式的处理方式了。

响应式 方法

这里用 传递 一个方法的办法

// 祖先

export default {
    data () {
        obj: {
            url: []
        }
    },
    provide () {
       getObj: () => this.obj
    }
}

然后 子组件 这么接

export default {
    inject: ['getObj'],
    computed: {
       obj () {
           return this.getObj()
       } 
    }
}

然后 子组件 就可以拿来用

<template>
    {{ obj }}
    
    {{ obj.url }}
</template>

obj.url值改了,子组件得到的就是新鲜出炉的。


问: 其他的地方也有用这个曾孙的组件,但是不传provide,会报错,这怎么解决?

没事,不是还有默认值吗

默认值

案例

不传provide,就用默认值inject,不会报错,有默认值顶着。

在 vue2 中,如果一个键在祖先提供者的provide中不存在,则会使用inject中这个键的默认值。

// 祖先组件提供的 `foo`

provide: {
    foo: 'bar'
}

// 子组件注入 'foo'

inject: {
    foo: {
        default: 'default'
    }
}

如果祖先不提供,就用子组件自己默认的。

provide 传参为方法 案例

// 祖先

export default {
    data () {
        obj: {
            url: []
        }
    },
    provide () {
       getObj: () => this.obj
    }
}

// 子组件inject的default的默认值这么写

就是一个返回对象{ url: [] }的函数


export default {
    inject: {
        getObj: {
            default: () => {
                return () => {
                    return {
                        url: []
                    }
                }
            }
        }
    },
    computed: {
       obj () {
           return this.getObj()
       } 
    }
}

上面的示例,就是vue2中provide inject 响应式 并且 不传也不会报错的(加了默认值)的例子。

以此记录。


vue3 (这里讲组合式)

在vue3中,provide 和 inject 。与 vue2 不同的是,vue3 中的 provide 和 inject 默认使用了响应式的数据传递方式,这就意味着当provide中的数据发生变化是,所有使用inject注入的后代组件都能够接收到更新。

基本用法

// 祖先

<script>
    import { ref, provide } from 'vue'
    
    // 提供静态值
    provide('foo', 'bar')
    
    // 提供响应式的值
    const count = ref(0)
    provide('count', count)
</script>

// 子组件

<script>
    import { inject } from 'vue'
    
    // 注入值的默认方式
    const foo = inject('foo')
    
    // 注入值的响应式方式
    const count = inject('count')
    
    
    
    
    // 注入一个值,若为空则使用提供的默认值
    const foo = inject('foo', 'default')
</script>

提供函数 以及 接收函数 写法

// 祖先

<script>
    import { ref, provide } from 'vue'
    
    const getUser = () => {
        return {
            name: 'Jack',
            age: 35
        }
    }

    provide('getUser', getUser)
</script>

// 子组件

<script>
    import { reactive, inject } from 'vue'
     
    const getUser = inject(
        'getUser',
        () => ({})
    )
    
    const user = reactive(getUser())
    
</script>

总结

在 Vue 2 中,provideinject 提供的是一种非响应式的数据传递方式。

这意味着通过 provide 提供的数据在子组件中可以被访问和使用,但是如果在子组件中修改了这些数据,这些修改并不会反映到父组件中的数据上。

这是因为 Vue 2 中的 provideinject 使用的是普通的 JavaScript 对象来传递数据,并且这些对象不是响应式的。

相比之下,在 Vue 3 中,provideinject 默认使用响应式的数据传递方式。

这意味着通过 provide 提供的数据在子组件中可以被访问和使用,并且如果在子组件中修改了这些数据,这些修改会实时地反映到父组件中的数据上。

这是因为 Vue 3 中的 provideinject 使用的是响应式的数据结构来传递数据,例如 reactiveref

这个变化的主要原因是为了提供更好的性能和开发体验。

在 Vue 2 中,由于 provideinject 不是响应式的,所以如果需要在子组件中修改父组件中的数据,通常需要使用事件或回调函数等额外的逻辑来实现。

这样不仅增加了代码量,也可能导致性能问题。

而在 Vue 3 中,由于 provideinject 默认使用响应式的数据传递方式,这些问题都得到了有效的解决。

希望能有所帮助。

最好的学习是贡献和输出。

本文正在参加「金石计划」