Vue组件通信之Provide / Inject

通常从父组件向子组件传递数据时,用的最多的就是Props。如果有这种场景:有一些深层嵌套的组件。如果使用Props就很复杂了,例如以下结构的嵌套组件:

Root
└─ TodoList
   ├─ TodoItem
   └─ TodoListFooter
      ├─ ClearTodosButton
      └─ TodoListStatistics

需要从TodoList 传递到 TodoListStatistics,如果使用Props,就只能TodoList —> TodoListFooter —> TodoListStatistics 逐层传递。

对于这种情况,可以使用一对provideinject。无论组件层次结构有多深,父组件都可以向所有子组件一键传递数据。

// 爷爷组件
export default {
	name: 'todo-list',
	data() {
		return {
			todos: ['吃🍚', '看🎬']
		}
	},
	provide: {
		todo: '打球'
	}
}

// 孙子组件
export default {
	name: 'todo-list-statistics',
	inject: ['todo'],
	created() {
		console.log(this.todo) // 打球
	}
}

这种写法无法传递组件实例prototype,以下写法将会报错

export default {
	name: 'todo-list',
	data() {
		return {
			todos: ['吃🍚', '看🎬']
		}
	},
	provide: {
		todo: this.todos[0] // Cannot read property 0 of undefined
	}
}

要访问组件实例 property,需将provide作为一个函数,返回一个对象,就像data选项

export default {
	name: 'todo-list',
	data() {
		return {
			todos: ['吃🍚', '看🎬']
		}
	},
	provide() {
		return {
			todo: this.todos[0]
		}
	}
}

以上例子中,如果todos变化了,子组件无法响应其变化,因为provide/inject不是响应式的。可以为 provide的 todo 分配一个 computed:

provide() {
   return {
     todo: Vue.computed(() => this.todos[0])
   }
 }

在vue2中,可以使用Object.defineProperty使provide具有响应性

export default {
    data() {
        return {
            todos: [],
        }
    },
    provide() {
        const rootData = {}

        Object.defineProperty(rootData, "todos", {
            enumerable: true,
            get: () => this.todos,
        })

        return {
            rootData
        }
    }
}

子组件中就可以通过this.rootData.todos拿到父组件的todos

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值