Vue.js was created by Evan You and 250+ community lovers.
It’s a very progressive framework for building user interfaces. It consists of an approachable core library that focuses on the view layer only, as well as an ecosystem of supporting libraries that helps you tackle complexity in large Single-Page Applications.
In this post, you will be introduced to watchers — an exciting concept that will help you build mastery in Vue.js.
To achieve accessibility on the web, you need to design pages, tools, and technologies that everyone can use.
Here, ‘everyone’ includes people with auditory, cognitive, neurological, physical, speech, and visual impairments.
Accessibility support is necessary to allow assistive technology like screen readers to interpret web pages and applications. For these technologies to work, developers need to think in terms of accessibility and build accessible applications.
This post is intended for all levels of frontend developers that use Vue.js, so being conversant with beginner concepts and installation processes is not required to understand these concepts.
Here are a few prerequisites you should already have before you start to use Vue CLI 3 through this article.
You will need:
npm uninstall -g vue-cli
Then install the new one:
npm install -g @vue/cli
OR
npm install
While building your presentation inside the template section of your Vue component, you might notice that you can only have one root HTML tag inside the template tag.
Inside of this root HTML tag, you can have as many child nodes as you want, so it is impossible to have more than one root node in a Vue component.
If you opened the project in VS Code, navigate to the src folder, then the components folder, and then open the app.js
file. Your app.js
file should look like this:
<template> <div id="app"> <img alt="Vue logo" src="./assets/logo.png"> <Test msg="Welcome to Your Vue.js App"/> </div> </template> <script> import Test from './components/Test.vue' export default { name: 'app', components: { Test } } </script> <style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>
You can see that the div is the only root node in the template. If you tried to add an extra root node like this:
<template> <span> <div id="app"> <img alt="Vue logo" src="./assets/logo.png"> <Test msg="Welcome to Your Vue.js App"/> </div> <div> <h1>Header inside root node 2</h1> </div> </span> </template> <script> import Test from './components/Test.vue' export default { name: 'app', components: { Test } } </script> <style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>
You’d see that as you save it, Vue compiler will flag an error about having multiple root nodes.
To find a way around this, Vue developers often create an extra (and mostly unnecessary) root wrapper node inside which they can create child nodes to suit their wireframes.
This tag can be a span or a div tag. Most Vue developers use div tags a lot to ensure their code block for a return statement does not lead to errors that break the application.
These extra tags do absolutely nothing except prevent errors.
<template> <span> <div id="app"> <img alt="Vue logo" src="./assets/logo.png"> <Test msg="Welcome to Your Vue.js App"/> </div> <div> <h1>Header inside root node 2</h1> </div> </span> </template> <script> import Test from './components/Test.vue' export default { name: 'app', components: { Test } } </script> <style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>
The problem with this method is that it is not accessible.
Now, according to HTML guidelines, semantics tags like list items should be wrapped with either ordered or un-ordered list tags. Similarly, table items should wrapped by the table tags as their parent tags.
Let’s use the App.vue
component to render a list that we’ll create in the Test.vue
component.
Open your App.vue
file and copy the lines of code below in the template section:
<template> <span> <div id="app"> <img alt="Vue logo" src="./assets/logo.png"> <ol> <Test /> </ol> </div> </span> </template>
Then, in the Test.vue
component, put the list items in the template section like this:
<template> <div> <li>1. Array method</li> <li>2. Extra tag method</li> <li>3. fragments</li> </div> </template>
The code block above will not return errors by the compiler. It would actually be passed into the App.vue
component to render the list correctly.
But if you inspect the elements your dev tools, you will see that it does not return semantic HTML
If this semantic is not followed, your HTML code might work alright, but it won’t be picked up by assistive devices like a screen reader or announcer.
This is why this method (which is widely used) is now frowned upon. Generally, there’s a push to write accessible code.
This concept started when the React team released version 16. It’s the solution to the accessibility gap that has been created by developer behavior.
The team found a way to create an HTML tag that would not read as a node by the DOM and called it fragments.
This works exactly like your div or span tag, but it doesn’t change the overall structure of your code, therefore keeping your DOM tree semantic.
render() { return ( <React.fragment > <ChildA / > <ChildB / > <ChildC / > </React.fragment> ); }
This shows up in the DOM like this:
<ChildA / > <ChildB / > <ChildC / >
Fragments are the invisible wrapper tags that do not affect the node structure of the DOM, thereby achieving accessibility.
The Vue team has not yet built an official fragment feature, but there is a great plugin built by Vue community member Julien Barbay.
This plugin simply acts like a wrapper. Then, on Vue compile, it gets commented out on the DOM.
This is a very efficient way to use fragments in Vue 2.x
The syntax looks like this:
<Fragment > <ChildA / > <ChildB / > <ChildC / > </Fragment>
In the DOM, it renders like this:
<!--Fragment--> <ChildA / > <ChildB / > <ChildC / > <!--Fragment-->
You can see that both lines are commented out so the DOM is semantic and the code is accessible. To use, first install the plugin inside your Vue project:
npm install -s vue-fragment
Then import it and you are ready to use it in your Test.vue
file like this:
<template> <fragment> <li>1. Array method</li> <li>2. Extra tag method</li> <li>3. fragments</li> </fragment> </template> <script> import { Fragment } from 'vue-fragment' export default { name: 'Test', components: { Fragment }, props: { msg: String } } </script>
You can see that the div tag was replaced by the fragment. Now, the whole presentation becomes accessible.
In this post you have learnt how to use fragments in Vue and seen why it’s really important to write code with accessibility in mind.
The Vue team has promised to bring in a fragment feature in the upcoming Vue version 3 release.
The plugin by Julien is a really helpful one, which you can use today.
Happy hacking!
Debugging Vue.js applications can be difficult, especially when there are dozens, if not hundreds of mutations during a user session. If you’re interested in monitoring and tracking Vue mutations for all of your users in production, try LogRocket.
LogRocket is like a DVR for web and mobile apps, recording literally everything that happens in your Vue apps, including network requests, JavaScript errors, performance problems, and much more. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred.
The LogRocket Vuex plugin logs Vuex mutations to the LogRocket console, giving you context around what led to an error and what state the application was in when an issue occurred.
Modernize how you debug your Vue apps — start monitoring for free.
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowLearn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.
Bypass anti-bot measures in Node.js with curl-impersonate. Learn how it mimics browsers to overcome bot detection for web scraping.
Handle frontend data discrepancies with eventual consistency using WebSockets, Docker Compose, and practical code examples.
Efficient initializing is crucial to smooth-running websites. One way to optimize that process is through lazy initialization in Rust 1.80.
3 Replies to "Fragments in Vue.js"
Never heard before of this, just used the div wrapper. Thanks a lot for the the article!
Hi, thank you for the explanation and a point to the vue-fragment library.
I think that it the second example when you want to show the error having multiple root components, you accidentally put the correct solution with span wrapper.
I’m doing end-to-end testing with Laravel Dusk, and using vue-fragment means Dusk can’t see the DOM components when it renders. Any idea how to fix that? Is there a way to register the components in Dusk?
Thanks