Vue进阶属性:directives指令、mixins混入、extends继承、provide提供、inject注入
directives指令
自定义指令
一,声明一个全局指令
Vue.directive('x',directiveOptions)
你就可以在任何组件里用v-x了
例子:元素在插入到页面时,就绑定click事件
Vue.directive('x',{
inserted:function(el){
el.addEventListener('click',()=>{
console.log('x')
})
}
})
二,声明一个局部指令,只能在这个组件里使用
export default{
name:'hello',
directives:{
'x':{
inserted(el){
el.addEventListener('click',()=>{})
}
}
}
}
directiveOptions
五个函数属性
bind(el,info,vnode,oldVnode) -类似created
inserted(el,info,vnode,oldVnode)-类似mounted
update(el,info,vnode,oldVnode)-类似updated
componentUpdated(el,info,vnode,oldVnode)- 用的不多
unbind(el,info,vnode,oldVnode)- 类似destroyed
举例:
new Vue({
directives:{
//声明on2指令
on2:{
inserted(el,info){
console.log(info)
//info.value是用户传来的值,这里会接到一个方法
el.addEventListener(info.arg, info.value)
},
//元素销毁时
unbind(el,info){
//解绑事件
el.removeEventListener(info.arg, info.value)
}
}
},
template:`
<button v-on2:click="hi">点我</button>
`,
methods:{
hi(){
console.log('hi')
}
}
})
如何缩写下面这部分?其实一般不缩写的!如何写请查文档!
inserted(el,info){
console.log(info)
//info.value是用户传来的值,这里会接到一个方法
el.addEventListener(info.arg, info.value)
},
//元素销毁时
unbind(el,info){
//解绑事件
el.removeEventListener(info.arg, info.value)
}
指令的作用
主要用于DOM操作
Vue实例/组件用于数据绑定、事件监听、DOM更新
Vue指令主要目的就是原生DOM操作
减少重复
如果某个DOM操作你经常使用,就可以封装为指令
如果某个DOM操作比较复杂,也可以封装为指令
mixins混入
类比
directives的作用是减少DOM操作的重复
mixins的作用是减少data、methods、钩子的重复
场景
假设我们需要在每个组件上添加name和time
在created时,打出提示,并报出存活时间
一共有五个组件,请问你怎么做?
1 给每个组件添加dat和钩子,共五次
2 或者使用mixins减少重复
创建mixins文件夹和其下面的log.js文件
const log = {
//data里的属性会自动和下方Child1.vue的属性智能合并,undefined会被值:Child1覆盖掉
data(){
return{
name:undefined,
time:undefined
}
},
created(){ //created也会智能合并
//如果this.name不存在
if(!this.name){
throw new Error('需要name')
}
this.time = new Date()
console.log(`${this.name}出生了`)
},
beforeDestroy(){
const now = new Date()
console.log(`${this.name}死亡了,共生存了${now - this.time}`)
}
}
export default log
有Child1.vue,Child2.vue,Child3.vue,Child4.vue,Child5.vue
每个文件里,都导入log
这是Child1.vue:
<script>
import log from '../mixins/log.js'
export default{
data(){
return {
name:'Child1'
}
},
mixins:[log] //等于把log及其内容复制到了这里
}
</script>
所以每个vue组件内都有了log的内容。
如果所有组件都要有log功能
可以在main.js中使用Vue.mixin
Vue.mixin({
data(){
return{
name:undefined,
time:undefined
}
},
created(){ //created也会智能合并
//如果this.name不存在
if(!this.name){
throw new Error('需要name')
}
this.time = new Date()
console.log(`${this.name}出生了`)
},
beforeDestroy(){
const now = new Date()
console.log(`${this.name}死亡了,共生存了${now - this.time}`)
}
})
全部组件就自动有了这些内容了。
这个方式不太好!
Extends 继承、扩展
实现与mixins同样的需求
声明一个MyVue.js
import Vue from 'vue'
const MyVue = Vue.extend({ //关键词extend
data(){
return{
name:undefined,
time:undefined
}
},
created(){ //created也会智能合并
//如果this.name不存在
if(!this.name){
throw new Error('需要name')
}
this.time = new Date()
console.log(`${this.name}出生了`)
},
beforeDestroy(){
const now = new Date()
console.log(`${this.name}死亡了,共生存了${now - this.time}`)
}
})
Child1.vue
import MyVue from '../MyVue.js'
export default{
extends:MyVue, //关键词
data(){}
}
extends是比mixins更抽象一点的封装,用得少
Provide提供 和 Inject注入
换肤例子
App.vue
<template>
<div :class="`app theme-${themeName}`">
<Child1 />
</div>
</template>
<script>
export default{
name:"App",
data(){
return {
themeName:"blue",
fontSize:"normal"
}
}
}
</script>
components文件夹下的ChangeThemeButton.vue文件
<template>
<div>
<button>换肤</button>
</div>
</template>
components文件夹下的Child1.vue文件,另外还有Child2.vue,Child3.vue,Child4.vue,Child5.vue
<template>
<div>Child1
<change-theme-button /> //注意这里的大小写
</div>
</template>
<script>
import ChangeThemeButton from "./ChangeThemeButton.vue" //引入文件
export default{
components:{
ChangeThemeButton //大小写
}
}
</script>
问题来了,在ChangeThemeButton.vue里,如何改变App.vue的data来让皮肤变色???
答:用provide
App.vue:
<template>
<div :class="`app theme-${themeName}`">
<Child1 />
</div>
</template>
<script>
export default{
name:"App",
//提供一个themeName的复制品出去
provide(){
return {
themeName:this.themeName,//这里提供出去的只是一个新的值,所以那边改也无效,除非提供出去的是引用,但是不推荐,因为容易失控
changeTheme:this.changeTheme
}
},
data(){
return {
themeName:"blue",
fontSize:"normal"
}
},
methods:{
changeTheme(){
if(this.themeName === 'blue'){
this.themeName = 'red'
}else{
this.themeName = 'blue'
}
}
}
}
</script>
ChangeThemeButton.vue
<template>
<div>
<button @click="x">换肤</button>
</div>
</template>
<script>
export default{
inject:['themeName','changeTheme'], //注入上面代码提供的themeName
methods:{
x(){
this.changeTheme()
}
}
}
</script>
总结
作用:共用大范围的data和method
注意:不能只传themeName不传changeTheme,因为themeName的值是被复制给provide的
资料来源:饥人谷