前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >组件库源码中这些写法你掌握了吗?

组件库源码中这些写法你掌握了吗?

作者头像
树酱
发布2020-07-15 11:08:02
1.6K0
发布2020-07-15 11:08:02
举报
文章被收录于专栏:前端那些趣事前端那些趣事

❝ 前沿:这几年,前端的组件库的演变迅速,社区脱颖而出不少优秀的开源组件库,包括element-ui、Ant design、IView等等,这些开源组件库源码中其实有很多值得我们学习的地方,无论是设计思路,代码风格等等,可以通过参考源码中一些写法,引用到我们平时的项目中去。 ❞

1.Directives (指令)

❝ 在vue中我们可以通过自定义指令,来对DOM元素进行底层操作,我们顺便复习下如何自定义一个指令,主要包含5个钩子函数,这里只列出几个比较常用的钩子函数,最后再介绍组件库常见的一些自定义指令 ❞

代码语言:javascript
复制
Vue.directive("directiveName", {
  bind: function(el, binding, vnode){
   # 当指令第一次绑定元素el时触发,常用来做初始化
  },
  update: function(el, binding, vnode) {
   # 绑定Vue编译生成的虚拟节点VNode 更新时调用
  },
  unbind: function(el, binding, vnode) {
   # 解绑操作,用来将指令和元素解绑时调用,类似vue生命周期中的beforeDestroy钩子函数
  }
});
复制代码
1.1 v-clickoutside

❝ v-clickoutside是Element-ui实现的一个自定义指令,目的是用来处理点击元素外面才会触发的事件,常用来处理下拉菜单等展开内容的关闭,在Element-ui的Select选择器、Dropdown下拉菜单、Popover 弹出框等组件中都用到了该指令 ❞

  • element的实现

❝ element的 clickoutside 的具体实现,如下?,更多源码详情看链接 element/src/utils/clickoutside.js

下面我们大概解读下这段代码的三个钩子函数内的逻辑

  • bind: 将绑定clickoutside指令的dom的el通过push到nodeList存起来,目的在于管理每次有 clickoutside 指令绑定到页面上,都会将绑定元素存储到 nodeList 中去。通过自增的临时变量 id来标识该 clickoutside 指令
  • update: 其实本质上就是用来更新初始化我们定义绑定在el的ctx中的值,方便组件更新时做变更
  • unbind:当需要将指令和元素el解绑时,通过遍历原先的“元素管理器“ - nodeList 的长度和结合上文提到的id找到 nodeList 中存储的当前解绑元素 el,将它从nodeList中删除

下图是一个bind的结果

❝ ? 啊斌同学:那clickoutside是怎么判断是否为点击外部? ❞

答案:是bind中使用的createDocumentHandler()

  • createDocumentHandler() :就是用来区分当前点击的区域是否为指令绑定的dom,本质上是contains方法,好比某A元素包含B元素,则返回true,否则 false 。用来判断元素所处的位置,简单来说点击绑定v-clickoutside绑定的元素则不触发clickoutside 指令的逻辑,点击不包含区域则触发指令绑定的binding.value,我们看下源码向下

❝ ? 啊琪同学:这个组件的指令,我想自己项目中使用咋搞哦? ❞

答案:跟平常引用的指令一样的方式,可以参考源码中引用 链接

  • IView的实现

❝ ? 啊呆弟弟:那其他组件库这种情况怎么实现的呢? ❞

答案:像iview源码中clickoutside引入了v-click-outside-x作为依赖,感兴趣的童鞋可以看文档链接

1.2 v-repeat-click

❝ v-repeat-clickr顾名思义就是"重复点击、用于函数防抖",结合dom.js中的on和once方法。element将v-repeat-clickr应用于el-input-number组件,当你点击+或者-时,会用到 ❞

当我们长按+或者-时,本质上只会触发一次触发mousedown的回调,但我们会发现输入框中的数字会不断递增?让我们先看看源码 源码链接

❝ 啊森同学:那数字会变,那不是一直触发? ❞

答案:repeat-click在mousedown的回调函数中加入了定时器,当鼠标松开,触发一次mouseup回调方法,然后根据时间间隔来执行

  • 如果时间间隔大于100毫秒,mousedown的回调方法里的setInterval回调函数就会执行handler函数(本质上是数字的decrease或increase)
  • 如果时间间隔小于100毫秒,定时器就会取消,通过once方法注册并执行一次mouseup回调

拓展:我们看看domjs中on及once的定义

  • once: 注册事件监听器并只允许执行一次,然后取消监听方法

2.Mixin(混入)

❝ Mixin相信大家不陌生,mixin提供了一种非常灵活的方式,可以用来分发Vue组件中的可复用功能,借助Mixin多个组件可以共享数据和方法。同时引入mixin的组件,mixin中的方法和属性也就并入到该组件中,可以直接使用。钩子函数也将会在两个都被调用(Mixin中的钩子会先执行) ❞

2.1 dispath 和 broadcast(Iview & element)

❝ Vue新版本中去掉了broadcast和dispatch的方法,分别是用来作:事件广播 和 事件派发的要。而后来 element ui 和 iview 中对 broadcast 和 dispatch 方法进行了重写,并通过 mixin 的方式植入到每个组件中。 ❞

  • broadcast

❝ broadcast 方法的作用是向后代子孙组件传值,它会遍历所有的后代组件,当遍历到后代组件中 componentName 与当前的组件名一样,则触发 $emit 事件,以此来传递数据 ❞

  • dispath

❝ dispatch 的作用是向祖先组件传值,它会一直寻找父组件,直到找到组件名和当前传入的组件名一致的祖先组件,就会触发其身上的 $emit 事件,并传递数据 ❞

下面我们看一个例子element的Select组件

el-select(ElSelect)其实包含了ElOption、ElOptionGroup等组件,那他们子父或者子祖之间是如何通信的呢,通过的就是dispath和broadcast,我们可以看看源码中的定义,下面是ElOption组件通知el-select的写法

ElOption组件调用dispatch方法(this.dispatch('ElSelect', 'handleOptionClick', [this.value])),通过while循环,找到上层名为ElSelect的组件,并在该组件中捕获该事件

2.2 link (Iview)

❝ Link的方法主要是跳转链接的区分,组件中如面包屑(breadcrumb)、按钮(button)、单元格(Cell)等组件需要处理跳转链接to=""内部路由还是外部链接,还有就是点击事件的处理 ❞

如: <Button to="//iviewui.com" target="_blank">New window</Button>

  • to - linkUrl (处理链接)

❝ ? 啊乐同学:他是怎么区分内部外部链接哦? ❞

答案是 : 外部链接:检测是否包含'//',内部路由:对相对路径则通过 ``router.resolve处理```

  • Click - handleClick (处理点击事件)

我们可以看到button链接模式下的点击事件click的实现,就是借助混入mixinsLink中的handleCheckClick

3. Validate (表单校验)

❝ 表单校验是组件库表单组件离不开的工具,作为表单数据提交前的格式检验拦截,是个不可缺的角色,我们看到element 和 Iview组件库在表单校验都使用到一个依赖async-validator

  • element
  • IView
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020年07月13日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.Directives (指令)
    • 1.1 v-clickoutside
      • 1.2 v-repeat-click
      • 2.Mixin(混入)
        • 2.1 dispath 和 broadcast(Iview & element)
          • 2.2 link (Iview)
          • 3. Validate (表单校验)
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档