3.12 Breadcrumb 面包屑

0x00 简介

组件 Breadcrumb 用于显示当前页面的路径,快速返回之前的任意页面。 本文将深入分析源码,剖析其实现原理,耐心读完,相信会对您有所帮助。源码实现详见packages/breadcrumb/src/ 文件夹下 breadcrumb.vuebreadcrumb-item.vue 等组件实现。 🔗 组件文档 Breadcrumb 🔗 gitee源码

更多组件剖析详见 👉 📚 Element 2 源码剖析组件总览

面包屑组件有两部分 <breadcrumb><breadcrumb-item>,组件源码都在 packages/breadcrumb/src/ 文件夹下。在项目工程化机制下,每个组件对应各自的文件夹 component-name, 定义导出组件并为其扩展 install 方法,以 commonjs2 规范对每个组件单独打包构建,支持按需引入。

0x01 breadcrumb 组件

breadcrumb.vue 组件是面包屑组件的容器。

template 模板内容

模板创建一个 class 名为.el-breadcrumb<div>元素作为包裹容器,提供了匿名插槽,将提供breadcrumb-item组件引用内容。

<template>
  <div class="el-breadcrumb" aria-label="Breadcrumb" role="navigation">
    <slot></slot>
  </div>
</template>

ARIA 无障碍访问

组件添加了 rolearia-label 属性。 role 表示当前元素的类型。aria-label属性用来给当前元素加上的标签描述。

Accessible Rich Internet Applications (ARIA) 是能够让残障人士更加便利的访问 Web 内容和使用 Web 应用的一套机制。 更多内容详见 "ARIA",MDN

attributes 属性

组件定义了 2 个 prop : separatorseparatorClass 。 这两个prop用于在<el-breadcrumb>标签中设置分隔符的形式。

默认使用separator属性,只能是字符串,默认为斜杠/。也可通过设置 separatorClass 使用相应的 iconfont 作为分隔符,格式内容为el-icon-[icon-name],这将使 separator 设置失效。具体逻辑实现详见下文章节 breadcrumb-item 组件#分隔符

provide/inject 依赖注入

使用 依赖注入,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在其上下游关系成立的时间里始终生效。

provide 选项允许指定想要提供给后代组件的数据/方法。这里将提供组件 breadcrumb 的 vue 实例 。

在任何后代组件里,使用 inject 选项来指定接收添加在这个实例上的 property。breadcrumb-item组件访问父级组件breadcrumb的实例。

mounted()

实例被挂载后,即 mounted 方法中,通过 $el.querySelectorAll('.el-breadcrumb__item') 在面包屑组件的DOM元素中查找<breadcrumb-item>子节点。为最后一个 <breadcrumb-item> 节点添加属性aria-current="page"

组件DOM渲染如下,指明<breadcrumb-item>集合中的最后一个代表当前页面。

0x02 breadcrumb-item 组件

breadcrumb-item.vue组件用于实现每一个el-breadcrumb-item 子标签。

template 模板内容

模板创建一个 class 名为el-breadcrumb__item<span>元素作为标签容器,包含 2 个子节点 标签inerr分隔符

标签 inner

该节点渲染一个 class 名为el-breadcrumb__inner<span>元素, 根据 prop 传入的to值动态添加链接样式。当prop属性 totruthy 时,添加is-link样式。 同时提供了匿名插槽自定义标签内容。

ref 声明用来给元素注册引用信息。role="link" 声明用于识别创建与应用或外部资源的超链接的元素。

attributes 属性

组件定义了 2 个 prop toreplace用于路由设置。

  • to 路由跳转对象,同 vue-routerto

  • replace 在使用 to 进行路由跳转时,启用 replace 将不会向 history 添加新记录。

mounted()

实例被挂载后,根据 toreplace的传入值动态配置路由设置。

  1. 使用$refs获取 标签 inner节点标签元素信息。

  2. 为节点元素添加click监听事件

标签监听事件主要用于,点击标签时,判断是否 注册 router 实例 和 设置路由跳转对象(prop 的 to),若都满足,则根据 replace 在使用 to 进行路由跳转时使用不同编程式的导航 。

声明式
编程式
描述

<router-link :to="...">

router.push(...)

向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL。

<router-link :to="..." replace>

router.replace(...)

不会向 history 添加新记录,替换掉当前的 history 记录。

分隔符

当属性 separatorClasstruthy 时,使用相应的 iconfont 作为分隔符。

否则使用separator属性,默认为斜杠/,此时渲染的 <span> 元素, 其role="presentation" 属性声明用于从元素及其子元素中删除语义含义。

separatorseparatorClass属性值通过依赖注入从父组件获取实例,在 mounted 方法中获取父组件的prop中的属性值进行赋值。


0x03 组件样式

src/breadcrumb.scss

组件样式源码 packages\theme-chalk\src\breadcrumb.scss 使用混合指令 beutils-clearfix嵌套生成组件样式。

混合指令utils-clearfix 用于清除浮动。

breadcrumb.scss 生成逻辑如下。

虽然定义了 breadcrumb-item.scss样式文件,但是所有的样式逻辑都在breadcrumb.scss中实现。

lib/breadcrumb.scss

前文可知使用 gulpfile.js编译 scss 文件转换为CSS,经过浏览器兼容、格式压缩,最后生成 packages\theme-chalk\lib\breadcrumb.scss,内容格式如下。

0x04 📚参考

"依赖注入",vuejs.org “组件注入”,vue-router “Using ARIA: Roles, states, and properties”,MDN “Breadcrumb Example”,w3.org "ref",vuejs.org

最后更新于