Vue Slots Jsx

broken image


This page assumes you've already read the Components Basics. Read that first if you are new to components.

  1. Vue Scoped Slots Jsx
  2. Vue V-slot Jsx
  3. Vue Slot Jsx

Slot Content

If you use Vue version above 2.6.0, Vue introduces new unified slot api, which is v-slot. It replaces the slot and slot-scope attributes, which are deprecated, but have not been removed and are still documented here. You can refer to deprecated API here. # Slots (Default). The slot and slot-scope attributes will continue to be supported in all future 2.x releases, but are officially deprecated and will eventually be removed in Vue 3. Named Slots with the slot Attribute. Deprecated in 2.6.0+. See here for the new, recommended syntax.

如果不理解 slot 概念请先阅读Vue slot教程 Vue 基于 Web Components 规范草案,将 slot 元素作为承载分发内容的出口。 又根据是否需要需要获取上下文,分类为了slot和scopedSlots两者的异同点相同的部分. I've created a global components extending Bootstrap Vue Table component to made a custom template for each table named VTable. The Bootstrap Vue Table component have possibility to use named slots to customize the data rendering. Having both children and slots therefore allows you to choose whether this component knows about a slot system or perhaps delegates that responsibility to another component by passing along children. Template Compilation. You may be interested to know that Vue's templates actually compile to render functions.

Vue implements a content distribution API that's modeled after the current Web Components spec draft, using the element to serve as distribution outlets for content.

This allows you to compose components like this:

Then in the template for , you might have:

When the component renders, the element will be replaced by 'Your Profile'. Slots can contain any template code, including HTML:

Or even other components:

If did not contain a element, any content passed to it would simply be discarded.

Named Slots

There are times when it's useful to have multiple slots. For example, in a hypothetical base-layout component with the following template:

For these cases, the element has a special attribute, name, which can be used to define additional slots:

To provide content to named slots, we can use the slot attribute on a element in the parent:

Or, the slot attribute can also be used directly on a normal element:

There can still be one unnamed slot, which is the default slot that serves as a catch-all outlet for any unmatched content. In both examples above, the rendered HTML would be:

Default Slot Content

There are cases when it's useful to provide a slot with default content. For example, a component might want the content of the button to be 'Submit' by default, but also allow users to override with 'Save', 'Upload', or anything else.

To achieve this, specify the default content in between the tags.

If the slot is provided content by the parent, it will replace the default content.

Compilation Scope

When you want to use data inside a slot, such as in:

That slot has access to the same instance properties (i.e. the same 'scope') as the rest of the template. The slot does not have access to ‘s scope. For example, trying to access url would not work. As a rule, remember that:

Everything in the parent template is compiled in parent scope; everything in the child template is compiled in the child scope.

Scoped Slots

New in 2.1.0+

Sometimes you'll want to provide a component with a reusable slot that can access data from the child component. For example, a simple component may contain the following in its template:

But in some parts of our app, we want the individual todo items to render something different than just the todo.text. This is where scoped slots come in.

To make the feature possible, all we have to do is wrap the todo item content in a element, then pass the slot any data relevant to its context: in this case, the todo object:

Now when we use the component, we can optionally define an alternative for todo items, but with access to data from the child via the slot-scope attribute:

In 2.5.0+, slot-scope is no longer limited to the element, but can instead be used on any element or component in the slot.

Destructuring slot-scope

The value of slot-scope can actually accept any valid JavaScript expression that can appear in the argument position of a function definition. This means in supported environments (single-file components or modern browsers) you can also use ES2015 destructuring in the expression, like so:

This is a great way to make scoped slots a little cleaner.

← Custom EventsDynamic & Async Components →
Phát hiện lỗi hoặc muốn đóng góp vào nội dung? Chỉnh sửa trang này trên GitHub!

Vue.js has an easy API and several options for defining HTML templates in our components.

We can use the tag option, define a template property on our root component instance, or use Single-File components.

The options above are awesome and work perfectly, but, there comes a time in the lifecycle of your application where they either feel clunky, over-engineered or very inflexible.

Table of Contents

So, why would we want to JSX instead of any of the other template definitions?

  • JSX is easy to read.
    ...
    is subjectively better than this.$createElement('div', {}, [...])
  • Seriously, It's just JavaScript.
  • Vue has support for JSX.
  • JSX makes custom Vue components easier to import and manage.

A quick intro

Let me give you an example of why JSX is good.

We want to build a component that can either be a normal single-line text input or a multiline input (textarea). Our template declaration might look like this.

