我认为这个功能是故意删除的,但在某些情况下它可能非常有用。 为什么不把这个东西放回去可能使它成为可选的呢?
任何现实世界的用例?
在小型用例中,只需全局注册所有内容; 在大型应用程序中,每个组件显式地依赖于它的需要更易于维护。 它在某些情况下可能有用,但好处是全局权衡。 1.0 背后的理念是“如果某些东西只有一点点有用,或者对可维护性有负面影响,让我们删除它。”
是的。 我的应用程序有一个弹出窗口,其中包含复杂的自定义编辑器元素结构。 这些元素可以组合成 3-4 级的层次结构,从而使为每个父元素显式声明它们效率低下(3-5 个父类型 * 10 个声明的元素 = 50 行重复代码)。 而且,全局注册它们也不好,因为它们永远不会出现在应用程序的其他部分。 所以我想让它们“本地”加载。
显式地导入它们是值得重复的。 它允许您单独查看该层次结构中的任何组件并了解其依赖项的来源。 使用隐式回退,您将不记得 3 个月后在层次结构中导入这些组件的位置。
@yyx990803我记性很好,谢谢。 所以我会记得我的应用程序由两个非常不同的部分组成,每个部分都注册了一组明确定义的特定于它的组件。 所以我更愿意选择在哪里加载我的资产(我怀疑自定义指令和过滤器也发生了同样的事情)。
让我分享一下我的印象。 我使用 0.12.x 并且进展顺利(减去一些小的学习曲线问题)。 简约而干净的 API、语法、可靠的代码。 现在,我们处于 1.0.0-beta 版本,它变得更糟,而不是更好。 更多的代码重复,我使用的功能被删除,让我一遍又一遍地重写相同的代码。 我开始认为我在选择 Vue 而不是 React 时犯了一个错误,因为我不确定将来不会有更多的重大变化和浪费我的时间。
@karevn
strict: true
设为默认值。 口味不同,有些人会更喜欢“后备”方法,这种方法有时更直观。 特别是在动态加载组件时。 它可以使用 mixins、工厂等来解决,但这都需要宝贵的时间。options.strict = true
时,此更改可能不会中断。是的,升级总是伴随着重构的痛苦,但 Vue 1.0 是摆脱这些遗留配置选项的唯一机会。 在 1.0 之后,它将是严格的 semver,并且在 2.0 之前什么都不会中断。 由于您谈到的可靠性问题,我希望 1.x 能够持续尽可能长的时间。
关于严格模式:当你严重依赖它时,它肯定会花费重构时间——但理想情况下,对于在 1.0 之后选择 Vue 的新用户来说,他们甚至不需要知道这个东西的存在。 API 表面应尽可能小,全局结构化模式应尽可能一致。 禁用严格模式本质上鼓励了两种不同风格的 Vue 应用程序结构——想象人们在一个使用strict: true
的应用程序上工作,然后转移到另一个使用strict: false
的项目......它创建开发人员体验的碎片化,我想摆脱这种可能性,而 1.0 是唯一合理的地方。
在此过渡过程中陷入困境对您来说有点不走运,我感谢您的反馈。 但是需要做的事情必须要做。
@yyx990803我可以看到一个我有点坚持的具体用例。
我想要做什么
我构建了一个可扩展的应用程序:可使用小部件进行扩展。 小部件是开发人员定义的应用程序的一部分,它插入全局应用程序以在某些点上对其进行扩展; 它在应用程序启动时动态加载。 应用程序的每个实例都可以有不同的小部件集,并且应用程序的 2 个实例可以存在于同一页面上。
加载时,小部件将向 vuejs 应用程序添加一个动态创建的组件。
小部件可以包含其他小部件(子小部件)。我们不知道它在启动时会如何,因为这部分是在应用程序加载后由用户管理的。 这就是为什么小部件需要相互了解并注册其他小部件的原因。
问题
我想避免全局注册这些小部件(兼容性原因)。
因为组件是动态构建和加载的,所以我需要在每个可以包含子组件的组件中注册所有组件。 这做了很多可能不会使用的注册。 明白我的意思(请注意,目前我没有尝试对组件进行本地注册,而是使用全局注册进行测试):
var components = {
appComponents: {
template: "...",
components: components
},
appComponents2: {
template: "...",
components: components
},
widgetComponents: {
template: "...",
components: components
},
widgetComponents2: {
template: "...",
components: components
},
}
这样做时是否存在性能瓶颈?
这就是为什么我认为“半全局”组件的作用域可能有用。 它可以帮助构建具有封闭组件范围的应用程序,其中组件可以从根组件和子组件访问。 但不是来自其他 vuejs 根。 你怎么认为?
全局注册不递归注册,它只注册
组件本身,而不是其中的components
选项。 所以我猜
没有问题。
2016 年 8 月 22 日星期一 16:00 Soufiane Ghzal [email protected]写道:
@yyx990803 https://github.com/yyx990803我可以看到一个具体的用例
我有点坚持。_我想要做什么_
我构建了一个可扩展的应用程序:可使用小部件进行扩展。 小部件是一个
开发者定义的应用程序,它在
应用程序的启动。 应用程序的每个实例都可以有
不同的小部件集。加载时,小部件将添加一个动态创建的组件到
Vue.js 应用程序。
小部件可以包含其他小部件(子)。,我们不知道它是如何
将在启动时,因为这部分是由用户管理后
应用程序已加载。 这就是为什么小部件需要相互了解的原因。_问题_
我想避免在全局范围内注册这些小部件。
因为小部件是动态加载的,所以我需要在其中注册所有小部件
每个可以包含孩子的小部件。 这做了很多注册
可能不会使用。 看:变量组件 = {
appComponents: { template: "...", components: components }, appComponents2: { template: "...", components: components },
}
_这样做有没有性能瓶颈?_
—
您收到此消息是因为您订阅了此线程。
直接回复此邮件,在 GitHub 上查看
https://github.com/vuejs/vue/issues/1297#issuecomment -241339596,或者静音
线程
https://github.com/notifications/unsubscribe-auth/AFTLl6QDePtH93VOU2lgrC72Z0vKLsv-ks5qiVcXgaJpZM4F7M1v
.
@fnlctrl这与全球注册无关。
问题是
在我看来,问题在于 vue 虽然适用于静态(全局)方式,但它仅限于打包/可分发(本地)方式。
semi-global
注册实际上已经成为可能,因为 Vue 具有原型继承。
https://jsfiddle.net/fnlCtrl/32dt9e9g/
@fnlctrl
我不确定你想用你发送的小提琴显示什么(请注意你的例子有错误: Unknown custom element: <bar> - did you register the component correctly?
)
我不够清楚,也许你没有理解我要解释的内容。 重新开始:
我想解释的是,我们可以:
Vue.component('name', {...})
注册组件(非常适合单页应用程序)new Vue({ components: {...} });
中本地注册一个组件(这样可以很好地发送具有依赖关系的组件以实现本地可重用性)但是我们不能让父组件对子组件可用。 例如为当前vm
实例和在此实例中加载的所有组件注册全局组件,但不为在其他 vm 实例中加载的组件注册。 查看示例: https ://jsfiddle.net/p8wqafm1/2/
你明白吗?
哎呀,似乎我的小提琴没有正确保存..
这是我打算给你看的..
https://jsfiddle.net/fnlCtrl/32dt9e9g/1/
我现在正在阅读您的示例。
我在这里分叉了您的示例
您想在 Foo 中添加受限的动态组件。
@fnlctrl感谢您的示例,但它似乎还没有涵盖我想要实现的目标。
在您的示例中使用该方法仅在Foo
中注册组件,但这不会使它们在Foo
的子项中可用(在此示例中Bar
)。
看小提琴,我在Foo
$ 中注册Baz
#$ 并且我希望它在Bar
中可用,因为它是从Foo
加载的: https://jsfiddle .net/8y0Lmb01/3/
分叉你的例子: https ://jsfiddle.net/fnlCtrl/uvzaotaz/
关键是组件应该有清晰的依赖树,相互依赖的动态组件也不例外。
@fnlctrl在您的示例中Baz
不再在Foo
中可用。
为此,我可以使用Vue.component('baz', {...}
,但问题是它会用这个baz
组件“污染”其他 vue 实例。
或者
我可以在Foo
和Bar
以及所有 foo 孩子、所有 bar 孩子和所有 Foo Grand Children 等中注册Baz
......但这增加了一个大型/动态应用程序的复杂性
你明白我的意思吗? 我可以在本地注册,但我们不能继承当前组件的子、孙、...的组件_only_
是的,我现在明白你的意思了。 抱歉,我不知道注册
Foo 下的组件不会使其在 Foo 的范围内成为全局的,不像
Vue.component 。 将查看源代码以了解原因。
2016 年 8 月 22 日星期一 20:17 Soufiane Ghzal [email protected]写道:
@fnlctrl https://github.com/fnlctrl在你的例子中 Baz 不可用
在 Foo 了。为此,我可以使用 Vue.component('baz', {...} 但问题是
它会用这个 baz 组件“污染”其他 vue 实例。或者
我可以在 Foo 和 Bar 以及所有 foo 孩子中注册 Baz,并且
所有酒吧的孩子,所有的 Foo Grand Children,等等……但这增加了很多
大型/动态应用程序的复杂性你明白我的意思吗? 我可以在本地注册,但我们不能继承
当前组件的子、孙、...的组件
_只要_—
你收到这个是因为你被提到了。
直接回复此邮件,在 GitHub 上查看
https://github.com/vuejs/vue/issues/1297#issuecomment -241395119,或者静音
线程
https://github.com/notifications/unsubscribe-auth/AFTLl2ud0GDO_hOwFN8GIA1TzVEF1q0Fks5qiZM9gaJpZM4F7M1v
.
谢谢 :)
关键是我想发布一个依赖于 vue 的独立库,为给定实例注册组件将是一个真正的好处,因为无论如何,作为一个独立库,我不允许在全局 Vue 实例中注册它(这会破坏独立部分)。
请让我知道我所说的是否可以在 Vue 中实现
好吧,我想原因太明显以至于我忽略了:我不是
使用new Foo()
...
将在 20 分钟内得到小提琴,在我回家的路上。
2016 年 8 月 22 日星期一 20:27 宋铄运[email protected]写道:
是的,我现在明白你的意思了。 抱歉,我不知道注册
Foo 下的组件不会使其在 Foo 的范围内成为全局的,不像
Vue.component 。 将查看源代码以了解原因。2016 年 8 月 22 日星期一 20:17 Soufiane Ghzal [email protected]
写道:@fnlctrl https://github.com/fnlctrl在你的例子中 Baz 不是
Foo 不再可用。为此,我可以使用 Vue.component('baz', {...} 但问题是
它会用这个 baz 组件“污染”其他 vue 实例。或者
我可以在 Foo 和 Bar 以及所有 foo 孩子中注册 Baz,并且
所有酒吧的孩子,所有的 Foo Grand Children,等等……但这增加了很多
大型/动态应用程序的复杂性你明白我的意思吗? 我可以在本地注册,但我们不能继承
当前组件的子、孙、...的组件
_只要_—
你收到这个是因为你被提到了。
直接回复此邮件,在 GitHub 上查看
https://github.com/vuejs/vue/issues/1297#issuecomment -241395119,或者静音
线程
https://github.com/notifications/unsubscribe-auth/AFTLl2ud0GDO_hOwFN8GIA1TzVEF1q0Fks5qiZM9gaJpZM4F7M1v
.
好吧, new Foo(...)
也没有用: https ://jsfiddle.net/8y0Lmb01/5/
确实很奇怪...... https://jsfiddle.net/fnlCtrl/p0ggkncu/
现在调查它。
我已经阅读了一些源代码,发现在 Vue 本身上,我们可以这样破解:
https://jsfiddle.net/fnlCtrl/522aw9sm/
(不使用 Vue.extend 或 Vue.component,顺便说一句,Vue.component 只是一个辅助函数,它执行 Vue.extend 并修改 Vue.options.components)
虽然相同的方法不适用于扩展的 Vue:
https://jsfiddle.net/fnlCtrl/v1m2s16u/
所以我认为问题是由组件分辨率引起的。 我会继续寻找。
@fnlctrl好的,谢谢,我尝试检查一些事情并得出与您相同的结论。 我对核心的了解不够,无法找到它为什么会这样工作。 我们知道这是否是预期的行为吗?
函数体中的代码不看祖先链吧? 也许它还没有实施?
我还不够了解,仍在学习它的行为,但我猜“祖先链”是指第一个参数options
。
我想我可以得出结论,原因是这个 (src/core/global-api/extend) 。
它使扩展类使用与父类相同的方法。
我已经测试过了,如果您复制core/global-api/assets中的内容(当然,使用 dist 版本中的相应代码,该代码已去除类型)
到 vue.extend,使其看起来像这样(将Vue
更改为Sub
):
config._assetTypes.forEach(function (type) {
Sub[type] = function (id, definition) {
if (!definition) {
return this.options[type + 's'][id];
} else {
/* istanbul ignore if */
if ("development" !== 'production') {
if (type === 'component' && config.isReservedTag(id)) {
warn('Do not use built-in or reserved HTML elements as component ' + 'id: ' + id);
}
}
if (type === 'component' && isPlainObject(definition)) {
definition.name = definition.name || id;
definition = Sub.extend(definition);
}
if (type === 'directive' && typeof definition === 'function') {
definition = { bind: definition, update: definition };
}
this.options[type + 's'][id] = definition;
return definition;
}
};
});
Foo = Vue.extend()
和Foo.component()
将起作用。
虽然我猜这会导致一些性能损失。
@gsouf我想我已经找到了拼图的最后一块(无需修改 vue 的等效解决方法):
https://jsfiddle.net/fnlCtrl/v1m2s16u/
var Root = Vue.extend()
Root.options.components.Foo = Root.extend({
template: '<div>Foo</div>'
})
Root.options.components.Bar = Root.extend({
template: '<div>Bar, uses <foo></foo></div>'
})
new Root({
template: `
<div>
<foo></foo>
<bar></bar>
</div>
`
}).$mount('#app')
嗨@fnlctrl ,感谢您的输出,抱歉耽搁了。
确实看起来组件从它们的构造函数继承组件,而不是从它们的父级继承。 目前正在寻找是否可以为我的用例应用补丁。
在您的情况下,它仍然附加到构造函数,而不是实例,我正在寻找它只是实例的一部分
@fnlctrl由于 javascript 的工作方式,并且由于您的示例,我可以通过为我创建的每个实例“动态扩展”vue 来解决它,使所有内容仅可用于此应用程序。:
createVueInstance = function(el, data){
var vExtend = Vue.extend();
vExtend.partial('some-semiglobal-partial', "...");
vExtend.component('some-semiglobal-component', vExtend.extend({...}));
return new vExtend({
el: el,
data: data
});
};
在检查了核心是如何构建的之后,它看起来并不是为了轻松集成每个实例可用的组件而构建的,而且这种解决方法对我来说足够稳定。
谢谢你的帮助!
顺便说一句,我认为您向我展示的示例可以在文档中进行深入解释。 我没有找到关于那个的提及
@gsouf不客气。 我认为这个问题对于那些想要实现类似功能的人来说已经足够了 :smile:
在这里,我有一个“半全局”用例:
我有一个相对通用的 Layout 组件,但内容可以由使用 Layout 组件的组件配置,例如。 组件 A 使用 Layout 并希望使用组件 B 配置其内容,其他一些组件可能使用 Layout 并使用组件 C 配置其内容等。
应该支持这种模式吗?
或者有什么解决方案可以替代这种设计?
该模式在 iOS 中被广泛使用以提高代码重用,这是一种灵活的设计。
@hpsoar您可能需要的是插槽
我的设计如下,基本上这将允许我对单元格做两件事:
<template>
<div class="tile is-ancestor">
<div class="tile is-parent">
<article class="tile is-child box">
<div class="table-responsive">
<table class="table is-bordered is-striped is-narrow">
<thead>
<tr>
<th v-for="c in columns">
{{c.title}}
</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in items">
<template v-for="c in columns">
<td v-if="c.hasOwnProperty('component')"><div :is="c.component"></div></td>
<td v-else>{{ item[c.name] }}</td>
</template>
</tr>
</tbody>
</table>
</div>
</article>
</div>
</div>
</template>
<script>
export default {
components: {
},
props: [
'columns',
'items'
],
data: function () {
return {
}
}
}
</script>
<style lang="scss" rel="stylesheet/scss">
.table-responsive {
display: block;
width: 100%;
min-height: .01%;
overflow-x: auto;
}
</style>
最有用的评论
显式地导入它们是值得重复的。 它允许您单独查看该层次结构中的任何组件并了解其依赖项的来源。 使用隐式回退,您将不记得 3 个月后在层次结构中导入这些组件的位置。