什么是Vue.extend?

Joh*_*ore 39 vue.js

这很简单,但我没有从文档中得到我需要的答案.我在学习Vue.js的过程中,我真的不明白的地方Vue.extend.我得到Vue.component适合,但我看不出有什么Vue.extend做这Vue.component不.它只是1.0的遗留功能吗?如果没有,它在Vue 2.0中有用吗?

Joh*_*iao 30

以前的Vuejs.org网站上的指南有一份文件.

复制自http://optimizely.github.io/vuejs.org/guide/composition.html,它是从vuejs/Vuejs.org分发的Vuejs版本0.10.6.

明白之间的差别是非常重要的Vue.extend()Vue.component().由于Vue它本身是一个构造函数,因此 Vue.extend()是一个类继承方法.它的任务是创建一个子类Vue并返回构造函数. Vue.component()另一方面,是一种类似于和的资产登记方法.它的任务是将给定的构造函数与字符串ID相关联,以便Vue.js可以在模板中选择它.当直接传入选项时 ,它会在引擎盖下调用.Vue.directive()Vue.filter()Vue.component()Vue.extend()

Vue.js支持两种不同的API范例:基于类,命令式,Backbone样式的API,以及基于标记的声明性Web组件样式API.如果您感到困惑,请考虑如何使用new Image()或使用<img>标记创建图像元素.每个都是有用的,Vue.js试图提供最大的灵活性.


Mar*_*ski 26

Vue v2 的文档有点稀少,Vue.extends但简而言之:

您可以使用Vue.extend创建组件定义(称为“组件构造”老文档中),并Vue.component注册它,所以它可以在模板中使用实际创建组件实例

<div id="example">
  <my-component></my-component>
</div>
Run Code Online (Sandbox Code Playgroud)
// define
var MyComponent = Vue.extend({
  template: '<div>A custom component!</div>'
})
// register
Vue.component('my-component', MyComponent)
// create a root instance
new Vue({
  el: '#example'
})
Run Code Online (Sandbox Code Playgroud)

但是,在 Vue API 中可以传递由Vue.extend您创建的“组件构造函数”的任何地方都可以传递普通对象,它会调用Vue.extend

所以前面的例子可以写成

// define
var MyComponent = {
  template: '<div>A custom component!</div>'
}
// register
Vue.component('my-component', MyComponent)
// create a root instance
new Vue({
  el: '#example'
})
Run Code Online (Sandbox Code Playgroud)

看来人们现在更喜欢将组件定义为普通的 JS 对象(在 Vue 世界中称为选项对象)。

您可以看到,在当前的 Vue v2 文档中,您很少看到Vue.extends提及,而在 v1 的文档中,它在描述Vue 实例的第一章(与v2比较)中进行了清楚的解释,并且在组件章节中得到了很好的解释。明确指出直接传递 options 对象只是一个

我的猜测是,为了保持简单易学,新文档只在任何地方使用普通对象。为什么要解释诸如“Vue 构造函数”、“组件构造函数”之类的附加概念,什么是Vue.extend您 99% 的时间不需要理解它?您可以定义所有的应用程序的组件与普通的JS选择对象,并登记,而无需使用它们Vue.extends。当必须使用VUE构造函数的唯一的地方是当创建根Vue的实例new Vue({...})。这使用基本Vue构造函数。您不需要知道Vue 构造函数可以扩展为使用预定义选项创建可重用的组件构造函数,因为尽管您可以命令式地创建扩展实例,但在大多数情况下,您会将组件构造函数注册为自定义元素并以声明方式将它们组合在模板中。来源

因此文档作者决定您不需要了解Vue.extends. 但是是否有任何用例值得使用Vue.extend而不是普通的选项对象?

是的。

打字稿

如果您想使用 Typescript(并且不喜欢类样式组件),那么您应该使用正确的类型推断Vue.extend而不是普通对象。它使用特征来获得对对象的正确推断。ThisType<T> this