As you can see from the snippet above, we'll quickly run into a few problems like duplicate code and many more. Imagine having to support a variety of properties on the input. This little snippet above will grow and be a nightmare to maintain.

To fix this, we need to go low-level with Vue. We need to get closer to Vue's internal API to fix this mess.

The render() method

NOTE: I'm not saying that the there's not a simple way or ways to handle the above problem without JSX, all I'm saying is that moving this logic to the render() method with JSX in tow can make for a more intuitive component. Keep reading to find out why?

Every component we create in Vue has a render method. This is where Vue chooses to render the component. Even if we don't define this method, Vue will do it for us.

This means that when we define HTML templates in Vue — Vue's template compiler compiles it to a createElement function that takes a couple parameters and returns the result from the render function.

To fix the code in the previous section, we remove the template property or the template tag and define a render() method on the component. If the render method is defined on a component, Vue will ignore the template definition.

The above code does a few things:

  1. The render method takes a createElement helper from Vue.
  2. We programmatically define our tag.
  3. Then we create the tag and pass its attributes, classes etc as an object. There are quite a few options we can pass to createElement.
  4. We return the newly created element for rendering.

Note:Every template we define for a Vue component will be converted into a render method that returns a createElement function. It's because of this reason the render method will take precedence over a template definition.

Take this example:

The template compiler will convert the HTML above into:

Okay! now you might ask this question, 'Isn't this bad for readability?' The answer is yes. Once you define a component with many levels of elements nesting or has several sibling elements — we run into a new problem. We just sacrificed readability. Like they say, 'we've moved from the frying pan to fire.'

Cue JSX. This is where we'll have JSX bring back the readability we lost.

What is JSX

If you already know about JSX, feel free to skip to the next section where I'll show you how to use JSX in Vue.

JSX is a term coined by Facebook's engineering team.

JSX is an XML-like syntax extension to JavaScript without any defined semantics.

JSX is NOT intended to be implemented by engines or browsers. Instead, we'll use transpilers like Babel to convert JSX to regular JavaScript.

Basically, JSX lets us use an HTML-like syntax in JavaScript.

Unfortunately, this article assumes you already know JSX, so teaching JSX is beyond the scope of this article. I'll still point you in the right direction. JSX is very easy to grok and can be done in a couple minutes.

Use these links to learn The basics of JSX, Learn JSX in-depth, finally, if you really want to know about the specification that is JSX, visit its official website.

Configure Vue to use JSX

Vue Scoped Slots Jsx

If you use Vue-cli greater or equal to version 3.0 you are in luck as JSX is supported.

If you are using an older version of Vue-cli that doesn't support JSX, you can add it by installing babel-preset-vue-app and add it to your .babelrc file.

To install:

In you .babelrc file, all you have to do is:

There, we can now use JSX in our component's render function.

Vue's JSX syntax gotchas

There are few gotchas to using JSX in Vue.

First, you can no longer use the : and @ shortcuts for binding and listening to events. They are invalid JSX syntax and your code won't compile.

To listen for events in JSX, we need the 'on' prefix. For example, use onClick for click events.

To modify events, use:

To bind a variable, instead of : use:

To set HTML string as the content of an element, instead of v-html use:

We can also spread a large object.

Using JSX in render

Going back to our initial 'TextField' component. Now that we have JSX enabled in our Vue app, we can now do this.

Importing Vue JSX Components

Vue Slots Jsx

Another benefit to using JSX in Vue is that we no longer have to register every component we need. We just import and use.

How to make JSX work with TypeScript

TypeScript is used as a mechanism that adds type-checking to JavaScript. You can read more.

To add JSX support to TypeScript all we need to do is modify our tsconfig.json.

To enable JSX in TypeScript, first save the file as a .tsx file and modify your tsconfig.json to include:

Setting the jsx option to 'preserve' means that TypeScript should not process the JSX. Doing this lets Babel take control of everything JSX and TypeScript stick to types as it does not yet support Vue JSX. You can learn more.

Then create a jsx.d.ts file in your project and add the TypeScript JSX declarations for Vue.

Make sure that TypeScript can load the declaration file. Or, you can add autoloading for it in tsconfig.json via:

Conclusion

That's it for today. Enjoy having some or all of your Vue.js templates in JSX.

Vue V-slot Jsx

And, please no complaints about JSX breaking SOC (separation of concerns), I can't take another one of those arguments. If you prefer using the createElement function with objects by all means enjoy!!

Vue Slot Jsx

Let me know your thoughts and suggestions in the comments.

Cheers!

Like this article?Follow @KayandraJT on Twitter

Read next...





broken image