一、Directives 指令
- v-开头,v-if、v-for、v-show等是内置属性
1、构造一个指令
- 声明一个全局指令
Vue.directive('x',{
inserted:function(el){
el.addEventListener('click',()=>{console.log('x')})
}
})
- 声明一个局部指令
- 想用在哪个实例,就在哪个实例选项中添加directives这项
new Vue({
...,
directives:{
x:{
inserted(el){
el.addEventListener('click',()=>{console.log('x')})
}
}
}
})
2、directiveOptions属性
2.1、属性
- bind:只调用一次,指令第一次绑定到元素时调用
- inserted:被绑定元素插入父节点时调用(仅保证父节点存在)
- unbind:只调用一次,指令与元素解绑时调用
- 几乎不用的有两个,update、componentUpdated
2.2、参数
- bind(el,info,vnode,oldVnode)
- el:绑定的元素
- info:除元素外其他的详细信息
- vnode:元素对应的虚拟节点
- oldVnode:之前的虚拟节点
- directiveOptions属性都有这四个参数
3、自制v-on指令
<button v-on:click="hi">点我</button>,这个按钮被点击后,打印出“hi”,自制v-on2
new Vue({
directives:{
on2:{
inserted(el,info){
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')
}
},
})
4、总结
- 指令的主要目的就是原生DOM操作,数据绑定、事件监听、DOM更新等
- 如果某个DOM操作经常使用(或比较复杂),就可以封装为指令
二、mixins 混入
- 减少data、methods、钩子(即构造选项)的重复,可以理解为复制
- 用代码理解mixins;需求:有5个组件,都要对其添加name和记录存活时长
- App.vue
<template>
<div id="app">
<Child1 v-if="child1Visible" />
<button @click="child1Visible=false">消亡</button>
...
<Child5 v-if="child5Visible" />
<button @click="child5Visible=false">消亡</button>
</div>
</template>
<script>
import Child1 from "./components/Child1.vue";
...
import Child5 from "./components/Child5.vue";
export default{
name:"App",
data(){
return{
child1Visible:ture,
...
child5Visible:ture,
}
},
components:{
Child1,
...
Child5,
}
}
</script>
<style>
...
</style>
- 新建mixins目录,新建log.js文件(将共有的data、created、beforeDestroy放入)
const log={
data(){
return{
name:undefined,
time:undefined
}
},
created(){
if(this.name===undefined){
throw new Error("need name")
}
this.time=new Date()
console.log(`${this.name}出生了`)
},
beforeDestroy(){
const now=new Date()
console.log(`${this.name}消亡了,共生存了${now-this.time}ms`)
}
}
export default log
- Child1.vue
<template>
<div>Child1</div>
</template>
<script>
import log from '../mixins/log.js'
export default{
data(){
return{
name:"Child1"
}
},
mixins:[log]
}
</script>
三、extends 继承
- 比mixins更抽象的封装,也可以理解为复制,只是形式不一样(推荐用mixins)
- 延用上一个需求,换extends实现
- 新建MyVue.js文件
import Vue from "vue"
const MyVue=Vue.extend({
data(){
return{
name:undefined,
time:undefined
}
},
created(){
if(this.name===undefined){
throw new Error("need name")
}
this.time=new Date()
console.log(`${this.name}出生了`)
},
beforeDestroy(){
const now=new Date()
console.log(`${this.name}消亡了,共生存了${now-this.time}ms`)
}
})
export default MyVue
- Child1.vue
<script>
import MyVue from "../MyVue.js"
export default{
extends:MyVue,
data(){
return{
name:"Child1"
}
}
}
</script>
四、provide 提供 inject 注入
- provide:提供大范围共用的data和methods等
- inject:隔代共享provide提供的信息
- 用代码理解provide和inject;需求:一键换肤
- App.vue
<template>
<div:class="`app theme-${themeName}`">
<Child1 />
</div>
</template>
<script>
import Child1 from "./components/Child1.vue";
export default{
name:"App",
provide(){
return{
themeName:this.themeName,
changeTheme:this.changeTheme
}
},
data(){
return{
themeName:"blue"
}
},
methods:{
changeTheme(){
if(this.themeName==='blue'){
this.themeName='red'
}else{
this.themeName='blue'
}
}
},
components:{
Child1
}
}
</script>
<style>
...
</style>
- ChangeThemeButton.vue
<template>
<div>
<button @click="z">换肤</button>
</div>
</template>
<script>
export default{
inject:['themeName','changeTheme'],
methods:{
z(){
this.changeTheme()
}
}
}
</script>
- Child1.vue
<template>
<div>Child1
<change-theme-button /> //这样的写法Vue支持
</div>
</template>
<script>
import ChangeThemeButton from "./ChangeThemeButton.vue";
export default{
components:{
ChangeThemeButton
}
}
</script>