资讯专栏INFORMATION COLUMN

高级 Vue 组件模式 (6)

makeFoxPlay / 2664人阅读

摘要:之后再引入该指令,如下之后就可以在组件的模板中使用该指令了,比如一切都将按预期中运行,当组件的状态为开时,组件的根元素会增加一个的内容增强属性。到后来兴起了组件化开发的开发思想,指令似乎是随着的没落而消失了踪影。

06 通过 directive 增强组件内容 目标

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

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

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

实现 简单实现

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

export default function(el, binding, vnode) {
  const on = binding.value

  if (on) {
    el.setAttribute(`aria-expanded`, true);
  } else {
    el.removeAttribute(`aria-expanded`, false);
  }
}

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

directives: {
  toggler
}

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

一切都将按预期中运行,当 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 的值,如下:

提供更多灵活性

指令函数的第二个参数除了可以获取传入指令内部的表达式的值以外,还有其他若干属性,比如 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,只谈技术,不谈人生

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/98558.html

相关文章

  • 高级 Vue 组件模式 (1)

    摘要:写在前头去年,曾经阅读过一系列关于高级组件模式的文章,今年上半年,又抽空陆陆续续地翻译了一系列关于高级组件模式的文章,碰巧最近接手了一个公司项目,前端这块的技术栈是。同时这个组件还拥有一个属性,用来初始化的状态值。 写在前头 去年,曾经阅读过一系列关于高级 react 组件模式的文章,今年上半年,又抽空陆陆续续地翻译了一系列关于高级 angular 组件模式的文章,碰巧最近接手了一个公...

    lanffy 评论0 收藏0
  • vue-router 一些容易被忽略的知识点

    摘要:调用全局的守卫。在被激活的组件里调用。用创建好的实例调用守卫中传给的回调函数。 本文适用于对 Vue.js 和 vue-router 有一定程度了解的开发者除特殊说明,vue-router 版本为 3.0.2 正文 路由 class 匹配 路由匹配后会给该标签添加 class 属性值 .router-link-active,该功能在嵌套路由中十分方便 class 的实际属性值可以通...

    chunquedong 评论0 收藏0
  • 高级 Vue 组件模式 (3)

    摘要:在中,我们是否也有一些手段或特性来提高组件的复用程度和灵活性呢答案当然是有的,那就是。成果通过实现,我们成功将注入的逻辑抽离了出来,这样每次需要共享组件的状态和方法时,混入该即可。 03 使用 mixin 来增强 Vue 组件 目标 之前一篇文章中,我们虽然将 toggle 组件划分为了 toggle-button、toggle-on 和 toggle-off 三个子组件,且一切运行良...

    iKcamp 评论0 收藏0
  • 高级 Vue 组件模式 (2)

    摘要:编写复合组件目标我们需要实现的需求是能够使使用者通过组件动态地改变包含在它内部的内容。成果通过复合组件的方式,我们将组件划分为了三个更小的职责更加单一的子组件。 02 编写复合组件 目标 我们需要实现的需求是能够使使用者通过 组件动态地改变包含在它内部的内容。 熟悉 vue 的童鞋可能马上会想到不同的解决方案,比如使用 slot 并配合 v-if,我们这里采用另外一种方法,利用 vu...

    Galence 评论0 收藏0
  • 前端面试题总结(js、html、小程序、React、ES6Vue、算法、全栈热门视频资源)

    摘要:并总结经典面试题集各种算法和插件前端视频源码资源于一身的文档,优化项目,在浏览器端的层面上提升速度,帮助初中级前端工程师快速搭建项目。 本文是关注微信小程序的开发和面试问题,由基础到困难循序渐进,适合面试和开发小程序。并总结vue React html css js 经典面试题 集各种算法和插件、前端视频源码资源于一身的文档,优化项目,在浏览器端的层面上提升速度,帮助初中级前端工程师快...

    pumpkin9 评论0 收藏0

发表评论

0条评论

makeFoxPlay

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<