
建议使用Vue mixin在组件之间共享通用功能。 除非您为它们使用多个,否则它们会很好。 这是因为它们在设计上是隐式的,并污染了组件的上下文。 让我们尝试通过为他们提供尽可能多的明确性来解决此问题。
目标
我们希望有一个全局的mixin,它为任何组件提供一个称为types
baseClass
,并输出从mods
继承自baseClass
的CSS类数组。
鉴于此标记:
<SampleComponent :types="['active', 'block']"></SampleComponent>
我们期望有这个(假设我们的baseClass
是sample-component
):
<div class="sample-component sample-component--active sample-component--block"></div>
天真的方法
通过仅阅读Vue文档,您的第一个想法可能是只使用内置属性合并并在所需组件中将mods
作为计算属性提供。
// SampleComponent.vue <template> <div class="sample-component" :class="mods"><slot /></div> </template>
import bemMods from 'bemMods.js'; export default { name: 'SampleComponent', mixins: [ bemMods('sample-component') ] }
这种方法存在许多问题:
- 每个组件中的样板代码。 (至少在Vue方法中)
- 对
baseClass
参数的依赖。 - 没有明确指示
mods
属性来自何处。 - 名称冲突很容易发生。
我们将在下一步中尝试解决所有这些问题。
带有明确导出的Mixin
Vue有一个依赖注入机制,称为Inject \ Provide 。 它可以潜在地解决污染环境下的问题。
首先,让我们从一个简单的mixin切换到一个接受选项的插件,稍后我们将使用它来避免名称冲突。
其次,我们还可以将组件的名称作为baseClass
而不必在每个组件中都将其作为自定义选项。
最后,如果组件的baseClass
与名称不匹配,我们将保留将baseClass
作为函数参数传递的选项。
现在,我们准备在全球范围内注册我们的插件。
import Vue from 'vue'; import bemMods from 'bemMods.js'; Vue.use(bemMods);
我们还可以通过提供一个options对象来自定义道具的调用方式。
import Vue from 'vue'; import bemMods from 'bemMods.js'; Vue.use(bemMods, { propName: 'modifiers', modsName: 'classes' });
这是mixin重构后我们的组件的外观:
<template> <div class="sample-component" :class="mods"><slot /></div> </template>
export default { name: 'SampleComponent',
假设我们的组件没有name
或者它的name
具有不同的baseClass
:
<template> <div class="special-component" :class="mods('snowflake')"><slot /></div> </template>
export default { name: 'SpecialComponent', inject: ['mods'] }
或者,如果我们希望为重构或插件删除做好准备:
export default { name: 'SomeComponent', inject: {
您还可以将Symbol
用作mods名称,以完全消除名称冲突,但这将要求您在每个要使用bemMods
组件中都包含该符号。
我们没有隐式指定道具名称,但这是一个核心的混合限制,我们试图通过在插件配置中使用自定义道具名称来克服。
希望这对您有所帮助,并且您找到了一种为Vue编写mixins的更好方法。