持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第22天,点击查看活动详情
自定义指令
现有一个输入框:
<div id="app">
<input type="text" id="it">
</div>
若是想在刷新页面后自动获取输入框的焦点,该如何实现呢?
其实非常简单,可以调用输入框的 focus 函数:
<div id="app">
<input type="text" id="it">
</div>
<script>
document.getElementById('it').focus();
</script>
但Vue不推荐我们直接操作DOM,所以我们可以将其转化为自定义的指令:
<div id="app">
<input type="text" v-focus>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 自定义指令
Vue.directive('focus', {
// 当指令绑定到指定元素上时调用此函数,只执行一次
bind(el) { // el即为绑定该指令的元素
},
// 当元素插入到DOM时调用此函数,只执行一次
inserted(el) {
el.focus();
},
// 当元素更新时调用此函数,执行多次
updated(el) {
}
});
</script>
这里需要注意,自定义指令通过 Vue.directive 进行设置,它需要两个参数,第一个参数为指令的名称,第二个参数为一个对象,在该对象内需要定义指令生效的三个周期函数,周期函数的入参中可以获取到绑定该指令的元素,然后调用 focus 获取焦点即可。
\
在使用该指令时也需要注意,必须在自定义的指令名前加上 v- 前缀。
\
那么自定义指令该如何实现传值呢:
<div id="app">
<input type="text" v-color="'red'">
</div>
自定义一个v-color指令,并根据传递的参数值设置输入框的字体颜色, 实现如下:
<script>
// 自定义指令
Vue.directive('color', {
// 当指令绑定到指定元素上时调用此函数,只执行一次
bind(el,binding) { // el即为绑定该指令的元素
el.style.color = binding.value;
},
// 当元素插入到DOM时调用此函数,只执行一次
inserted(el) {
},
// 当元素更新时调用此函数,执行多次
updated(el) {
}
});
</script>
通过周期函数的第二个参数 binding ,我们能够获取到很多信息,其中value属性即为指令设置的值,将该值设置到样式中即可。
\
刚才定义的是全局指令,我们也可以定义只属于某个Vue实例本身的私有指令,与过滤器类似,只需在Vue实例中定义即可:
<script>
var app = new Vue({
el: '#app',
data: {
},
directives: {
// 自定义私有指令
'color': {
// 当指令绑定到指定元素上时调用此函数,只执行一次
bind(el, binding) { // el即为绑定该指令的元素
el.style.color = binding.value;
},
// 当元素插入到DOM时调用此函数,只执行一次
inserted(el) {
},
// 当元素更新时调用此函数,执行多次
updated(el) {
}
}
}
});
</script>
Vue还提供了一种更简便的方式来自定义指令:
<script>
Vue.directive('Vue', function (el,binding) {
el.style.color = binding.value;
});
</script>
但这种方式只会生效于bind和updated周期函数,它等同于将函数中的代码在bind和updated函数中均粘贴一份。
Vue实例的生命周期
Vue实例从创建、运行到销毁期间,总是伴随着各种各样的事件,这些事件统称为生命周期,生命周期大体被分为三类:
- 创建期间的生命周期
- 运行期间的生命周期
- 销毁期间的生命周期
其中创建期间的生命周期函数又有以下几个:
- beforeCreate:实例刚在内存中被创建出来,此时,还没有初始化好data和methods属性
- created:实例已经在内存中创建好,此时data和methods也已经创建好,但还没有编译模板
- beforeMount:此时已经完成了模板的编译,但是还未加载到页面中
- mounted:将已经编译好的模板挂载到页面指定的容器中显示
运行期间的生命周期函数:
- beforeUpdate:状态更新之前执行此函数,此时data中的状态值是最新的,但是界面上显示的数据还是旧的,因为此时还未重新渲染DOM
- updated:实例更新完毕后调用此函数,此时data中的状态值和界面上显示的数据都已经完成了更新,界面已经重新渲染
销毁期间的生命周期:
- beforeDestroy:实例销毁之前调用,实例仍然完全可用
- destroyed:实例销毁之后调用,调用完成后,Vue实例指示的所有东西都会解除绑定,所有的事件监听器会被移除,所有的子实例也会被销毁
\
先来测试一下beforeCreate函数:
<script>
var app = new Vue({
el: '#app',
data: {
msg: 'success'
},
methods: {
show() {
console.log('执行了show函数...');
}
},
// Vue实例完全被创建好之前执行此函数
beforeCreate() {
console.log('执行了beforeCreate函数---' + this.msg);// 无法访问msg数据
this.show();// 无法调用show函数
},
});
</script>
由于此时Vue实例并没有被完全创建好,所以Vue实例中的data和methods属性均无法访问,执行结果如下:
再看created函数:
<script>
var app = new Vue({
el: '#app',
data: {
msg: 'success'
},
methods: {
show() {
console.log('执行了show函数...');
}
},
// Vue实例完全被创建好之后渲染模板之前调用此函数
created() {
console.log('执行了created函数---' + this.msg);
this.show();
},
});
</script>
此时Vue实例已经完全创建好,当然就可以访问data和methods了,执行结果如下:
beforeMount函数:
<div id="app">
<p id="p">{{msg}}</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
msg: 'success'
},
methods: {
show() {
console.log('执行了show函数...');
}
},
// 模板编译完成后页面加载之前执行此函数
beforeMount() {
console.log('执行了beforeMount函数---' + document.getElementById('p').innerText);
},
});
</script>
该函数在模板编译完成后页面加载之前执行,所以我们获取到p标签的数据是还未加载数据的内容,执行结果:
mounted函数:
<script>
// 页面加载完成后执行此函数
mounted() {
console.log('执行了mounted函数---' + document.getElementById('p').innerText);
},
</script>
该函数在页面加载完成后执行,所以它能够获取到页面渲染后的真正数据,执行结果:
当mounted函数执行完成后,就表示Vue实例被真正地创建完成了。
\
再来看看运行期间的生命周期函数,首先是beforeUpdate函数:
<div id="app">
<p id="p">{{msg}}</p>
<input type="button" value="修改msg值" @click="msg='Fail'">
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
msg: 'success'
},
methods: {
show() {
console.log('执行了show函数...');
}
},
// data数据更新后但界面更新之前执行此函数
beforeUpdate() {
console.log('执行了beforeUpdate函数---');
console.log('页面上的数据---' + document.getElementById('p').innerText);
console.log('data中的数据---' + this.msg);
},
});
</script>
在该页面上显示了一个p标签,并能通过点击按钮修改data中的数据值,此时执行结果:
当点击按钮后,该函数获取到的页面数据仍然是success,而data中的数据发生了变化,这说明该函数在页面重新渲染之前会执行,但此时data中的数据是最新的。
\
updated函数:
<script>
updated() {
console.log('执行了updated函数---');
console.log('页面上的数据---' + document.getElementById('p').innerText);
console.log('data中的数据---' + this.msg);
}
</script>
执行结果:
该函数在页面重新渲染之后执行,所以页面和data中获取到的数据都是最新的。
\
最后是销毁阶段的生命周期函数,其中beforeDestroy函数是在销毁之前被执行的,在该函数中仍然可以使用Vue实例中的属性,此时还没有真正地销毁Vue实例,只有在destroyded函数执行完成后才真正地销毁了Vue实例。