一、属性侦听器
watch:与data同级。watch中写函数,函数名与数据源中的属性名一致。当属性发生改变时,会执行watch中对应的函数。
<div id="app">
<p>信息---{{msg}}-条</p>
<button @click="change">改变</button><br>
<span>{{person.name}}-----{{person.age}}</span>
<button @click="add">增加</button>
</div>
<script>
const app = {
data() {
return {
msg:1,
person:{name:'tom',age:21}
}
},
methods:{
change(){this.msg++},
add(){this.person.age++}
},
// 属性侦听器
watch:{
msg(){console.log('改变了')},
person(){console.log(111)}
// person:{
// handler:function(){console.log('深度监听')},
// deep:true
// }
}
}
Vue.createApp(app).mount('#app')
</script>
当点击两个按钮时,就会发现watch中msg函数执行了,但person却没有执行,这时因为侦听器只能监听数据源的属性,里面的age是属性的属性了,就无法侦听。如果需要这项功能,那么person就不能写作函数,而应该是对象,里面有两个属性handler和deep,handler是处理函数,可以有两个形参,接收的值是新值和旧值。deep的布尔值决定是否深度监听,true则深度监听。
二、生命周期函数
vue在运行中某一时刻,vue帮我们运行对应的函数,这个函数就是钩子,也称为生命周期函数。
beforeCreate(创建前):当this对象创建前执行。 此时数据源和方法等等均无法使用,因为此时还没有this对象。
created(创建后):当this对象创建完毕执行,数据源和方法等等都可以使用。不能操作页面,无法得到想要的文档树节点对象。
这里要明白一个点是,我们在模板中绑定的属性变量以及插值表达式中的值,表面上看着是data返回的对象中的属性值,但其实是this中的属性值。vue实例创建后只是使用了data返回对象,将里面的所有属性都给了一份给this,并且把methods中的方法也给了一份给this,相当于把这些数据复制给this,所以this中有data返回对象的属性以及methods中的方法。所以我们才可以通过this修改属性值以及调用methods中的方法。
beforeMount(挂载前):挂载之前。不要操作DOM。 可以访问this成员。
mounted(挂载后):在页面渲染完后再执行,已经挂载完毕。可以访问this的成员。可以操作DOM。
beforeUpdate(更新前):数据源改变后,页面更新前。指页面更新,而不是数据更新,页面中操作数据导致页面更新后,在这里面打印数据,是更新后的数据。
updated(更新后):数据源改变后,页面已经更新完毕。可以访问this成员。
beforeUnmount(卸载前):this对象释放前。可以访问this成员。
unmount(卸载后):this对象释放完毕后。无法访问this的成员。
<div id="app">
<p>{{msg}}</p>
</div>
<script>
const app = {
data() {
return {msg:'hello'}
},
beforeCreate(){console.log('beforeCreate')},
created(){console.log('created')},
beforeMount(){console.log('beforeMount')},
mounted(){console.log('mounted')},
beforeUpdate(){console.log('beforeUpdate')},
updated(){console.log('updated')},
// vue2.0中是beforeDestroy,destroyed
beforeUnmount(){console.log('beforeUnmount')},
unmount(){console.log('unmount')}
}
Vue.createApp(app).mount('#app')
</script>
从运行结果中可以看出,页面第一次渲染执行的生命周期函数是4个:beforeCreate、created、beforeMount、mounted。在整个vue运行期间,beforeCreate、created、beforeMount、mounted、beforeUnmount、unmounted只会执行一次。
三、自定义指令
directives对象:与data同级。自定义指令要在directives中注册后才能使用。自定义指令后面可以有等号,也可以没有,如果要获取等号后面的值,mounted函数添加第二个参数bind,bind.value可以获取。第一个参数是指令所在的元素。
<div id="app">
<p v-zjy>自定义指令</p>
<p v-name="own">有等号</p>
</div>
<script>
const VueApp = {
data(){
return { own:'自定义' }
},
directives:{
zjy:{
mounted(el){
el.style.color = 'red'
}
},
name:{
mounted(el,bind){
el.style.color = 'red'
console.log(el,bind.value)
}
}
}
}
Vue.createApp(VueApp).mount('#app')
</script>
四、组件
components对象:与data同级。在components对象中注册组件,属性名就是组件名,组件对象中有一个template属性,属性值为字符串,也就是一个模板,类似id名为app的div,那么这个组件就也有自己的数据源、methods、computed、watch等等。
<div id="app">
<box></box>
</div>
<script>
const VueApp = {
data(){
return {}
},
components:{
box:{
template:`
<div>
<h1>{{msg}}</h1>
</div>`,
data(){
return { msg:'组件的数据源' }
}
}
}
}
Vue.createApp(VueApp).mount('#app')
</script>
五、全局与局部的指令和组件
全局指令和全局组件是能够在每一个模板中都能使用,局部指令和局部组件只能在所在的模板中使用。
<div id="app">
<box></box>
<p v-name>自定义指令</p>
<box3></box3>
<p v-own>全局指令--1</p>
</div>
<script>
const VueApp = {
data(){
return {}
},
directives:{
// 局部指令:在下面的box组件中不能使用
name:{
mounted(el){
el.style.color = 'red'
}
}
},
components:{
// 局部组件:在下面的box组件的模板中不能使用
box:{
template:`
<div>
<h1>{{msg}}</h1>
<box3></box3>
<p v-own>全局指令--2</p>
</div>
`,
data(){
return { msg:'组件的数据源' }
}
}
}
}
let v = Vue.createApp(VueApp)
// 全局指令
v.directive('own',{
mounted(el){
el.style.color = 'orange'
}
})
// 全局组件
v.component('box3',{
template:'<div>box3</div>'
})
v.mount('#app')
</script>