#每天都是崭新的一天#再累也要照顾好自己

【vue系列】vue指令directive,自定义指令,对dom操作封装,实战练习(获取焦点,滚动条置底获取数据)

一、前言

最近在看vue的全局API,看着自己总想着自己手动实现一两个,这样有助于理解概念以及原理。

当我看到directive的时候,我在想自己在项目中总是使用ref,然后使用this.$refs.名字获取dom对象,然后操作,现在觉得如果对于不常用的场景是没有问题的,如果很多场景需要操作dom的时候,这时候需要指令directive来解决这个代码复制的痛点。


二、vue自带的指令有哪些?

vue提供了很多指令,比如:v-model, v-on, v-show等。而且还提供了自定义directive属性来自定义指令。

本质:vue.directive是一种特殊的html元素属性

提供两种注册方法:

(1)全局注册

(2)局部注册

当遇到一两个页面使用的时候,可以使用局部注册,但是如果出现三个及三个以上页面使用,建议还是使用全局注册。


三、为啥要用vue.directive?

我们在vue中也是可以操作dom的,为啥还需要使用directive指令来封装dom操作呢?那是因为:

(1)vue是MVVM架构实现,实现了view和viewModel分离,我们必须封装dom操作,vue是数据驱动,属于viewModel层,不应该出现view层的dom操作。

(2)vue的directive是在dom元素创建,销毁绑定的,vue的directive让我们更加优雅的进行dom操作。


四、实战练习:全局注册指令

在vue.directive中定义组件的名称和相关指令操作。

指令的格式:

Vue.directive('my-directive', {
    // 一些option,提供hook function定义具体操作,比如inserted,bind等
    bind: function() {
        
    },
    inserted: function(el) {
    //  指令插入元素后的操作
    },
    update: function() {
      
    },
    componentUpdates: function() {
      
    },
    unbild: function() {
      
    }
})


1、指令:实现一个input元素获取焦点

再vue-cli建立的项目中,入口文件main.js中定义

/* 引入全局指令focus */
Vue.directive('focus', {
  // 被绑定元素插入到dom中  inserted: function (el) {
    el.focus();
  }
})

简单说一下'focus'是指令的名字,inserted是被绑定函数插入到dom中,绑定函数就是回调函数。

然后在需要获取焦点的input元素加入

<input maxlength="16" v-focus @keyup.enter="startLogin" type="text" placeholder="用户名" v-model="name">

这样就可以了,在dom元素挂载mounted后,就会获取焦点,实际就是调用input的自带focus事件。


2、指令:用户滚动条滚动到页面底部,请求更多数据

在移动端开发中,经常会遇到这样的需求。

2.1 如果没有浮动的固定元素,用的是body上的滚动条。

(1)将dom操作封装到指定的option中

let scrollCallback = function(callback) {
  if(document.body.scrollHeight < 1000) {
      return ;
  }
  if(document.body.scrollHeight - window.scrollY - 100 <= document.body.clientHeight){
      callback();
  }
}
let callBackWarpped;
export default {
    bind: function(el, binding, vnode) {
      callBackWarpped = scrollCallback.bind({}, binding.value);
      window.addEventListener("scroll", callBackWarpped, true)
    },
    unbind: function() {
      window.removeEventListener("scroll", callBackWarpped, true)
    }
}

首先需要监听页面body滚动条,如果触发了scroll事件就要执行执行回调函数callBackWarpped,callBackWarpped函数绑定页面具体的函数binding.value。

由于解除绑定的时候也要将监听事件从window对象上移除,所以必须给回调函数取一个名字,比如例子中的scrollCallback,在unbind函数中将监听移除,因此scrollCallback具体定义在对象外执行。

并且回调函数应该在页面滑动到底部的时候才执行,不是马上执行binding.value,而是bind.value作为函数参数传进scrollCallback,先判断,满足条件调用。

(2)导入directive的option,并且注册vue指令

在入口文件main.js中

/* scroll全局置顶scroll */
import scrollDirective from '../src/utils/scroll';
Vue.directive('scroll', scrollDirective)

(3)在相应的dom上加上指令


在methods中定义onScroll方法:

 onScroll() {
      console.log('置底操作加载新数据的指令输出');
      // 请求接口  
    }



2.2 如果有浮动的固定元素,body上的滚动条禁掉了,使用具体元素的滚动条。

上面需要修改的地方是:dom操作封装到options中这块。修改为以下:

let scrollCallback = function(callback, el) {
  if(el.scrollHeight < el.clientHeight) {
    return ;
  }
  if(el.scrollTop + el.clientHeight === el.scrollHeight){
    callback();
  }
}
let callBackWarpped;
export default {
  bind: function(el, binding, vnode) {
    callBackWarpped = scrollCallback.bind({}, binding.value, el);
    window.addEventListener("scroll", callBackWarpped, true)
  },
  unbind: function(el) {
    window.removeEventListener("scroll", callBackWarpped, true)
  }
}

主要是将绑定的dom对象传进来el。根据这个dom对象el的scrollHeight(滚动条总高度),这个是当前内容决定的,固定的。clientHeigth是当前dom对象高度(视窗的高度),固定的,scrollTop是滚动条到内容顶部的高度,变化的。然后根据el.scrollTop + el.clientHeight === el.scrollHeight ,判断是否到达底部了。

在我的happyChat(源码:https://github.com/saucxs/happy-chat-web)中页面用到:https://chat.chengxinsong.cn/message

消息页面的滑到底端,console有输出。



五、实战练习:局部注册指令

在组件的directives属性中注册指令。


在当前页面的元素input中加入v-focus属性。

<input maxlength="16" v-focus @keyup.enter="startLogin" type="text" placeholder="用户名" v-model="name">

滚动条置底请求数据的指令同理。


昵称:saucxs | songEagle | 松宝写代码 

github:https://github.com/saucxs;

一、技术产品:

1、sau交流学习社区(https://www.mwcxs.top/);

2、程新松个人网站(http://www.chengxinsong.cn);

3、happyChat乐聊(https://chat.chengxinsong.cn);

4、weekly周报系统(http://weekly.mwcxs.top);

等等。

二、开源作品:

1、watermark-dom水印插件(https://github.com/saucxs/watermark-dom);

2、captcha-mini验证码插件(https://github.com/saucxs/captcha-mini);

3、watermark-image图片水印(https://github.com/saucxs/watermark-image);

等等。


感谢你的阅读,本文由 sau交流学习社区 版权所有。
如若转载,请注明出处:sau交流学习社区-power by saucxs(程新松)(/page/796.html)
交流咨询
    官方QQ群
    群号663940201,欢迎加入!
    sau交流学习社区交流群

微信群
欢迎加入微信群
微信公众号
欢迎关注微信公众号

图文推荐

微信群
saucxs聊天机器人
saucxs
hi ,欢迎来到sau交流学习社区,欢迎与我聊天,问我问题哦!
您正在使用的浏览器是,不在支持范围内!
为了您的正常使用与展示,推荐使用Chrome浏览器68以上版本
支持浏览器:
火狐浏览器最新版
Safari浏览器最新版
Edge浏览器最新版
IE浏览器10,11