Vue.extend 有啥用?

Posted

技术标签:

【中文标题】Vue.extend 有啥用?【英文标题】:What is Vue.extend for?Vue.extend 有什么用? 【发布时间】:2017-04-04 18:58:48 【问题描述】:

这很简单,但我没有从文档中得到我需要的答案。我正在学习 Vue.js,但我不太明白 Vue.extend 适合哪里。我得到了 Vue.component,但我看不到 Vue.extend 做了哪些 Vue.component 没有.它只是 1.0 的遗留功能吗?如果没有,它在 Vue 2.0 中有什么用处?

【问题讨论】:

***.com/questions/31709462/… 【参考方案1】:

他们在之前的 Vuejs.org 网站上的指南有一个文档。

从http://optimizely.github.io/vuejs.org/guide/composition.html 复制而来,该http://optimizely.github.io/vuejs.org/guide/composition.html 是从 Vuejs 0.10.6 版本的 vuejs/Vuejs.org 派生出来的。

了解Vue.extend()之间的区别很重要 和Vue.component()。由于Vue 本身就是一个构造函数, Vue.extend() 是一个类继承方法。它的任务是 创建Vue 的子类并返回构造函数。 另一方面,Vue.component() 是一个资产注册 方法类似于Vue.directive()Vue.filter()。它的任务是 将给定的构造函数与字符串 ID 相关联,以便 Vue.js 可以选择 它在模板中。当直接将选项传递给 Vue.component(),它在后台调用Vue.extend()

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

【讨论】:

【参考方案2】:

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

// register an options object (automatically call Vue.extend)
Vue.component('my-component',  /* ... */ )

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

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

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

【讨论】:

【参考方案3】:

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

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

使用正确的库,TypeScript 可以查看您的组件定义并确定组件在初始化时的类型,这意味着它可以检查您定义的函数是否有意义(即,如果您引用this.foo 实际上有一个名为foo 的道具、数据字段、计算值或方法。如果您使用Vue.component(),它将能够做到这一点,但如果您使用其他使组件可用的典型方法,即导出对象文字,则不能。

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

【讨论】:

这在不使用 TS 而是使用查找智能感知类型定义的 IDE 时也很有用。 谢谢。这正是我的想法,但你解释得比文档更清楚。 当 Typescript 抱怨 this.$refs 时,我为此苦苦挣扎了好几个小时,但我不知道为什么。用Vue.extend( ..... ) 包裹我的普通对象解决了这个问题。 感谢 @mattias-martens 您关于 TS 的最后一段,以及 Vue.extend 的作用帮助我理解了为什么它解决了我在尝试访问 $vuetify$store 时的所有类型错误的原因或 $route 在 nuxt+ts+vuetify 项目中。我能够用Vue.extend 解决它,但在文档中没有看到明确解释为什么这是要走的路。那谢谢啦。也许这将在未来帮助更多的人【参考方案4】:

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

您使用Vue.extend 创建组件定义(在旧文档中称为“组件构造函数”)和Vue.component 到register 它可以在模板中使用它来实际创建组件实例。

<div id="example">
  <my-component></my-component>
</div>
// 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'
)

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

所以前面的例子可以写成

// define
var MyComponent = 
  template: '<div>A custom component!</div>'

// register
Vue.component('my-component', MyComponent)
// create a root instance
new Vue(
  el: '#example'
)

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

您可以看到,在 Vue v2 的当前文档中,您很少看到 Vue.extends 提及,而在 v1 的文档中,它在描述 Vue Instance 的第一章中明确解释(与 v2 比较)并且非常在Components 章节中有很好的解释。明确指出直接传递选项对象只是sugar。

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

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

是的。

打字稿

如果您想使用 Typescript(并且不喜欢 class-style 组件),那么要进行正确的类型推断,您 should 使用 Vue.extend 而不是普通对象。它使用ThisType&lt;T&gt; feature 来获得this 对象的正确推断。

组件继承(又是 Typescript)

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

<div id="appBar">
    fooMessage || barMessage ||  additionalData
    <button v-on:click="changeAllMessages">Change</button>
</div>
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"  );

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

【讨论】:

哦,很高兴知道您可以使用 Vue.extend 子类化组件!感谢您的解释!【参考方案5】:

理解 Vue.extend 的一个简单方法是创建一个扩展 Vue 类的对象。

通常,要创建一个新的 Vue 实例,

var vm = new Vue( /* ...*/)

Vue.extend 也创建了一个 Vue ie 的实例

var page = Vue.extend ( /* ... */);

page 和上面的 vm 一样是 Vue 的一个实例。

要挂载页面,你必须把它挂载到一个div上,

new page().$mount('#page-div') 

#page-div 是您页面中 div 的 Id

另外,对于具有面向对象编程知识的程序员来说

var ext = Vue.extend(/ *...* /)

那么我们可以将 ext 解释为

class ext extends Vue


请注意,当您创建一个组件时,即Vue.component('my-component', /* ... */ ),它实际上会执行以下操作:Vue.component('my-component', Vue.extend( /* ... */)),因此 Vue.component 会在后台调用 Vue.extend。

如果您仍然感到困惑,请将Vue.extend 视为创建组件的实用函数

【讨论】:

以上是关于Vue.extend 有啥用?的主要内容,如果未能解决你的问题,请参考以下文章

Vue 基础知识之 Vue.extend

vue.extend、 new vue()、component、render

全局配置(Vue.extend( options ))

vue_extend_component

vue -- 组件构造器(extend)

vue中extend,mixins,extends,components,install的几个操作