在vuejs中,自定义一些指令对底层dom进行操作。下面本篇文章总结分享一些常用的自定义指令代码,可以直接使用,提高开发效率!
【相关推荐:《vue.js教程》】
1、元素点击范围扩展指令 v-expandclick
使用该指令可以隐式的扩展元素的点击范围,由于借用伪元素实现,故不会影响元素在页面上的排列布局。
可传入的参数为:上右下左扩展的范围,单位 px,默认向外扩展 10px。指令的代码如下:
export default function (el, binding) { const s = document.stylesheets[document.stylesheets.length - 1] const default = -10 // 默认向外扩展10px const rulestr = `content:"";position:absolute;top:-${top || default}px;bottom:-${bottom || default}px;right:-${right || default}px;left:-${left || default}px;` const [top, right, bottom, left] = binding.expression && binding.expression.split(',') || [] const classnamelist = el.classname.split(' ') el.classname = classnamelist.includes('expand_click_range') ? classnamelist.join(' ') : [...classnamelist, 'expand_click_range'].join(' ') el.style.position = el.style.position || "relative" if (s.insertrule) { s.insertrule('.expand_click_range::before' + '{' + rulestr + '}', s.cssrules.length) } else { /* ie */ s.addrule('.expand_click_range::before', rulestr, -1) }}
参数 attributes:
然后你可以在模板中任何元素上使用新的 v-expandclick property,如下:
<div v-expandclick="20,30,40,50" @click="glabclickoutside"> 点击范围扩大</div>
2、文本内容复制指令 v-copy
使用该指令可以复制元素的文本内容(指令支持单击复制 v-copy、双击复制 v-copy.dblclick、点击icon复制 v-copy.icon 三种模式),不传参数时,默认使用单击复制。
指令的代码如下:
export default { bind (el, binding) { // 双击触发复制 if (binding.modifiers.dblclick) { el.addeventlistener('dblclick', () => handleclick(el.innertext)) el.style.cursor = 'copy' } // 点击icon触发复制 else if (binding.modifiers.icon) { if (el.hasicon) return const iconelement = document.createelement('i') iconelement.setattribute('class', 'el-icon-document-copy') iconelement.setattribute('style', 'margin-left:5px') el.appendchild(iconelement) el.hasicon = true iconelement.addeventlistener('click', () => handleclick(el.innertext)) iconelement.style.cursor = 'copy' } // 单击触发复制 else { el.addeventlistener('click', () => handleclick(el.innertext)) el.style.cursor = 'copy' } }}function handleclick (text) { // 创建元素 if (!document.getelementbyid('copytarget')) { const copytarget = document.createelement('input') copytarget.setattribute('style', 'position:fixed;top:0;left:0;opacity:0;z-index:-1000;') copytarget.setattribute('id', 'copytarget') document.body.appendchild(copytarget) } // 复制内容 const input = document.getelementbyid('copytarget') input.value = text input.select() document.execcommand('copy') // alert('复制成功')}
参数 attributes:
然后你可以在模板中任何元素上使用新的 v-copy property,如下:
<div v-copy> 单击复制 </div><div v-copy.dblclick> 双击复制 </div><div v-copy.icon> icon复制 </div>
3、元素全屏指令 v-screenfull
全屏指令,点击元素进行全屏/退出全屏的操作。支持元素后面是否插入 element-ui 的全屏图标 el-icon-full-screen。
指令的代码如下:
import screenfull from 'screenfull'export default { bind (el, binding) { if (binding.modifiers.icon) { if (el.hasicon) return // 创建全屏图标 const iconelement = document.createelement('i') iconelement.setattribute('class', 'el-icon-full-screen') iconelement.setattribute('style', 'margin-left:5px') el.appendchild(iconelement) el.hasicon = true } el.style.cursor = el.style.cursor || 'pointer' // 监听点击全屏事件 el.addeventlistener('click', () => handleclick()) }}function handleclick () { if (!screenfull.isenabled) { alert('浏览器不支持全屏') return } screenfull.toggle()}
参数 attributes:
然后你可以在模板中任何元素上使用新的 v-screenfull property,如下:
<div v-screenfull.icon> 全屏 </div>
4、元素说明指令 v-tooltip
为元素添加说明,如同 element-ui 的 el-tooltip(问号 icon 在鼠标覆盖后,展示说明文字)。
指令的代码如下:
import vue from 'vue'export default function (el, binding) { if (el.hasicon) return const iconelement = structureicon(binding.arg, binding.value) el.appendchild(iconelement) el.hasicon = true}function structureicon (content, attrs) { // 拼接绑定属性 let attrstr = '' for (let key in attrs) { attrstr += `${key}=${attrs[key]} ` } const a = `<el-tooltip content=${content} ${attrstr}><i class="el-icon-question" style="margin:0 10px"></i></el-tooltip>` // 创建构造器 const tooltip = vue.extend({ template: a }) // 创建一个 tooltip 实例并返回 dom 节点 const component = new tooltip().$mount() return component.$el}
参数 attributes:
然后你可以在模板中任何元素上使用新的 v-tooltip property,如下:
<div v-tooltip:content='tootipparams'> 提示 </div>
举例:
<div v-tooltip:提示内容为xxx1> 提示1</div><div v-tooltip:提示内容为xxx='tootipparams'> 提示2 </div>
为指令传入 element-ui 支持的参数:
data() { return { tootipparams: { placement: 'top', effect: 'light', } }}
5、文字超出省略指令 v-ellipsis
使用该指令当文字内容超出宽度(默认 100 px)时自动变为省略形式。等同于使用 css:
width: 100px;whitespace: nowrapoverflow: hidden;textoverflow: ellipsis;
使用指令效果:
指令的代码如下:
export default function (el, binding) { el.style.width = binding.arg || 100 + 'px' el.style.whitespace = 'nowrap' el.style.overflow = 'hidden'; el.style.textoverflow = 'ellipsis';}
参数 attributes:
然后你可以在模板中任何元素上使用新的 v-ellipsis property,如下:
<div v-ellipsis:100> 需要省略的文字是阿萨的副本阿萨的副本阿萨的副本阿萨的副本</div>
6、回到顶部指令 v-backtop
使用该指令可以让页面或指定元素回到顶部。
可选指定元素,如果不指定则全局页面回到顶部。可选在元素偏移多少 px 后显示 backtop 元素,例如在滚动 400px 后显示回到顶部按钮。
指令的代码如下:
export default { bind (el, binding, vnode) { // 响应点击后滚动到元素顶部 el.addeventlistener('click', () => { const target = binding.arg ? document.getelementbyid(binding.arg) : window target.scrollto({ top: 0, behavior: 'smooth' }) }) }, update (el, binding, vnode) { // 滚动到达参数值才出现绑定指令的元素 const target = binding.arg ? document.getelementbyid(binding.arg) : window if (binding.value) { target.addeventlistener('scroll', (e) => { if (e.srcelement.scrolltop > binding.value) { el.style.visibility = 'unset' } else { el.style.visibility = 'hidden' } }) } // 判断初始化状态 if (target.scrolltop < binding.value) { el.style.visibility = 'hidden' } }, unbind (el) { const target = binding.arg ? document.getelementbyid(binding.arg) : window target.removeeventlistener('scroll') el.removeeventlistener('click') }}
参数 attributes:
然后你可以在模板中任何元素上使用新的 v-backtop property,如下表示在 id 为 app 的元素滚动 400px 后显示绑定指令的元素:
<div v-backtop:app="400"> 回到顶部 </div>
也可以这样使用,表示为一直显示绑定指令的元素,并且是全局页面回到顶部:
<div v-backtop> 回到顶部 </div>
7、空状态指令 v-empty
使用该指令可以显示缺省的空状态。可以传入默认图片(可选,默认无图片)、默认文字内容(可选,默认为暂无数据)、以及标示是否显示空状态(必选)。
指令的代码如下:
import vue from "vue";export default { update (el, binding, vnode) { el.style.position = el.style.position || 'relative' const { offsetheight, offsetwidth } = el const { visible, content, img } = binding.value const image = img ? `<img src="${img}" height="30%" width="30%"></img>` : '' const defaultstyle = "position:absolute;top:0;left:0;z-index:9999;background:#fff;display:flex;justify-content: center;align-items: center;" const empty = vue.extend({ template: `<div style="height:${offsetheight}px;width:${offsetwidth}px;${defaultstyle}"> <div style="text-align:center"> <div>${image}</div> <div>${content || '暂无数据'}</div> </div> </div>` }) const component = new empty().$mount().$el if (visible) { el.appendchild(component) } else { el.removechild(el.lastchild) } },}
参数 attributes:
然后你可以在模板中任何元素上使用新的 v-empty property,如下传入对象 emptyvalue:
<div style="height:500px;width:500px" v-empty="emptyvalue"> 原本内容
需要传入一个参数对象,例如显示文字为:暂无列表,图片路径为 ../../assets/images/blue_big.png,控制标示 visible:
emptyvalue = { content: '暂无列表', img: require('../../assets/images/blue_big.png'), visible: true,},
8、徽标指令 v-badge
使用该指令在元素右上角显示徽标。
支持配置徽标的背景颜色、徽标形状;支持传入徽标上显示的数字。
指令的代码如下:
import vue from 'vue'const success = '#72c140'const error = '#ed5b56'const warning = '#f0af41'const info = '#4091f7'const height = 20let flag = falseexport default { update (el, binding, vnode) { const { modifiers, value } = binding const modifierskey = object.keys(modifiers) let isdot = modifierskey.includes('dot') let backgroundcolor = '' if (modifierskey.includes('success')) { backgroundcolor = success } else if (modifierskey.includes('warning')) { backgroundcolor = warning } else if (modifierskey.includes('info')) { backgroundcolor = info } else { backgroundcolor = error } const targettemplate = isdot ? `<div style="position:absolute;top:-5px;right:-5px;height:10px;width:10px;border-radius:50%;background:${backgroundcolor}"></div>` : `<div style="background:${backgroundcolor};position:absolute;top:-${height / 2}px;right:-${height / 2}px;height:${height}px;min-width:${height}px;border-radius:${height / 2}px;text-align:center;line-height:${height}px;color:#fff;padding:0 5px;">${value}</div>` el.style.position = el.style.position || 'relative' const badge = vue.extend({ template: targettemplate }) const component = new badge().$mount().$el if (flag) { el.removechild(el.lastchild) } el.appendchild(component) flag = true }}
参数 attributes:
然后你可以在模板中任何元素上使用新的 v-badge property,如下:
<div v-badge.dot.info="badgecount" style="height:50px;width:50px;background:#999"> </div>
9、拖拽指令 v-drag
使用该指令可以对元素进行拖拽。
指令的代码如下:
export default { let _el = el document.onselectstart = function() { return false //禁止选择网页上的文字 } _el.onmousedown = e => { let disx = e.clientx - _el.offsetleft //鼠标按下,计算当前元素距离可视区的距离 let disy = e.clienty - _el.offsettop document.onmousemove = function(e){ let l = e.clientx - disx let t = e.clienty - disy; _el.style.left = l + "px" _el.style.top = t + "px" } document.onmouseup = e => { document.onmousemove = document.onmouseup = null } return false }}
然后你可以在模板中任何元素上使用新的 v-drag property,如下:
<div v-drag> 支持拖拽的元素 </div>
10、响应缩放指令 v-resize
使用该指令可以响应元素宽高改变时执行的方法。
指令的代码如下:
export default { bind(el, binding) { let width = '', height = ''; function isreize() { const style = document.defaultview.getcomputedstyle(el); if (width !== style.width || height !== style.height) { binding.value(); // 执行传入的方法 } width = style.width; height = style.height; } el.__timer__ = setinterval(isreize, 300); // 周期性监听元素是否改变 }, unbind(el) { clearinterval(el.__timer__); }}
参数 attributes:
然后你可以在模板中任何元素上使用新的 v-resize property,如下:
// 传入 resize() 方法<div v-resize="resize"></div>
11、字符串整形指令 v-format
使用该指令可以修改字符串,如使用 v-format.tofixed 保留两位小数、 v-format.price 将内容变成金额(每三位逗号分隔),可以同时使用,如 v-format.tofixed.price。
例如将数字 243112.331 变成 243112.33,或 243,112.33。
指令的代码如下:
export default { update (el, binding, vnode) { const { value, modifiers } = binding if (!value) return let formatvalue = value if (modifiers.tofixed) { formatvalue = value.tofixed(2) } console.log(formatvalue) if (modifiers.price) { formatvalue = formatnumber(formatvalue) } el.innertext = formatvalue },}function formatnumber (num) { num += ''; let strs = num.split('.'); let x1 = strs[0]; let x2 = strs.length > 1 ? '.' + strs[1] : ''; var rgx = /(\d+)(\d{3})/; while (rgx.test(x1)) { x1 = x1.replace(rgx, '$1' + ',' + '$2'); } return x1 + x2}
参数 attributes:
然后你可以在模板中任何元素上使用新的 v-format property,如下:
<div v-format.tofixed.price="123333"> 123 </div>
如何使用这些指令?
为了便于管理指令,我们将每个指令都存在于单独的 js 文件中。在项目的 src 下建一个 directives 目录,目录下新建 index.js 文件用于引入并注册指令。
├── src| ├── directive| | ├── index.js| | ├── backtop.js| | ├── badge.js| | ├── copy.js| | ├── ellipsis.js| | ├── empty.js| | ├── expandclick.js| | ├── screenfull.js| | └── tooltips.js| ├── main.js
举个例子:
directives 目录下新建 ellipsis.js 文件:
export default function (el, binding) { el.style.width = binding.arg || 100 + 'px' el.style.whitespace = 'nowrap' el.style.overflow = 'hidden'; el.style.textoverflow = 'ellipsis';}
directives 的 index.js 文件中引入 ellipsis 指令并注册:
import vue from 'vue'import ellipsis from './ellipsis' // 引入指令// import other directivesconst directives = { ellipsis // other directives}object.keys(directives).foreach(name => vue.directive(name, directives[name]))
最后在 mian.js 中引入 index.js 文件:
import '@/directives/index'
这样就可以正常使用这些指令了:
import '@/directives/index'
更多编程相关知识,请访问:编程入门!!
以上就是分享一些vuejs中常用的自定义指令(总结)的详细内容。
