📜 ⬆️ ⬇️

Dark day for Vue.js


Today I was amazed at how normally the positive and friendly community of Vue.js rolled into a sad confrontation. Two weeks ago, Vue creator Evan Yu published a proposal (RFC) with a new functional API for components in the upcoming Vue 3.0. Today, a critical discussion on Reddit and similar comments on Hacker News have caused an influx of developers in the original RFC with outrage, sometimes even too sharp.


It stated about the following:



After a wall of negative comments on Reddit, it is surprising that the discussion of the RFC itself contains mostly positive reactions, especially among the first comments. In fact, the very first comment is full of enthusiasm.


I was the person who wrote this first comment. It turned out that I received a notification about the new RFC, immediately read it and found that this is exactly what I would like from Vue 3.0 and wrote a comment about it within 15 minutes after the RFC was published, to express my gratitude. In this post I hope to reveal this topic, why I consider the new API such a good idea. But first, allow me to respond to the statements of critics.


I suspect that many people have stirred up after reading Hacker News or Reddit, where there were a lot of inaccurate comments, misleading, but they did not read the original sentence . Evan has already added a question and answer section that answers most questions:



There was still a somewhat subjective point about the fact that the new syntax generates less structured code. I want to demonstrate this with a simple example that explains why I’m so excited about the RFC and why I think the new approach will lead to more structured code.


Provide a component that gives the user to enter information about your pet and is updated as data is entered. Wherein:




Component appearance


You can see a live demo with a component here and also see the source code for Vue 2.x right here (the components / Vue2.vue file).


Consider the Javascript part of this component:


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"; } } } 

In principle, we have some data and various properties calculated from this data. Notice that in Vue 2.x there is no way to put related things together. We cannot place the petColor ad next to the calculated petColorDarker , because in Vue 2.x they are grouped by type.


Of course, for such a small example it is not very important. But imagine a bigger example in which there are pieces of functionality with the necessary data, calculated properties, methods, and even with a couple of watches. There is no good way to combine related entities together! Some might think of mixins or higher-order components, but they have problems — it's hard to see where these properties come from, and there are problems with name conflicts.


The new syntax suggests the organization of the components by related functionality, instead of the value type. This is similar to how you organize files on your computer - usually you do not make separate folders "excel-tables" and "word-documents", rather there will be folders "work" or "vacation planning". Let's imagine what our component will look like in the proposed new syntax (as far as it’s possible to run the code, let me know if you find any bugs):


  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 }; } 

Notice, that:



In addition, the new syntax provides full Typescript support, which was difficult to achieve in the Vue 2.x object syntax. And we can refactor our logic by transferring to reusable functions. Something like this:


 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 }; } }; 

In Vue 2.x, I often found that I was writing a “monstrous component” that is difficult to break into small pieces — it cannot be divided into smaller components, because too much is happening based on a small number of state variables. However, with the new proposed syntax, you can see that you can easily separate the logic from large components into separate pieces, put them into separate files, if necessary, by obtaining small and easy to understand functions and components.


Did Vue have a darker day? Most likely no. The former community around the project has split. But I have a hope that people will look again at the RFC, which breaks nothing, because it allows people to still group entities by type, if they like it, but also allows much more - cleaner and cleaner code, more opportunities for libraries and full Typescript support.


And finally, when using open source, it would be nice to remember that its developers put a lot of effort into what you get for free. The overly harsh criticism that we see today is not what suits us. Fortunately, disrespectful comments were in the minority (albeit significant), and the majority were able to express themselves in a more appropriate tone.


')

Source: https://habr.com/ru/post/457250/


All Articles