显示带有 Vue.extend 函数的代码的图像,我们看到它被 Typescript 识别

组件继承(以及 Typescript)

.extend不仅可以在基础Vue构造函数上使用,还可以在自定义组件上使用。这不如mixins灵活,因为您可以在组件中使用许多 mixin,而.extend方法仅适用于一个组件。但是,它与 Typescript 一起使用效果更好,因为它的 mixins 似乎不能很好发挥作用.extend对于许多情况,使用Typescript 支持可能“足够好”。您可以从继承的组件访问字段,但是如果您的组件与“基本”组件有一些名称冲突,那么它就不能很好地工作(例如,我得到了一种never冲突道具名称的类型)。

<div id="appBar">
    {{fooMessage}} || {{barMessage}} || {{ additionalData}}
    <button v-on:click="changeAllMessages">Change</button>
</div>
Run Code Online (Sandbox Code Playgroud)
var FooComponent = Vue.extend({
    data: () => ({
        fooMessage: 'Foo message'
    }),
    methods: {
        changeFooMessage() {
            this.fooMessage = "Foo message changed";
        }
    }
})
var BarComponent = FooComponent.extend({
    data: () => ({
        barMessage: "Bar message",
    }),
    methods: {
        changeAllMessages() {
            this.barMessage = "Bar message changes";
            this.changeFooMessage();
        }
    }
});
new BarComponent({ el: "#appBar", data: { additionalData: "additional data passed" } });
Run Code Online (Sandbox Code Playgroud)

在这里,我还展示了您可以使用自定义组件来创建根 Vue 实例( new BarComponent({...}))。就像你可以做的一样new Vue({...})。也许它不是那么有用,但它表明 BarComponent并且FooComponent只是扩展的基本Vue构造函数,您可以像使用Vue.


Guy*_*uyC 25

我认为混淆是因为扩展和组件紧密相连.要在内部创建Vue调用扩展组件:

// register an options object (automatically call Vue.extend)
Vue.component('my-component', { /* ... */ })
Run Code Online (Sandbox Code Playgroud)

因此,您可以使用extend来挂载基本Vue构造函数的子类(组件构造函数):https://vuejs.org/v2/api/#Vue-extend

但是你不太可能遇到或需要走这条路.相反,您将使用组件来获取命名的子类,您可以在应用程序中轻松引用它们.

因此,Extend不是真正的"遗留"功能,它是Vue组件的核心,但组件提供的附加糖使它们成为您工作的默认方式.


Mat*_*ens 13

除了提供的答案外,Vue.extend()如果使用TypeScript ,还有一个实际的用例可以直接调用。

在大多数情况下,建议在需要时从其他文件导入组件定义,而不是使用全局注册它们Vue.component()。它使事情在较大的项目中井井有条,并使跟踪问题更加容易。

有了正确的库,打字稿可以看看你的组件定义,弄清组件的类型将是当它的初始化,意味着那么它可以检查您已经定义,看看它们是否有意义(也就是说,如果你引用的功能this.foo有实际上是一个prop,数据字段,计算值或名为的方法foo。如果使用Vue.component()它,则可以做到这一点,但是如果使用使组件可用的其他典型方式(即导出对象文字),则不能这样做。

但是,另一种选择是导出包裹在中的组件定义Vue.extend()。然后,TypeScript将能够将其识别为Vue组件并相应地运行其类型检查,但是您不必放弃导出组件的最佳实践模式,而不必在全局范围内进行注册。

  • 这在不使用TS而是使用查找智能感知类型定义的IDE时也很有用。 (2认同)
  • 谢谢你。这正是我在想的,但你比文档更清楚地解释了它。 (2认同)
  • 当 Typescript 抱怨 `this.$refs` 时,我为此苦苦挣扎了几个小时,但我不明白为什么。用“Vue.extend({ ..... })”包装我的普通对象解决了问题。 (2认同)