gtag('config', 'G-0PFHD683JR');
Price Prediction

Vue.js: Publishing like a professional

When you create ingredients for your project, everything begins fun and easy. Create MyButton.vueAdd some design, and Foela.


Then you immediately realize that you need dozens of pillars, because your design team wants to be in different colors and sizes, with icons on the left and right, with the meters …

const props = withDefaults(defineProps<{
  theme?: ComponentTheme;
  small?: boolean;
  icon?: IconSvg; // I’ve described how I cook icons in my previous article
  rightIcon?: IconSvg;
  counter?: number;
}>(), {
  theme: ComponentTheme.BLUE,
  icon: undefined,
  rightIcon: undefined,
  counter: undefined
});

He is still fine. From logical. After all, you cannot get “cancellation” and “OK” buttons of the same color, and you need it to respond to the user reactions. Oh, truth, interactions.

const props = withDefaults(defineProps<{
  theme?: ComponentTheme;
  small?: boolean;
  icon?: IconSvg;
  rightIcon?: IconSvg;
  counter?: number;
  disabled?: boolean;
  loading?: boolean;
}>(), {
  theme: ComponentTheme.BLUE,
  icon: undefined,
  rightIcon: undefined,
  counter: undefined
});

Well, you will get the idea: there will be a wild thing, like traffic width: 100% Or add automatic focus – we all know what it looks simple in Figma until the real life reaches.

Imagine now a link button: it looks as it is, but when you press it, you should go to the external or internal link. You can understand in or Signs every time, but please no. You can also add to and href The pillars of your first component, but you will feel suffocated soon:


Of course, you will need the “second level” component to wrap your button (it will also deal with the outline of virtual hyperlink and some other interesting things, but I will lose sight of them for simplicity):




This is where our story begins.

One

Well, you will work mainly, I will not lie. You can still write And it will be fine. But there will be no automatic completion of the derivative pillars, and it is not great:

only "Href" and "to"only "Href" and "to"

We can silently spread the pillars, but IDE does not know anything about them, and this is a shame.

The direct and clear solution is to spread it explicitly:




It will work. IDE will be the right automatic completion. We will have a lot of pain and remorse for its support.

It is clear that the principle of “do not repeat yourself” has not been applied here, which means that we will need to synchronize each update. One day, you will need to add another pillar, and you will have to find every component surrounding the primary element. Yes, it is likely to be Button and Linkbutton caffeine, but imagine TextINPUT and dozens of ingredients that depend on: Passwordinput, emailput, Numberinput, Dateinput, HellenowsWhatelseinput. Add a pillar that should not cause suffering.

After all, it’s ugly. And more pillars, the more ugly it becomes.

Cleaning

It is very difficult to reuse an unknown type, so let’s give it a name.

// MyButton.props.ts

export interface MyButtonProps {
  theme?: ComponentTheme;
  small?: boolean;
  icon?: IconSvg;
  rightIcon?: IconSvg;
  counter?: number;
  disabled?: boolean;
  loading?: boolean;
}

We cannot export an interface from .vue A file due to some internal script setup Magic, so we need a separate creation .ts file. On the bright side, look at what we have reached here:

const props = withDefaults(defineProps(), {
  theme: ComponentTheme.BLUE,
  icon: undefined,
  rightIcon: undefined,
  counter: undefined,
});

I am clean, right? Here is the inheritance:

interface MyLinkButtonProps {
  to?: RouteLocationRaw;
  href?: string;
}

const props = defineProps();

However, here is a problem: Now, when the basic comments are dealt with MyLinkButtonThe pillars were not published with them v-bind=”$attrs” Next, so we need to do this ourselves.




   
    
  

Everything is good, but we are going a little more than we want:

W3C DisapprovesW3C Disapproves

As you can see, now, the basic button also has a file href Describing. It is not a tragedy, just a little of the additional chaos and peteen, although it is not cold. Let’s clean it too.




Now, we only pass through what it should be passed, but all of these modest craftsmen do not look great, right? This is the most sad story, guys. Let me tell you about it.

Facades for abstract facades

If you have worked with the appropriate languages ​​directed to the objects, you may know about things like reflection, which allows us to obtain identification data about our structures. Unfortunately, in Typescript, fast -disappeared interfaces. It does not exist at the time of operation, and we cannot easily know the fields that belong to MyButtonProps.

This means that we have two options. First, we can keep things as they are: Whenever we add a pillar to MyLinkButtonWe also need to exclude him from propsToPass (Even if we forget that, it is not a big problem).

The second method is to use objects instead of the facades. It may seem meaningless, but allow me to have a symbol: it will not be terrible; I promise you. Well, at least no Which – which terrible.

// MyButton.props.ts

export const defaultMyButtonProps: MyButtonProps = {
  theme: ComponentTheme.BLUE,
  small: false,
  icon: undefined,
  rightIcon: undefined,
  counter: undefined,
  disabled: false,
  loading: false,
};

It is not logical to create an object only to create an object, but we can use it for virtual pillars. Declaration in MyButton.vue It becomes more clean:

const props = withDefaults(defineProps(), defaultMyButtonProps);

Now, we just need to update propsToPass in MyLinkButton.vue:

const propsToPass = computed(() =>
  Object.fromEntries(
    Object.entries(props).filter(([key, _]) =>
      Object.hasOwn(defaultMyButtonProps, key)
    )
  )
);

To make this work, we need to determine everyone explicitly undefined and null Fields in defaultMyButtonProps; Otherwise, the object is not “it.”

In this way, whenever you add a support to the basic ingredient, you will also need to add it to the virtual values ​​object. So, yes, it’s two places again, and perhaps not better than the solution from the previous chapter. It is up to you, which one you will find cleaner.

i’m done

It is not a masterpiece, but it may be the best we can do within the restricctions restrictions.

It also seems that the presence of types of pillars within the SFC file is better, but I cannot say that it is transferred to a separate file made it much worse. But it certainly made it better, so I will consider it a small victory in an endless battle that we call work.

You can find the symbol from this article on GitHub.

Related Articles

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button