每日三问之Vue.directive自定义指令、vue中install方法、闭包应用场景

28 篇文章 0 订阅
24 篇文章 0 订阅

Vue.directive自定义指令 

  • 钩子函数 
<span v-pang>{{num}}</span>

directives: {
    pang: {
      // 指令的定义
      bind: function (el, bind, vnode) {
        console.log('el', el)
        console.log('bind', bind)
        console.log('vnode', vnode)
      },
      inserted: function (el) {
        el.focus()
        //绑定到节点
        console.log('2 - inserted')
      },
      update: function () {
        //组件更新
        console.log('3 - update')
      },
      componentUpdated: function () {
        //组件更新完成
        console.log('4 - componentUpdated')
      },
      unbind: function () {
        //解绑
        console.log('5 - unbind')
      }
    }
  },

案例

仿v-show

<span v-pang-show="show">{{num}}</span>

directives: {
   pangShow: {
      // 指令的定义
     bind: function (el, bind, vnode) {
        if (bind.value) {
          el.style.display = 'block'
        } else {
          el.style.display = 'none'
        }
  }
}

 权限控制v-permission

const permission={
    inserted(el, binding, vnode) {
        const { value } = binding
        const roles = ['editor','admin']
        if (value && value instanceof Array && value.length > 0) {
            const permissionRoles = value
            const hasPermission = roles.some(role => {
                return permissionRoles.includes(role)
            })
            if (!hasPermission) {
                el.parentNode && el.parentNode.removeChild(el)
            }
        } else {
            throw new Error(`need roles! Like v-permission="['admin','editor']"`)
        }
    }
}

Vue.directive('permission', permission)

vue中install方法

vue提供install可供我们开发新的插件及全局注册组件等
install方法第一个参数是vue的构造器,第二个参数是可选的选项对象

export default {
	install(Vue,option){
		组件
		指令
		混入
		挂载vue原型
	}
}
MyPlugin.install = function (Vue, options) {
  // 1. 添加全局方法或属性
  Vue.myGlobalMethod = function () {
    // 逻辑...
  }

  // 2. 添加全局资源
  Vue.directive('my-directive', {
    bind (el, binding, vnode, oldVnode) {
      // 逻辑...
    }
    ...
  })

  // 3. 注入组件
  Vue.mixin({
    created: function () {
      // 逻辑...
    }
    ...
  })

  // 4. 添加实例方法
  Vue.prototype.$myMethod = function (methodOptions) {
    // 逻辑...
  }
}

全局注册组件

// index.js
import PageTools from '@/components/PageTools/pageTools.vue'
import update from './update/index.vue'
import ImageUpload from './ImageUpload/ImageUpload.vue'
import ScreenFull from './ScreenFull'
import ThemePicker from './ThemePicker'
import TagsView from './TagsView'
export default {
  install(Vue) {
    Vue.component('PageTools', PageTools)
    Vue.component('update', update)
    Vue.component('ImageUpload', ImageUpload)
    Vue.component('ScreenFull', ScreenFull)
    Vue.component('ThemePicker', ThemePicker)
    Vue.component('TagsView', TagsView)
  }
}

// main.js
import Component from '@/components'
Vue.use(Component)

全局自定义指令

// index.js
export default{
	install(Vue){
		Vue.directive('pre',{
			inserted(button,bind){
				button.addEventListener('click',()=>{
					if(!button.disabled){
						button.disabled = true;
						setTimeout(()=>{
							button.disabled = false
						},1000)
					}
				})
			}
		})
	}
}

// main.js
import pre from '@/aiqi'
Vue.use(pre)

闭包应用场景

  • 什么是闭包

有权访问另一个函数作用域内变量的函数都是闭包。

  • 闭包特性

1、函数嵌套函数
2、函数内部可以引用函数外部的参数和变量
3、参数和变量不会被垃圾回收机制回收

a()中的返回值是一个匿名函数,这个函数在a()作用域内部,所以它可以获取a()作用域下变量name的值,将这个值作为返回值赋给全局作用域下的变量b,实现了在全局变量下获取到局部变量中的变量的值

methods: {    
    init() {
      var name = 'jack'
      return function () {
        return name
      }
    }
}

mounted() {
    console.log(this.init()()) // jack
}

闭包经典案例

一般情况下,在函数fn执行完后,就应该连同它里面的变量一同被销毁,但是在这个例子中,匿名函数作为fn的返回值被赋值给了fn1,这时候相当于fn1=function(){var n = 0 … },并且匿名函数内部引用着fn里的变量num,所以变量num无法被销毁,而变量n是每次被调用时新创建的,所以每次fn1执行完后它就把属于自己的变量连同自己一起销毁,于是乎最后就剩下孤零零的num,于是这里就产生了内存消耗的问题

methods: {  
  fn() {
      var num = 3
      return function () {
        var n = 0
        console.log(++n)
        console.log(++num)
      }
    }
}

mounted() {
   var fn1 = this.fn()
   fn1() // 1 4
   fn1() // 1 5
}

 按照预期它应该依次输出1 2 3 4 5,而结果它输出了五次5,这是为什么呢?原来由于js是单线程的,所以在执行for循环的时候定时器setTimeout被安排到任务队列中排队等待执行,而在等待过程中for循环就已经在执行,等到setTimeout可以执行的时候,for循环已经结束,i的值也已经编程5,所以打印出来五个5,那么我们为了实现预期结果应该怎么改这段代码呢?(ps:如果把for循环里面的var变成let,也能实现预期结果)

for(var i = 0;i<5;i++){
    (function(i){
         setTimeout(function(){
            console.log(i)
        }, i*100)
    })(i)
}
  

// 等同于 let
for(let i = 0;i<5;i++){
    setTimeout(function(){
        console.log(i)
    }, i*100)
}

闭包应用场景

https://www.jb51.net/article/203104.htm

总结 

闭包就是一个函数引用另外一个函数的变量,因为变量被引用着所以不会被回收,因此可以用来封装一个私有变量。这是优点也是缺点,不必要的闭包只会徒增内存消耗!

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值