浅析Vue的directive mixins extend 和 provide inject

292 阅读3分钟

directive

在vue中,我们可以使用各式各样的指令,而不要去考虑DOM操作,例如v-text,v-html,v-on,v-bind等。

但有时候我们还是想要去实现一些自定义的DOM操作,这时候,我们就可以通过directive来封装一些vue没有的指令。

指令主要基于DOM操作,可以有效的减少重复的DOM操作

  • 声明全局指令
/*****在main.js中声明*****/
Vue.directive('example',{
  inserted(el){
  /*****el为写v-example的那个元素*****/
    el.addEventListener('click',()=>{
      console.log('hello')
    })
  }
})

<template>
  <section>
    <button v-example>hello</button>
  </section>
</template>
  • 声明局部指令
<script>
  export default {
    directives: {
      example: {
        inserted(el) {
          el.addEventListener('click', () => {
            console.log('hello')
          })
        }
      }
    }
  }
</script>

<template>
  <section>
    <button v-example>hello</button>
  </section>
</template>

可以看到,在上面的例子中,我们使用了inserted,另外directives也支持其他的属性。

下面,我们来看一下directive的其他常用属性

  • bind——类似于created
  • inserted——类似于mounted
  • update——类似于updated
  • componentUpdate——指令所在组件的 VNode 及其子 VNode 全部更新后调用(例如一个元素使用了v-show,再使用componentUpdate就会触发)
  • unbind——类似于destoryed

以上这些属性都可以接受4个参数

  • el——那个节点被写上 v-xxx el就是哪个节点
  • info——info内有许多属性,平时我们用得到的属性基本都在info中

  • vnode——Vue 编译生成的虚拟节点
  • oldVnode——上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。

自己简单的实现一个v-on

<template>
  <section>
    <div>{{n}}</div>
    <button v-on2:click="add" >+1</button>
  </section>
</template>

<script>
  export default {
    data(){return{n:0}},
    directives: {
      on2: {
        inserted(el,info){
          el.addEventListener(info.arg,info.value)
        },
        unbind(el,info){
          el.removeEventListener(info.arg,info.value)
        }
      }
    },
    methods:{
      add(){this.n+=1}
    }
  }
</script>

mixins

minxins 我们可以简单的将其理解为 “复制”。

上面我们提到过directive是为了减少DOM操作,mixins 也类似,只不过他是为了减少data methods 钩子的重复

使用时机:多次使用相同的data/methods/钩子

下面我们来看一下如何使用mixins

//js中
const log = {
  data() {
    return {
      content: '内容',
      time: undefined,
      name:undefined
    }
  },
  created() {
    this.time = new Date()
    console.log(`${this.name}被创造出来了`)
  },
  beforeDestroy() {
    const now = new Date()
    console.log(`${this.name} 消失了,存活了 ${now - this.time} ms`)
  }
}

export default log
//导出对象


//组件中
<script>
  import Log from '../mixins/log.js'
  //引入
  export default {
    data() {
      return {name: 'content'}
    },
    mixins: [Log]
    //使用引入的对象
  }
</script>

我们可以看到,上面引入的对象中,name为undefined,但我们想用不同的name是,只需要中组件中再次声明一个name,mixins就会智能合并


extends

extends 类似于 mixins ,也可以理解为复制,只不过,extends 是使用继承来实现的。

使用extends只需要两步

//第一步
//在js文件中创建原型
const xxx = Vue.extends({})

//第二步
//在组件的构造选项中使用它
extends: xxx

provide 和 inject

provide(提供) 和 inject(注入) 可以实现大范围的数据/方法共用

//在一个实例的构造选项中
provide(){
    xxx : this.xxx
}

//在另一个实例的构造选项中
inject : ['xxx']

一般在使用provide时,推荐传入方法,不建议传对象(因为对象是地址引用,容易失控)