Vue进阶构造属性

105 阅读3分钟

一、Directives指令

内置指令

  • v-if v-for v-show v-html等

自定义指令

  • 声明全局指令:Vue.directive('x',directiveOptions)
Vue.directive('x', {
    inserted: function(el) {
        el.addEventListener('click', () => { console.log('x') })
    }
})  //自定一个v-x指令,当元素出现在页面时,执行console.log函数
  
  • 局部声明
    • 单个组件的构造选项中加入,只能在当前组件中使用
directives:{
    x:{
        inserted(el){
            el.addEventListener("click",()=>{console.log('x')})
        }
    }
}

directiveOptions的五个属性

- bind (el,info,vnode,oldVnode)-类似created
- inserted  - 类似mounted
- updated    - 类似updated
- componentUpdated   - 不常用
- unbind  - 类似destroyed

举例

  • 自制v-on2指令模仿 v-on (简化版)
    • 指令 v-on2:click='hi'
    • methods:{ hi(){....}}
    • 构造选项
directives:{
    'on2':{
        inserted(el,info){     //接收两个参数
            console.log(info)   //打印出info,
            el.addEventListener(info.arg,info.value)  //info.args就是事件  //info.value就是事件触发后的方法
        },
        unbind(el,info){       //将事件监听清理
            console.log(info)
            el.addEventListener(info.arg,info.value)
        }
    }
}

小结

指令的作用

  • 主要用于DOM操作
    • Vue实例/组件用于数据绑定、事件监听、DOM更新
    • Vue指令主要目的就是原生DOm操作
  • 减少重复
    • 如果某个DOM操作经常使用,就可以封装为指令
    • 如果某个DOM操作复杂,也可以封装为指令

二、mixins 混入/复制

类比

  • directives的作用是减少DOm操作的重复
  • mixins的作用是减少data、methods、钩子的重复

场景描述

  • 多个子组件实现相同的功能
  • 常规操作是在子组件export default{}中写入相同的data,methods,钩子等,造成代码的重复
  • mixin:将这些重复的功能放入某个js文件的对象中
  • 子组件直接引入这个对象并在构造选项中声明mixin的对象就可以了 示例:以下代码为抽象说明
    常规操作:各个子组件重复相同的选项
子组件相同功能
export default{
data(){},

methods:{},

各种钩子...
}


  • mixins作
//新建log.js文件
const log={重复的选项:data,methods,钩子...}
export default log
//各个组件
import log from 'log.js文件路径'
export default{
mixins:[log]
}
  • 补充:mixins会智能合并组件中的内容

extends 继承

  • 类似mixins,应用场景与上个场景类似 新建MyVue.js
import Vue from 'vue'
const MyVue=Vue.extends({
  公共的选项
  data
  method等
})
export default MyVue

各组件中

import  MyVue from 'MyVue.js的url'
export default{
    extends:MyVue           
    }

provide和inject (提供和注入)

场景

  • 父组件app.vue中有数据number
  • 子组件child.vue要改变父组件中的number,但前提是只能改变自己的数据
  • 因此需使用provide和inject
父组件
<template>
<div>
{{number}}   //父组件中的number

<child-button />  //子组件按钮
</div>

</template>

<script>
export default{
  provide(){
    return { number: this.number,//将number提供给子组件
             changeNumber:this.changeNumber  //将修改number函数提供给子组件
             }  
  },
  methods:{
    changeNumber(){修改number操作}   //修改number
 }
  data(){
return {number:'oldNumber'}    //被修改的数据
  },
  
  
}
</script>
子组件
<template>
   <div>
   <button @click='changeNumber'>ChangeNumber</button> 
   </div>

</template>

<script>
  export default{
inject:['number''changeNumber']     //把父组件提供的number和函数注入
                     
  
}
</script>


  • 补充说明:
    • number虽然提供给了子组件,但是子组件不能自己提供方法来修改,因为子组件拿到的是oldNUmber字符串,是复制品,修改之后并不能作用于父组件
    • 因此,父组件提供改变number的方法,子组件得到引用,触发方法改变number的值
    • 强行改number的方法
      • 由于是复制品,想办法拿到引用,而不是复制品
      • 父组件data中直接return number:{value:'oldNumber'}
      • 这样子组件拿到的是对象的引用(即地址),在子组件中顺着地址修改对象值,父组件中也会顺着地址找到对象,此时的值就变了
      • 示意图

f79bc3ee8c1922bf01be2f9620a0666.png

  • 此方法不建议使用,因为涉及到太多变量,容易混乱

小结

- provide和inject的作用是大范围的data和method等共用