Vue 中的受控与非受控组件的实现(2)

当然由于在这种模式下外部对状态有完全的控制权,所以在 active-idx-change 的事件处理中也可以做更为复杂的判断,例如是否允许激活目标 Tab 之类的校验。

而在 Tabs 组件内部,我们还需要做一些小的修改。在受控模式中,我们所有状态相关的处理都是直接使用 localActiveIdx,而现在我们的逻辑应该变为“如果存在 activeIdx props,则使用,否则使用 localActiveIdx”。

为了保证以上逻辑不会让我们的组件内部实现变得复杂、易错,我们引入一个 computed 属性:

computed: { _activeIdx() { return this.activeIdx || this.localActiveIdx; } }

这样我们就可以把状态相关的判断改为通过 idx === _activeIdx 判断一个 Tab 是否为激活状态,也通过 {{ tabs[_activeIdx].content }} 展示 active Tab 的内容。

同样,我们在 handleActiveIdxChange 的方法内部也可以增加一个判断,如果存在 props aciveIdx 则不更新 localActiveIdx:

handleActiveIdxChange(idx) { if (this.activeIdx === undefined) { this.localActiveIdx = idx; } this.$emit("active-idx-change", idx); }

在一些更复杂的组件中,可能会频繁判断是否为受控模式并做不同的处理,这时候通过 this.activeIdx 这样的核心状态 props 是否传入来判断是否为受控模式是一个不错的实践。

总结

最终我们为 active index 设计的完整 API 如下:

{ props: { activeIdx: Number, defaultActiveIdx: { type: Number, default: 0 } }, data() { return { localActiveIdx: this.defaultActiveIdx }; }, computed: { _activeIdx() { return this.activeIdx || this.localActiveIdx; } }, methods: { handleActiveIdxChange(idx) { if (this.activeIdx === undefined) { this.localActiveIdx = idx; } this.$emit("active-idx-change", idx); } } }

通过这种 API 设计方式,可以让我们设计的基础组件使用方式更一致,拓展性更强,不论是开发还是使用时思路也会更加简洁清晰。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/dff8df8892b8889891968e377ec223a4.html