Vue.js的黑暗日子


今天,我对通常积极友好的Vue.js社区如何陷入悲伤的冲突感到惊讶。 两周前,Vue的创建者Ewan Yu发布了一个提案 (RFC),其中包含即将发布的Vue 3.0中组件的新功能API。 今天, 对Reddit严格讨论和对Hacker News的类似评论已引起开发人员大为恼火,有时甚至过于苛刻地涌入原始RFC。


它声明如下内容:


  • 所有Vue代码都必须以全新的方式重写,因为现有语法将被删除
  • 人们花在学习Vue上的所有时间原来都是徒劳的,因为一切都会改变
  • 事实证明,新语法比旧语法差,没有给出清晰的结构并生成意大利面条代码
  • Vue团队在未咨询任何人的情况下进行了重大更改
  • Vue变成了React!
  • 还是不行,在AngularJS / Angular中!
  • 现在必须将所有HTML编写成一行!

在对Reddit提出负面评论之后,令人惊讶的是RFC本身的讨论包含了大部分积极的反应,尤其是在最初的评论中。 实际上,第一个评论充满了热情。


我是撰写此第一条评论的人。 事实证明,我收到有关新RFC的通知,立即阅读并发现这正是我从Vue 3.0中获取的信息,并在RFC发布后15分钟内对此发表了评论,以表示感谢。 在这篇文章中,我希望揭示这个主题,为什么我认为新的API是一个好主意。 但首先,让我回答批评者的言论。


我怀疑许多人在阅读Hacker News或Reddit之后会感到尴尬,那里有许多不可靠的评论具有误导性,但没有阅读原文 。 Evan已经添加了一个问答部分,可以回答大多数问题:


  • 如果您不愿意,则无​​需从头开始重写任何内容-新语法是一种补充,而旧语法将在整个Vue 3.0中始终存在,直到被积极使用为止。 即使最终从主代码中删除了该代码, 也可以使用plugins轻松将其返回
  • 学习Vue的时间不会浪费-在新语法中,熟悉的概念(如单文件组件,模板和本地样式)的工作方式与以前相同。
  • 未经讨论就没有进行更改-此RFC是讨论。 新语法离最终版本还差得很远。
  • 不,HTML不必像巨大的字符串一样编写

关于新语法生成的结构化代码较少的事实,有些主观的观点。 我想用一个简单的示例来说明这一点,该示例将解释为什么我如此热衷于RFC,以及为什么我认为新方法将导致结构化代码的产生


想象一下一个组件,该组件允许用户输入有关其宠物的信息,并在您输入数据时进行更新。 在这种情况下:


  • 标题文本会根据宠物的名称进行更新。
  • 笔触的颜色取决于所选的动物颜色,包括阴影,其阴影是根据所选的颜色计算出来的。
  • 标题字体大小和笔画样式取决于用户选择的动物大小


组件外观


您可以在此处查看带有该组件的实时演示,还可以在此处查看Vue 2.x的源代码(文件组件/ Vue2.vue)。


考虑一下此组件的Javascript部分:


data() { return { petName: "", petColor: "#000", petSize: "" }; }, computed: { header: function() { if (this.petName) { return "My Pet " + this.petName; } return "Enter Pet Details"; }, petColorDarker: function() { return tinycolor(this.petColor) .darken() .toString(); }, shadow: function() { return "2px 2px " + this.petColorDarker; }, borderStyle: function() { switch (this.petSize) { case "Small": return "dotted"; case "Medium": return "dashed"; default: return "solid"; } }, headerSize: function() { switch (this.petSize) { case "Small": return "12px"; case "Large": return "60px"; default: return "30px"; } } } 

基本上,我们有某种数据和根据该数据计算出的各种属性。 请注意,在Vue 2.x中,无法将相关内容放在一起。 我们不能在计算的petColorDarker旁边放置petColor ,因为在Vue 2.x中它们是按类型分组的。


