06 通过 directive 增强组件内容

目标

之前的五篇文章中,switch 组件一直是被视为内部组件存在的,细心的读者应该会发现,这个组件除了帮我们提供开关的交互以外,还会根据当前 toggle 的开关状态,为 button 元素增加 aria-expanded 属性,以 aira 开头的属性叫作内容增强属性,它用于描述当前元素的某种特殊状态,帮助残障人士更好地浏览网站内容。

但是,作为组件调用者,未必会对使用这种相关属性对网站内容进行增强,那么如何更好地解决这个问题呢?答案就是使用 directive。

我们期望能够显示地声明当前的元素是一个 toggler 职能的组件或者元素,这个组件或者元素,可以根据当前 toggle 组件的开关状态,动态地更新它本身的 aria-expanded 属性,以便针对无障碍访问提供适配。

实现

简单实现

首先创建一个 toggler 指令函数,如下:

export default function(el, binding, vnode) {const on = binding.valueif (on) {el.setAttribute(`aria-expanded`, true);} else {el.removeAttribute(`aria-expanded`, false);}
}

这个指令函数很简单,就是通过传入指令的表达式的值来判定,是否在当前元素上增加一个 aria-expanded 属性。之后再 app 引入该指令,如下:

directives: {toggler
}

之后就可以在 app 组件的模板中使用该指令了,比如:

<custom-button v-toggler="status.on" ref="customButton" :on="status.on" :toggle="toggle"></custom-button>

一切都将按预期中运行,当 toggle 组件的状态为开时,custom-button 组件的根元素会增加一个 aria-expanded="true" 的内容增强属性。

Note: 这里关于指令的引入,使用的函数简写的方式,会在指令的 bind 和 update 钩子函数中触发相同的逻辑,vue 中的指令包含 5 个不同的钩子函数,这里就不赘述了,不熟悉的读者可以通过阅读官方文档来了解。

注入当前组件实例

上文中的指令会通过 binding.value 来获取 toggle 组件的开关状态,这样虽然可行,但在使用该指令时,custom-button 本身的 prop 属性 on 已经代表了当前的开关状态,能否直接在指令中获取当前所绑定的组件实例呢?答案是可以的。指令函数的第三个参数即为当前所绑定组件的虚拟 dom 节点实例,其 componentInstance 属性指向当前组件实例,所以可以将之前的指令改版如下:

export default function(el, binding, vnode) {const comp = vnode.componentInstance;const on = binding.value || comp.on;if (on) {el.setAttribute(`aria-expanded`, true);} else {el.removeAttribute(`aria-expanded`, false);}
}

这样,即使不向指令传入表达式,它也可以自动去注入当前修饰组件所拥有的 prop 属性 on 的值,如下:

<custom-button v-toggler ref="customButton" :on="status.on" :toggle="toggle"></custom-button>

提供更多灵活性

指令函数的第二个参数除了可以获取传入指令内部的表达式的值以外,还有其他若干属性,比如 name、arg、modifiers等,详细说明可以去参考官方文档。

为了尽可能地使指令保证灵活性,我们期望可以自定义无障碍属性 aria 的后缀名称,比如叫做 aria-on,这里我们可以通过 arg 这个参数轻松实现,改版如下:

export default function(el, binding, vnode) {const comp = vnode.componentInstance;const suffix = binding.arg || "expanded";const on = binding.value || comp.on;if (on) {el.setAttribute(`aria-${suffix}`, true);} else {el.removeAttribute(`aria-${suffix}`, false);}
}

可以发现,这里通过 binding.arg 来获取无障碍属性的后缀名称,并当没有传递该参数时,降级至 expanded。这里仅仅是为了演示,读者有兴趣的话,还可以利用 binding 对象的其他属性提供更多的灵活性。

成果

最终的运行结果就不用语言描述了,直接截了一个图,是 toggle 组件开关状态为开时的截图:

你可以下面的链接来看看这个组件的实现代码以及演示:

  • sandbox: 在线演示
  • github: part-6

总结

关于指令的概念,我自身还是在 angularjs(v1.2以下版本) 中第一次接触,当时其实不兴组件化开发这个概念,指令本身的设计理念也是基于增强这个概念的,即增强某个 html 标签。到后来兴起了组件化开发的开发思想,指令似乎是随着 angularjs 的没落而消失了踪影。

但仔细想想的话,web 开发流程中,并不是所有的场景都可以拿组件来抽象和描述的,比如说,你想提供一个类似高亮边框的公用功能,到底如何来按组件化的思想抽象它呢?这时候使用指令往往是一个很好的切入点。

