如何在单文件组件中使用ES6 vue-loader扩展另一个VueJS组件?

42

我正在使用vue-loader来构建我的*.vue单文件组件,但是在尝试从另一个组件扩展单文件组件的过程中遇到麻烦。

如果一个组件遵循规范:export default { [组件“Foo”定义] },我认为只需要像导入任何子组件一样导入此组件,然后export default Foo.extend({ [扩展组件定义] })

不幸的是,这并不起作用。请问有人可以提供建议吗?

5个回答

51

经过一些测试,简单的解决方案是确保导出一个Vue.extend()对象而不是一个普通对象来扩展任何组件。

在我的情况下,基础组件:

import Vue from 'vue'

export default Vue.extend({ [component "Foo" definition] })

以及扩展组件:

import Foo from './Foo'

export default Foo.extend({ [extended component definition] })

这是一个很棒的想法,很高兴你已经搞定了。我可以想象在某些地方,这可能比混合更可取。 - Jeff
正是我在寻找的,谢谢。在我看来,这比被接受的解决方案更好,因为一个整个组件无法作为Mixin,否则会大大增加名称冲突的机会。Mixin应该仅限于较小的共享代码。 - Kashif
6
这对我有用,但我必须小心覆盖函数。例如像mounted这样的生命周期调用没有被覆盖,奇怪的是它和它的super都被调用了。但是在methods中声明的函数确实被覆盖了。所以我把需要覆盖的逻辑移到methods中,并从生命周期调用中调用它们。 - yeahdixon
我本来更喜欢使用这种方法而不是 mixins,因为这感觉更像是一种传统的继承模式,但不幸的是,如果你使用 TypeScript 而不是 Javascript,这并不完全适用,因为“子”组件不会继承“父”组件的数据属性。令人沮丧的是,mixins 在 TypeScript 中也不能直接使用。最后,我通过使用此插件来修复 TypeScript 的 mixins,从而成功实现了组件继承:https://www.npmjs.com/package/vue-typed-mixins - Joe Irby

29

另一种可能性是extends选项:

import Foo from './Foo'

export default { extends: Foo }

1
有没有办法像 export default { extends: Foo, Bar, Baz } 这样扩展多个对象? - Phantom007
2
@Phantom007 mixins. - trusktr
这方面有没有有用的文档?模板是如何合并的?我可以添加第二个事件处理程序吗?等等。 - phil294
那就是解决方案! :) - poitroae

20

正确的做法是使用混入(mixins): http://vuejs.org/guide/mixins.html

将混入视为抽象组件,您可以扩展它。因此,您可以创建一个混入,其中包含您想要在两者中具有的任何功能,然后将其应用于每个组件。


1
警告:如果您在Vue项目中使用TypeScript而不是JavaScript,则混入将无法直接编译。幸运的是,有人编写了一个包来解决这个问题:https://www.npmjs.com/package/vue-typed-mixins - Joe Irby

5
我建议避免使用Vue的"extends"功能,因为它是Vue命名不当的方法。在继承的情况下,它实际上并没有扩展任何内容。它所做的正是mixin所做的事情,即合并两个组件。它与模板代码无关,也不可扩展。 "extend" Vue 方法应该被称为"merge"。
无论如何,Vue必须与DOM的层次结构一起工作,并将组件组合到DOM中。相同的思维方式也应用于SFC的构建。使用组件mixin来进行基础行为,根据需要将mixin添加到组件中,同时将最小的共同部分组合成更大的部分,尽可能地保持模板代码的简洁性。在组合SFC时,应该考虑到“薄视图,重模型”的原则。:)

1
自从 Vue 3 推出,引入了 Composition API,使得在组件之间共享状态变得非常容易。
与其在组件定义对象上定义属性(例如 data、computed、methods 等),Composition API 允许你创建一个 setup 函数,在其中声明并返回这些属性。
以下是一个例子:
文件:useCounter.js
import { reactive, computed } from "vue";

export default function {
  const state = reactive({
    count: 0,
    double: computed(() => state.count * 2)
  });

  function increment() {
    state.count++
  }

  return {
    count,
    double,
    increment
  }
}

现在,计数器功能可以通过Vue组件的设置函数无缝引入:
文件:MyComponent.vue
<template>
   <button @click="increment">
      Count is: {{ count }}, double is: {{ double }}
   </button>
</template>

<script>
import useCounter from "./useCounter";

export default {
  setup() {
    const { count, double, increment } = useCounter();
    return {
      count,
      double,
      increment
    }
  }
}
</script>

使用组合式 API 声明组件的主要好处之一是它使逻辑重用和提取变得非常容易。组合函数是通过使组件的功能模块化和可重用来扩展组件的最简单和免费的方式。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接