当然,对于这么小的例子,这不是很重要。 但是,请想象一个更大的示例,其中包含一些功能,这些功能具有必要的数据,计算出的属性,方法,甚至还有几个观察者。 现在没有将相关实体组合在一起的好方法! 有人可能会想到mixin或高阶组件,但它们有问题 -很难看到这些属性的来源,并且还存在名称冲突问题。


新语法通过相关功能而不是值类型来提供组件的组织。 这类似于您在计算机上组织文件的方式-通常,您不会为excel表和Word文档创建单独的文件夹,而是会有诸如工作或假期计划之类的文件夹。 让我们想象一下我们的组件在建议的新语法中将是什么样的(如果没有运行代码的能力,它将发生多少—如果您发现任何错误,请告诉我):


  setup() { // Pet name const petName = value(""); const header = computed(() => { if (petName.value) { return "My Pet " + petName.value; } return "Enter Pet Details"; }); // Pet color const petColor = value("#000"); const petColorDarker = computed(() => { return tinycolor(petColor.value) .darken() .toString(); }); const shadow = computed(() => "2px 2px " + petColorDarker.value); // Pet size const petSize = value(""); const borderStyle = computed(() => { switch (petSize.value) { case "Small": return "dotted"; case "Medium": return "dashed"; default: return "solid"; } }); const headerSize = computed(() => { switch (petSize.value) { case "Small": return "12px"; case "Large": return "60px"; default: return "30px"; } }); // All properties we can bind to in our template return { petName, header, petColor, shadow, petSize, borderStyle, headerSize }; } 

注意:


  • 将相关实体组合在一起非常简单。
  • 查看设置函数的返回值,我们立即看到我们可以在模板中访问的内容。

另外,新语法提供了对Typescript的完全支持,而Vue 2.x的对象语法很难实现。 我们可以通过将逻辑转移到可重用的函数来重构逻辑。 像这样:


 function usePetName() { const petName = value(""); const header = computed(() => { if (petName.value) { return "My Pet " + petName.value; } return "Enter Pet Details"; }); return { petName, header }; } function usePetColor() { const petColor = value("#000"); const petColorDarker = computed(() => { return tinycolor(petColor.value) .darken() .toString(); }); return { petColor, petColorDarker }; } function petSizeToBorderStyle(sizeWrapper) { const borderStyle = computed(() => { switch (sizeWrapper.value) { case "Small": return "dotted"; case "Medium": return "dashed"; default: return "solid"; } }); return { borderStyle }; } function petSizeToHeaderSize(petSizeWrapper) { const headerSize = computed(() => { switch (petSizeWrapper.value) { case "Small": return "12px"; case "Large": return "60px"; default: return "30px"; } }); return { headerSize }; } export default { setup() { const { petName, header } = usePetName(); const { petColor, petColorDarker } = usePetColor(); const shadow = computed(() => "2px 2px " + petColorDarker.value); const petSize = value(""); const { borderStyle } = petSizeToBorderStyle(petSize); const { headerSize } = petSizeToHeaderSize(petSize); return { petName, header, petColor, shadow, petSize, borderStyle, headerSize }; } }; 

在Vue 2.x中,我经常发现我正在编写一个很难分解成小块的“怪异组件”-它不能分为较小的组件,因为基于少量状态变量发生了太多事情。 但是,使用提出的新语法,可以看出,可以通过获取小型且易于理解的功能和组件,轻松地将大型组件中的逻辑提取到单独的片段中,并将其放入单独的文件中。


Vue是否度过了黑暗的一天? 很有可能不会。 项目周围的前社区分裂了。 但我希望人们能再次看一下RFC,它不会破坏任何内容,因为它允许人们根据自己的喜好仍然按类型对实体进行分组,而且还允许使用更多的内容-更易理解和简洁的代码,以及更多的选择。库和完整的Typescript支持。


最后,使用开源时,最好记住它的开发人员为您免费获得的东西付出了很多努力。 我们今天看到的过于苛刻的批评并不适合我们。 幸运的是,少数人(尽管很重要)发表了不敬的评论,并且大多数人能够以更恰当的语气表达自己。

Source: https://habr.com/ru/post/zh-CN457250/


All Articles