因此,当你面临解决的问题,颗粒度小于组件化抽象的粒度,同时又具备复用性,那就大胆的使用指令来解决它吧。

目录

github gist

关注公众号 全栈101,只谈技术,不谈人生

高级 Vue 组件模式 (6)相关推荐

  1. 高级 Angular 组件模式 (3a)

    03-a Communicate Between Components Using Dependency Injection 原文: Communicate Between Components Us ...

  2. vue-class-component 以class的模式写vue组件

    vue英文官网推荐了一个叫vue-class-component的包,可以以class的模式写vue组件.vue-class-component(以下简称Component)带来了很多便利: 1.me ...

  3. 使用lib库模式打包vue组件及组件引用

    1.lib库模式打包vue组件 语法: vue-cli-service build --target lib --name libName [entry] 示例: 当使用一个 .js 或 .ts 文件 ...

  4. 14、Vue组件高级

    1.动态组件 问题描述: 当我们在使用大多数网站的时候,登录和注册可以在同一个页面实现,就是当点击登录的时候登录的相关信息显示,点击注册的时候,注册的相关信息显示. 针对以上问题我们可以使用v-if和 ...

  5. vue组件化开发实践

    前言 公司目前制作一个H5活动,特别是有一定统一结构的活动,都要码一个重复的轮子.后来接到一个基于模板的活动设计系统的需求,便有了一下的内容.首先会对使用Vue进行开发的一些前期需要的技术储备进行简单 ...

  6. 好用的vue组件插件及框架

    实用的vue插件大汇总 Vue是一个构建数据驱动的 web 界面的渐进式框架.Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件特别整理了常用的vue插件,来了个大汇总 ...

  7. Vue 组件通信方式居然有这么多?你了解几种

    ↓推荐关注↓ 前端技术编程 专注于分享前端技术:JS,HTML5,CSS3,Vue.js,React,Angular 等前端框架和前端开源项目推荐! 0篇原创内容 公众号 vue组件通信的方式,这是在 ...

  8. vue组件库大全(忘了的时候可以进来找一下~)

    基于Vue的组件库 https://github.com/ElemeFE/element" element 饿了么出品的Vue2的web UI工具套件 https://github.com/ ...

  9. Vue 组件 全家桶

    Vue是一个构建数据驱动的 web 界面的渐进式框架.Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件特别整理了常用的vue插件,这里对vue插件汇总,提供vue组件 ...

最新文章

  1. 敏捷 - #9 原则:持续关注卓越的技术和良好的设计 ( #9 Agile - Principle)
  2. 读取SD卡里面的BMP文件 显示到TFT上
  3. 放在每个定义前的html语言,html基础
  4. 下列哪个滤波器是非线性的_数字图像处理复习题(选择题及相应答案)
  5. 前端学习(3093):vue+element今日头条管理-反馈
  6. # android开发:4-1、Activity启动方式、生命周期、不同activity的数据传递
  7. 一篇让你的Python代码变得更加整洁的文章!
  8. 一道二叉树的题目--后序遍历+中序遍历确定二叉树
  9. 高并发系统架构案例 - 微信红包高并发架构设计 - 学习/实践
  10. Intel i5-7200U (3100MHZ),1*8GB(DDR4 2666) 在 Aida64 V5.97.4600 的测试结果
  11. S3C2440驱动开发(一)
  12. Spring乱码问题解决
  13. 小白学习Java第七天
  14. 计算机网络各层设备及功能讲解大汇总~
  15. 丽江古城历史悠久,古朴自然
  16. 电子产品销售数据分析
  17. IOT(物联网)的七大通信协议
  18. python简单入门——画多啦A梦
  19. 七日年化收益率及每万份收益
  20. 金彭电动三轮车质量好吗?来听听“老司机”怎么说

热门文章

  1. Ubuntu中Zabbix安装客户端
  2. 如何让Win7不再弹出升级Win10的提醒窗口
  3. [zabbix]解决binlog日志过大/web界面中文乱码问题
  4. Zabbix动态监控磁盘I/O
  5. Java中的System.getProperty()设置参数的方法
  6. 引用css样式时,一个class引用两个样式的写法( class=ico001 icoCom)。
  7. 执行Oracle中的sqlldr xxx.ctl命令导入数据时,当错误无法导入时,注意查看「xxx.log信息」
  8. 关于Eclipse中的plugin的安装(之*.zip)
  9. 【Python】pymysql.err.InternalError: (1236, 'Misconfigured master - server_id was not set')
  10. 【Linux】修改Linux操作系统字符集与Oracle数据库一致