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<T>
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(...)
一样。也许它没那么有用,但它表明BarComponent
和FooComponent
只是扩展 基本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 有啥用?的主要内容,如果未能解决你的问题,请参考以下文章