Bembew Programming
Home Topics Guides
Bembew Programming
Home Topics Guides

HTML Basics Learning Guide

HTML Basics Learning Guide
    • A Comprehensive Guide to HTML Tags
    • Configuring the head in VuePress
    • Controlling Access with the `meta` Attribute in Advanced Vue Router Scenarios
    • Distributed IDs
    • Text Tags: Title, Paragraph, Link
    • Image Tags: img and Image Attributes
    • List Tags: Unordered Lists and Ordered Lists
    • Table Tags: Tables, Rows, and Cells
    • Form Labels: Input Fields, Text Areas, and Buttons
    • The Role of the Tag</a></li> <li><a href="/en/article/content-inside-the-body-tag.html?guide-code=html" class="sidebar-article-link">Content Inside the <body> Tag</a></li> <li><a href="/en/article/using-the-header-tag.html?guide-code=html" class="sidebar-article-link">Using the <header> Tag</a></li> <li><a href="/en/article/using-the-nav-tag.html?guide-code=html" class="sidebar-article-link">Using the <nav> Tag</a></li> <li><a href="/en/article/using-the-main-tag.html?guide-code=html" class="sidebar-article-link">Using the <main> Tag</a></li> <li><a href="/en/article/using-the-article-tag.html?guide-code=html" class="sidebar-article-link">Using the <article> Tag</a></li> <li><a href="/en/article/using-the-aside-tag.html?guide-code=html" class="sidebar-article-link">Using the <aside> Tag</a></li> <li><a href="/en/article/using-the-footer-tag.html?guide-code=html" class="sidebar-article-link">Using the <footer> Tag</a></li> <li><a href="/en/article/using-the-class-attribute-in-html.html?guide-code=html" class="sidebar-article-link">Using the class Attribute in HTML</a></li> <li><a href="/en/article/using-the-style-attribute-in-css.html?guide-code=html" class="sidebar-article-link">Using the style Attribute in CSS</a></li> <li><a href="/en/article/using-the-src-attribute.html?guide-code=html" class="sidebar-article-link">Using the src Attribute</a></li> <li><a href="/en/article/using-the-href-attribute.html?guide-code=html" class="sidebar-article-link">Using the href Attribute</a></li> <li><a href="/en/article/secure-usage-of-the-html5-canvas-element.html?guide-code=html" class="sidebar-article-link">Secure Usage of the HTML5 Canvas Element</a></li> <li><a href="/en/article/css-selectors.html?guide-code=html" class="sidebar-article-link">CSS Selectors</a></li> <li><a href="/en/article/mobile-adaptation.html?guide-code=html" class="sidebar-article-link">Mobile Adaptation</a></li> <li><a href="/en/article/image-optimization.html?guide-code=html" class="sidebar-article-link">Image Optimization</a></li> <li><a href="/en/article/installing-and-configuring-node-js-for-nuxt-js-vue-react-next-js-rust-mongodb-sql-vuex.html?guide-code=html" class="sidebar-article-link">Installing and Configuring Node.js for Nuxt.js, Vue, React, Next.js, Rust, MongoDB, SQL, Vuex</a></li> <li><a href="/en/article/html5-overview.html?guide-code=html" class="sidebar-article-link">HTML5 Overview</a></li> <li><a href="/en/article/semantic-html5-tags.html?guide-code=html" class="sidebar-article-link">Semantic HTML5 Tags</a></li> <li><a href="/en/article/form-elements-input-textarea-select.html?guide-code=html" class="sidebar-article-link">Form Elements (Input, Textarea, Select)</a></li> <li><a href="/en/article/multimedia-elements-audio-and-video.html?guide-code=html" class="sidebar-article-link">Multimedia Elements (Audio and Video)</a></li> <li><a href="/en/article/html5-form-structure.html?guide-code=html" class="sidebar-article-link">HTML5 Form Structure</a></li> <li><a href="/en/article/form-validation-required-minlength-maxlength.html?guide-code=html" class="sidebar-article-link">Form Validation (required, minlength, maxlength)</a></li> <li><a href="/en/article/custom-form-validation.html?guide-code=html" class="sidebar-article-link">Custom Form Validation</a></li> <li><a href="/en/article/client-side-and-server-side-validation.html?guide-code=html" class="sidebar-article-link">Client-Side and Server-Side Validation</a></li> <li><a href="/en/article/using-audio-and-video-tags.html?guide-code=html" class="sidebar-article-link">Using Audio and Video Tags</a></li> <li><a href="/en/article/controlling-the-video-player.html?guide-code=html" class="sidebar-article-link">Controlling the Video Player</a></li> <li><a href="/en/article/html5-animation-with-canvas-api.html?guide-code=html" class="sidebar-article-link">HTML5 Animation with Canvas API</a></li> <li><a href="/en/article/overview-of-responsive-design.html?guide-code=html" class="sidebar-article-link">Overview of Responsive Design</a></li> <li><a href="/en/article/the-viewport-tag-in-html.html?guide-code=html" class="sidebar-article-link">The Viewport Tag in HTML</a></li> <li><a href="/en/article/media-queries.html?guide-code=html" class="sidebar-article-link">Media Queries</a></li> <li><a href="/en/article/responsive-design.html?guide-code=html" class="sidebar-article-link">Responsive Design</a></li> <li><a href="/en/article/ui-design-principles.html?guide-code=html" class="sidebar-article-link">UI Design Principles</a></li> <li><a href="/en/article/combining-html-and-css.html?guide-code=html" class="sidebar-article-link">Combining HTML and CSS</a></li> <li><a href="/en/article/essential-web-design-techniques.html?guide-code=html" class="sidebar-article-link">Essential Web Design Techniques</a></li> <li><a href="/en/article/canvas-api.html?guide-code=html" class="sidebar-article-link">Canvas API</a></li> <li><a href="/en/article/svg-graphics.html?guide-code=html" class="sidebar-article-link">SVG Graphics</a></li> <li><a href="/en/article/accessibility-testing.html?guide-code=html" class="sidebar-article-link">Accessibility Testing</a></li> </ul> </li> </ul> </div> </div> </aside> <main class="main-content sidebar-content toc-content"> <div class="article-content"> <nav class="breadcrumb-nav" aria-label="breadcrumb"> <ol class="breadcrumb"> <li class="breadcrumb-item"><a href="/en/guide/index.html">Guides</a></li> <li class="breadcrumb-item"><a href="/en/guide/html.html">HTML Basics Learning Guide</a></li> <li class="breadcrumb-item active">Controlling Access with the `meta` Attribute in Advanced Vue Router Scenarios</li> </ol> </nav> <h1>Controlling Access with the `meta` Attribute in Advanced Vue Router Scenarios</h1> <div class="article-body"><p>In advanced Vue Router applications, route configuration serves not only as the definition of navigation structures but also acts as the first line of defense in building secure systems. Traditional "whitelist" or global guard patterns often struggle to handle complex business scenarios, such as the need for differentiated display when users with different roles access the same resource. In such cases, introducing the <code>meta</code> attribute for fine-grained access control becomes the best practice for addressing this issue. This article delves into how to leverage Vue Router's metadata mechanism combined with route guards to implement an efficient and scalable permission verification solution.<br>The <code>meta</code> is a key property within the route configuration object used to store additional information unrelated to routing behavior. In the context of access control, we typically define a boolean field (such as <code>requiresAuth</code>) or a string array (such as <code>roles</code>) within the <code>meta</code> to indicate whether a page requires login and which roles are allowed to access it.</p> <p>Below is a standard Vue Router configuration example demonstrating how to add permission markers to specific routes:</p> <pre><code class="language-javascript">const routes = [ { path: '/dashboard', name: 'Dashboard', component: () => import('@/views/Dashboard.vue'), meta: { requiresAuth: true, // Authentication must be verified roles: ['admin', 'user'] // List of allowed roles } }, { path: '/profile', name: 'Profile', component: () => import('@/views/Profile.vue'), meta: { requiresAuth: true, roles: ['admin'] // Only accessible by administrators } }, { path: '/', name: 'Home', component: () => import('@/views/Home.vue') } ] </code></pre> <p>By doing so, we decouple business logic from the route structure. The <code>meta</code> object acts as a "metadata label" for routes, allowing us to flexibly define access policies without modifying the core Vue Router code.</p> <h2 id="building-global-permission-guards">Building Global Permission Guards</h2> <p>Once metadata markers are established, we need to implement logic at the application level to check these markers. Typically, we create a generic permission checking function and execute the route guard within the <code>beforeEach</code> hook.</p> <p>First, define a helper function to determine if the current user has the right to access a specific route:</p> <pre><code class="language-javascript">// utils/permission.js export function hasPermission(routeMeta) { if (!routeMeta.roles || routeMeta.roles.length === 0) { return true // Default allow if no role restrictions are set } const userRoles = ['admin', 'user']; // Assume the current user possesses these roles return userRoles.some(role => routeMeta.roles.includes(role)); } </code></pre> <p>Next, introduce Vue Router's navigation guard mechanism in <code>main.js</code> or the route configuration file. We need to intercept all requests and check if the target route has permission requirements set:</p> <pre><code class="language-javascript">import { createRouter, createWebHistory } from 'vue-router' import { hasPermission } from '@/utils/permission' const router = createRouter({ history: createWebHistory(), routes: [/* ... route definitions */] }) router.beforeEach((to, from, next) => { // Check if authentication is required if (to.meta.requiresAuth) { const isAuthenticated = true; // Real authentication logic should be called here if (!isAuthenticated) { next({ path: '/login', query: { redirect: to.fullPath } }) return } } // Check role permissions if (to.meta.roles && !hasPermission(to.meta)) { next({ name: '403' }) // Redirect to unauthorized page return } next() }) </code></pre> <p>This code demonstrates the core logic: first, it checks if mandatory authentication is required; if not logged in, it redirects to the login page. Second, it checks the role list; if the current user's role is not in the allowed list, it returns a 403 error code. This layered checking mechanism ensures the rigor of access control.</p> <h2 id="handling-special-scenarios-and-exception-flows">Handling Special Scenarios and Exception Flows</h2> <p>In actual development, access control is not a simple binary judgment but requires consideration of edge cases. For example, how should the system handle a situation where a user attempts to access a completely undefined route? Or, when user roles change dynamically (e.g., fetched via backend APIs), how can data consistency be guaranteed?</p> <p>For undefined routes, Vue Router triggers a 404 error by default. We can create a custom 403 page to uniformly handle permission denial scenarios, avoiding the exposure of specific error information to users. Additionally, to support dynamic roles, it is recommended to asynchronously fetch the user's latest role information within the <code>beforeEach</code> hook rather than hardcoding them at startup:</p> <pre><code class="language-javascript">// Improved guard logic snippet async function checkPermission(to) { const userRoles = await fetchUserRoles(); // Asynchronously fetch if (to.meta.roles) { if (!userRoles.some(role => to.meta.roles.includes(role))) { return next({ name: '403' }); } } } router.beforeEach(async (to, from, next) => { // ... Omit login check code ... await checkPermission(to); next(); }); </code></pre> <p>Furthermore, for high-security scenarios, combining CSRF token validation and HTTPS transmission encryption can form a complete permission protection system. Through the organic combination of <code>meta</code> attributes and route guards, developers can build single-page application architectures that are both intuitive and secure, effectively preventing unauthorized access and data leakage risks.</p> </div> </div> </main> <aside class="toc-sidebar" id="tocSidebar"> <div class="toc-sidebar-inner"> <div class="toc-title">On This Page</div> <nav class="toc-nav"> <ul> <li class="toc-level-2"><a href="#building-global-permission-guards">Building Global Permission Guards</a> </li> <li class="toc-level-2"><a href="#handling-special-scenarios-and-exception-flows">Handling Special Scenarios and Exception Flows</a> </li> </ul> </nav> </div> </aside> </div> <footer class="site-footer"> <div class="footer-sites"> <span class="footer-sites-label">Recommended Sites</span> <a href="https://math.bembew.com/en/index.html" target="_blank" rel="noopener">Mathematics</a> <span class="footer-sep">·</span> <a href="https://physics.bembew.com/en/index.html" target="_blank" rel="noopener">Physics</a> <span class="footer-sep">·</span> <a href="https://economics.bembew.com/en/index.html" target="_blank" rel="noopener">Economics</a> <span class="footer-sep">·</span> <a href="https://chemistry.bembew.com/en/index.html" target="_blank" rel="noopener">Chemistry</a> <span class="footer-sep">·</span> <a href="https://biology.bembew.com/en/index.html" target="_blank" rel="noopener">Biology</a> </div> <div class="footer-meta"> <a href="/en/info/about-website.html">About This Site</a> <span class="footer-sep">·</span> <a href="/en/info/privacy.html">Privacy Policy</a> <span class="footer-sep">·</span> <span>© 2025-2026 Bembew - All rights reserved</span> </div> </footer> <div id="cookieConsent" class="cookie-consent" role="region" aria-label="Cookie notice" style="display:none"> <div class="cookie-consent-inner"> <p class="cookie-consent-text">This website uses strictly necessary cookies to keep it secure and functioning (e.g., access control and bot protection), and collects limited anonymous technical data via our CDN. We do not use advertising or tracking cookies. See our <a href="/en/info/privacy.html">Privacy Policy</a>.</p> <button id="cookieConsentAccept" class="cookie-consent-btn" type="button">OK</button> </div> </div> <script src="https://cdn.bootcdn.net/ajax/libs/KaTeX/0.16.9/katex.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/KaTeX/0.16.9/contrib/auto-render.min.js"></script> <script> document.addEventListener('DOMContentLoaded', function() { if (typeof renderMathInElement === 'function') { renderMathInElement(document.body, { delimiters: [ {left: '$$', right: '$$', display: true}, {left: '$', right: '$', display: false}, {left: '\\(', right: '\\)', display: false}, {left: '\[', right: '\]', display: true} ], throwOnError: false, strict: false, trust: true }); } }); </script> <script> document.addEventListener('DOMContentLoaded', function() { var headings = document.querySelectorAll('.article-body h1[id], .article-body h2[id], .article-body h3[id], .article-body h4[id], .article-body h5[id], .article-body h6[id]'); var tocLinks = document.querySelectorAll('.toc-nav a'); if (headings.length === 0 || tocLinks.length === 0) return; // Highlight current heading on scroll using IntersectionObserver if ('IntersectionObserver' in window) { var observer = new IntersectionObserver(function(entries) { entries.forEach(function(entry) { if (entry.isIntersecting) { var id = entry.target.getAttribute('id'); tocLinks.forEach(function(link) { var isActive = link.getAttribute('href') === '#' + id; link.classList.toggle('active', isActive); }); } }); }, { rootMargin: '-80px 0px -70% 0px', threshold: 0 }); headings.forEach(function(h) { observer.observe(h); }); } }); </script> <script> document.addEventListener('DOMContentLoaded', function() { // Close language dropdown and mobile menu when clicking outside document.addEventListener('click', function(e) { var langMenu = document.getElementById('langMenu'); var langToggle = document.querySelector('.lang-dropdown-toggle'); if (langMenu && langMenu.classList.contains('show') && !langMenu.contains(e.target) && !langToggle.contains(e.target)) { langMenu.classList.remove('show'); } var mobileMenu = document.getElementById('mobileMenu'); var menuTrigger = document.getElementById('menuTrigger'); if (mobileMenu && mobileMenu.classList.contains('active') && !mobileMenu.contains(e.target) && !menuTrigger.contains(e.target)) { mobileMenu.classList.remove('active'); } }); // Close mobile menu when clicking a link inside it var mobileMenu = document.getElementById('mobileMenu'); if (mobileMenu) { mobileMenu.querySelectorAll('a').forEach(function(a) { a.addEventListener('click', function() { mobileMenu.classList.remove('active'); }); }); } // Close TOC overlay when clicking a link inside it (mobile) var tocSidebar = document.getElementById('tocSidebar'); if (tocSidebar) { tocSidebar.querySelectorAll('a').forEach(function(a) { a.addEventListener('click', function() { closeToc(); }); }); } // Close sidebar overlay when clicking a link inside it (mobile) var articleSidebar = document.getElementById('articleSidebar'); if (articleSidebar) { articleSidebar.querySelectorAll('a').forEach(function(a) { a.addEventListener('click', function() { closeSidebar(); }); }); } // Topic 详情页 Tab 切换(介绍 / 指南) var topicTabs = document.querySelector('.topic-tabs'); if (topicTabs) { var topicTabButtons = topicTabs.querySelectorAll('.topic-tab'); var topicTabPanels = topicTabs.querySelectorAll('.topic-tab-panel'); topicTabButtons.forEach(function(tab) { tab.addEventListener('click', function() { var key = tab.getAttribute('data-tab'); topicTabButtons.forEach(function(btn) { var on = btn === tab; btn.classList.toggle('active', on); btn.setAttribute('aria-selected', on ? 'true' : 'false'); }); topicTabPanels.forEach(function(panel) { panel.classList.toggle('active', panel.getAttribute('data-panel') === key); }); }); }); } }); // Mobile sidebar toggle (article page) function toggleSidebar() { var sidebar = document.getElementById('articleSidebar'); var overlay = document.getElementById('sidebarOverlay'); if (sidebar) sidebar.classList.toggle('open'); if (overlay) overlay.classList.toggle('show'); } function closeSidebar() { var sidebar = document.getElementById('articleSidebar'); var overlay = document.getElementById('sidebarOverlay'); if (sidebar) sidebar.classList.remove('open'); if (overlay) overlay.classList.remove('show'); } // Mobile TOC toggle function toggleToc() { var toc = document.getElementById('tocSidebar'); var overlay = document.getElementById('tocOverlay'); if (toc) toc.classList.toggle('open'); if (overlay) overlay.classList.toggle('show'); } function closeToc() { var toc = document.getElementById('tocSidebar'); var overlay = document.getElementById('tocOverlay'); if (toc) toc.classList.remove('open'); if (overlay) overlay.classList.remove('show'); } </script> <script> (function() { try { if (localStorage.getItem('cookie_consent')) return; var el = document.getElementById('cookieConsent'); var btn = document.getElementById('cookieConsentAccept'); if (!el || !btn) return; el.style.display = 'block'; btn.addEventListener('click', function() { try { localStorage.setItem('cookie_consent', 'v1'); } catch (e) {} el.style.display = 'none'; }); } catch (e) {} })(); </script> <script> !function(p){"use strict";!function(t){var s=window,e=document,i=p,c="".concat("https:"===e.location.protocol?"https://":"http://","sdk.51.la/js-sdk-pro.min.js"),n=e.createElement("script"),r=e.getElementsByTagName("script")[0];n.type="text/javascript",n.setAttribute("charset","UTF-8"),n.async=!0,n.src=c,n.id="LA_COLLECT",i.d=n;var o=function(){s.LA.ids.push(i)};s.LA?s.LA.ids&&o():(s.LA=p,s.LA.ids=[],o()),r.parentNode.insertBefore(n,r)}()}({id:"KNg95ReuAl9m0Oxc",ck:"KNg95ReuAl9m0Oxc"}); </script> </body> </html>