详解Vue用自定义指令完成一个下拉菜单(select组件)


Posted in Javascript onOctober 31, 2017

这次分享的是关于Vue自定义指令的使用方法,学习完基础后我们再来实战完成一个下拉列表,废话不多说,直接上干货

基本用法

//全局注册
Vue.directive('my-directive', {
 // 指令选项
})

// 局部注册
var app = new Vue({
 el: '#app'
 directives: {
  'my-directive': {
    // 指令选项
  }
})

相信对Vue比较熟悉的人看完都知道,directive的写法与组件 基本类似,只是方法名由component改为了directive。上例只是注册了自定义指令v-my-directive,还没实现具体功能,下面具体介绍 自定义指令的各个选项。

指令定义函数提供了几个钩子函数 (可选):

  1. bind:只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。
  2. inserted:被绑定元素插入父节点时调用 (父节点存在即可调用,不必存在于 document 中)。
  3. update:所在组件的 VNode 更新时调用,但是可能发生在其孩子的 VNode 更新之前。指令的值可能发生了改变也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
  4. componentUpdated:所在组件的 VNode 及其孩子的 VNode 全部更新时调用。
  5. unbind:只调用一次,指令与元素解绑时调用。

可根据需求在不同的钩子函数 内完成逻辑代码,如下面v-focus,我们希望在元素插入父节点时就调用,那用到的最好的就是inserted了。示例代码如下

// html部分
<div id="app" v-focus>
// js部分
Vue.directive('focus', {
 // 当绑定元素插入到 DOM 中。
 inserted: function (el) {
  // 聚焦元素
  el.focus()
 }
})

效果如下图所示

详解Vue用自定义指令完成一个下拉菜单(select组件)

自定义指令 v-focus.png

可以看到,打开这个页面,input输入框就自动获取焦点了,成为可输入状态。

每个钩子函数 都可以有几个参数可用,比如我们上面用到了el。它们 的含义如下:

  1. el:指令所绑定的元素,可以用来直接操作 DOM 。
  2. binding:一个对象,包含以下属性:
    1. name:指令名,不包括 v-前缀。
    2. value:指令的绑定值,例如:v-my-directive="1 + 1", value 的值是 2。
    3. oldValue:指令绑定的前一个值,仅在 update和 componentUpdated钩子中可用。无论值是否改变都可用。
    4. expression:绑定值的字符串形式。例如 v-my-directive="1 + 1" ,expression 的值是 "1 + 1"。
    5. arg:传给指令的参数。例如 v-my-directive:foo,arg 的值是 "foo"。
    6. modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar, 修饰符对象 modifiers 的值是 { foo: true, bar: true }。
  3. vnode:Vue 编译生成的虚拟节点,查阅 VNode API 了解更多详情。
  4. oldVnode:上一个虚拟节点,仅在 update和 componentUpdated钩子中可用。

下面是结合了以上参数 的一些具体示例,代码如下

// HTML部分
<div id="app" v-demo:msg.a.b="message">
 <div v-text:msg.a.b="message"></div>
</div>
// JS部分
Vue.directive('demo', {
 bind: function (el, binding, vnode) {
  var s = JSON.stringify
  el.innerHTML =
   'name: '    + binding.name + '<br>' +
   'value: '   + binding.value + '<br>' +
   'expression: ' + binding.expression + '<br>' +
   'argument: '  + binding.arg + '<br>' +
   'modifiers: ' + JSON.stringify(binding.modifiers).modifiers + '<br>' +
   'vnode keys: ' + Object.keys(vnode).join(',')
 }
})
new Vue({
 el: '#app',
 data: {
  message: 'some text'
 }
})

执行后,<div>的内容会使用innerHTML重置,结果为

name: "test"
value: "some text"
expression: "message"
argument: "msg"
modifiers: {"a":true,"b":true}
vnode keys: tag, data, children, text, elm, ns, context, functionalContext, functionalOptions, functionalScopeId, key, componentOptions, componentInstance, parent, raw, isStatic, isRootInsert, isComment, isCloned, isOnce, asyncFactory, asyncMeta, isAsyncPlaceholder

在多数使用场景,我们会在bind钩子里绑定一些事件,比如在document上用addEventListerer绑定,在unbind里有
removeEventListener 解绑,比较典型的示例就是让这个元素随着鼠标拖拽。

如果需要更多个值,自定义指令也可以传入一个JavaScript对象字面量, 只要是合法类型的JavaScript表达式都是可以的。示例代码如下:

// HTML部分
<div id="app" v-demo:msg.a.b="message">
 <div v-test="{msg: 'hello', name: 'Aresn'}"></div>
</div>

//JS部分
Vue.directive('test', {
 bind: function (el, binding, vnode) {
  console.log(binding.value.msg)
  console.log(binding.value.name)
 }
})
var app = new Vue({
 el: '#app'
})

Vue 2.x很移除大量Vue 1.x自定义指令的配置。在使用自定义指令时,应该充分解业务需求,因为很多时候你需要的可能并不是自定义指令,而是组件。

基础的东西讲完了,我们来根据directive提供的API来写一个点击外部区域可以让其下拉列表消失的菜单

// HTML部分
<div id="app" v-clock>
 <div class="main" v-clickoutside="handleClose">
  <button @click="show = !show">点击显示下拉菜单</button>
  <div class="dropdown" v-show="show">
   <p>下拉框内容,点击外面区域可以关闭</p>
  </div>
</div>

// JS部分
var app = new Vue({
 el: '#app',
 data: {
  show: false
 },
methods: {
 handleClose() {
  this.show = false;
 }
}
})

Vue.directive('clickoutside', {
 bind: function(el, binding, vode) {
  function documentHandler (e) {
   if (el.contains(e.target)) {
    return false
   }
   if (binding.expression) {
    binding.value(e)
   }
  }
  el.__vueClickOutSide__ = documentHandler
  document.addEventListener('click', documentHandler)
 },
 unbind: function(el, binding) {
  document.removeEventListener('click', el.__vueClickOutSide__)
  delete el.__vueClickOutSide__
 }
})

要在document上绑定click事件,所以在bind钩子内声明了一个函数documentHandler,并将它作为句柄定在document的click事件上。documentHandler函数做了两个判断,第一个是判断点击的区域是否是指令所在的元素内部,如果是,就跑出函数,不信下继续执行

contains方法是用来判断元素A是否包含了元素 B,包含返回true,不包含返回false

// HTML
<div id="parent">
 父元素
 <div id="children">子元素</div>
</div>
// JS
var a = doucment.getElemengById('parent')
var b = doucment.getElemengById('children')
console.log(A.contains(B)) // true
console.log(B.contains(A)) // false

第二个判断是当前 的指令v-clickoutside有没有写表达式,在该自定义指令中,表达 式应该是第一个函数 ,在过滤了内部元素后,点击外面任何区域应该招待用户表达 式中的函数 ,所以binding.value就用来执行上下文methods中指定的函数的

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
node.js中的console.dir方法使用说明
Dec 10 Javascript
JavaScript Window浏览器对象模型方法与属性汇总
Apr 20 Javascript
jQuery获取父元素节点、子元素节点及兄弟元素节点的方法
Apr 14 Javascript
JavaScript的Backbone.js框架入门学习指引
May 07 Javascript
浅谈JS继承_借用构造函数 &amp; 组合式继承
Aug 16 Javascript
如何解决jQuery EasyUI 已打开Tab重新加载问题
Dec 19 Javascript
Vue.js 递归组件实现树形菜单(实例分享)
Dec 21 Javascript
网页中右键功能的实现方法之contextMenu的使用
Feb 20 Javascript
HTML5+Canvas调用手机拍照功能实现图片上传(下)
Apr 21 Javascript
Angular2.0/4.0 使用Echarts图表的示例代码
Dec 07 Javascript
微信小程序购物车、父子组件传值及calc的注意事项总结
Nov 14 Javascript
微信小程序实现图片滚动效果示例
Dec 05 Javascript
原生js实现仿window10系统日历效果的实例
Oct 31 #Javascript
ES6使用Set数据结构实现数组的交集、并集、差集功能示例
Oct 31 #Javascript
Vue实战之vue登录验证的实现代码
Oct 31 #Javascript
jQuery ajax读取本地json文件的实例
Oct 31 #jQuery
ES6解构赋值的功能与用途实例分析
Oct 31 #Javascript
js原生日历的实例(推荐)
Oct 31 #Javascript
CheckBox多选取值及判断CheckBox选中是否为空的实例
Oct 31 #Javascript
You might like
PHP set_time_limit(0)长连接的实现分析
2010/03/02 PHP
探讨PHP使用eAccelerator的API开发详解
2013/06/09 PHP
smarty模板中拼接字符串的方法
2014/02/14 PHP
PHP代码优化之成员变量获取速度对比
2014/02/28 PHP
Session的工作机制详解和安全性问题(PHP实例讲解)
2014/04/10 PHP
php递归json类实例
2014/12/02 PHP
ThinkPHP框架获取最后一次执行SQL语句及变量调试简单操作示例
2018/06/13 PHP
超强的IE背景图片闪烁(抖动)的解决办法
2007/09/09 Javascript
Jquery之Ajax运用 学习运用篇
2011/09/26 Javascript
基于jQuery的烟花效果(运动相关)点击屏幕出烟花
2012/06/14 Javascript
基于KMP算法JavaScript的实现方法分析
2013/05/03 Javascript
理解JAVASCRIPT中hasOwnProperty()的作用
2013/06/05 Javascript
jquery实现按Enter键触发事件示例
2013/09/10 Javascript
javascript验证邮件地址和MX记录的方法
2015/06/16 Javascript
jquery实现浮动在网页右下角的彩票开奖公告窗口代码
2015/09/04 Javascript
正则表达式优化JSON字符串的技巧
2015/12/24 Javascript
关于vue-router路径计算问题
2017/05/10 Javascript
如何基于原生javaScript生成带图片的二维码
2019/11/21 Javascript
Vue中多元素过渡特效的解决方案
2020/02/05 Javascript
vue设置全局访问接口API地址操作
2020/08/14 Javascript
请不要重复犯我在学习Python和Linux系统上的错误
2016/12/12 Python
python爬取m3u8连接的视频
2018/02/28 Python
详解【python】str与json类型转换
2019/04/29 Python
python中tkinter的应用:修改字体的实例讲解
2019/07/17 Python
Python使用ffmpy将amr格式的音频转化为mp3格式的例子
2019/08/08 Python
Python测试Kafka集群(pykafka)实例
2019/12/23 Python
pandas中的数据去重处理的实现方法
2020/02/10 Python
Python使用Turtle模块绘制国旗的方法示例
2021/02/28 Python
解决HTML5手机端页面缩放的问题
2017/10/27 HTML / CSS
奥地利婴儿用品和玩具购物网站:baby-markt.at
2020/01/26 全球购物
开办加工厂创业计划书
2014/01/03 职场文书
夫妻忠诚协议书范本
2014/11/17 职场文书
我的中国梦心得体会范文
2016/01/05 职场文书
党员廉政准则心得体会
2016/01/20 职场文书
承诺书怎么写 ?
2019/04/16 职场文书
GO语言字符串处理函数之处理Strings包
2022/04/14 Golang