The announcement of Vue v2.5 came with much buzz to the Vue community and many improvements to Vue. One of these is the improved support for functional components in Vue. In this article, we will be cleaning up Vue components without state and instances (this) with functional components.
Functional components are an alternative to the widely used Vue components. They use either render functions or are JSX components without state and instance. This means they have no data
property or an instance of this
. Functional components are functions.
Functional components are cleaner and easier to render. This is how a simple functional component looks:
https://gist.github.com/00d85ffb8851ec401952be8cd59e92e7
Note: Props in functional components may not be specified, in which case all props are received from the component’s node.
When using functional components, the context argument is introduced to make-up for the lost state and instance.
One may wonder why we have children
as well as slot
. This is because context.children
refers to all child elements of the node whereas slots().foo
refers to all slots with the name foo, and slots().default
refers to all child element except named slots. These give us the flexibility to choose ways to target child elements. Let’s look at a simple conversion from a stateful component to a stateless on using functional component.
Let’s create a simple generic header, which can be used throughout a Vue instance. Headers are from h1 through to h6. From a stateful component perspective:
https://gist.github.com/7a6399bdbd82dd23a0126f0c36f5f34e
See a codepen demo here https://codepen.io/Chuloo/pen/aLexEe
In our stateful header, the createElement()
function is used to create the header passing it arguments of the level props and the $slots.default
instance for any child node. Since we have no data
from this component, let’s make this cleaner by making it a functional component, thereby eliminating all instances of this
and introducing the context
argument to handle props.
https://gist.github.com/feefc104ad8c7c6fa2818b62c2da5f51
See a codepen demo here https://codepen.io/Chuloo/pen/boXZxw
Notice how this.level
is replaced with context.props.level
and this.$slots.default
is replaced with context.children
.
From Vue v2.5, functional components defined by single-file components can have the functional
attribute in the template tags. This denotes the component as a functional one, eliminates the need to specify the functional property in <script> and the component is treated outright as a functional component.
Also, functional components have CSS in scope as well as hot-reloading features. I built a simple Vue project using the webpack-simple template to show a sample functional component.
It is assumed that you have node and npm installed.
Vue ships with a wonderful CLI for building applications fast, using npm install Vue with:
https://gist.github.com/4502fad144f76e8f266ddac141c6119b
A new project with the webpack-simple template is created using:
https://gist.github.com/f93d32bc47368968ae3853a50d693270
A simple Vue project is created and the command:
https://gist.github.com/6e89463140e8b0b072570de6a084bbf9
serves the Vue project on a development server on Localhost:8080.
In the project folder, we create a file named Header.vue in /src/components/
and edit it to:
https://gist.github.com/9f4c6dcc889ed04792cb7214328faa7b
This is our functional component. Note the absence of the props object? This is because the props object is passed explicitly from the components node. In App.vue located in /src/
wipe all the data provided by our template and edit it to:
https://gist.github.com/c3349ae8abdc999756f34bbce4a61ecd
This is our parent Vue template, the app is built here.
Now run:
https://gist.github.com/87f024b0cbee50c83861dd5e19f899f6
The browser displays:
The app can be styled anyway, either the component is styled and the scoped
attribute is used on the style tags as seen above to ensure that the styling is scoped to solely the component in view.
Functional components are used because they are lighter and cheaper to render by the browser. Instead of using JSX or render functions, they are stateless and have no instance. With the release of v2.5 of Vue, functional components can now possess scoped styling as well as hot-reloading features as we have seen in the simple demo above.