1.实现业务
当我们点击按钮,就会切换h1标签的语句内容,再次点击按钮,h1标签的语句内容就会恢复,每次点击按钮,浏览器都会输出一个语句来表达监视到了h1的内容改变
2.Vue中的computed计算属性
2.1利用Vue中的computed计算属性实现业务
<body>
<!-- 给一个容器 -->
<div id="root">
<!-- 因为info是一个计算属性,所以当Vue初次解析模板是就会输出info的返回值 -->
<h1>今天的天气很{{info}}</h1>
<!-- 事件绑定时:@xxx="yyy" yyy可以是一些简单的语句 -->
<button @click="isHot = !isHot">切换天气</button>
</div>
<script>
Vue.config.productionTip = false; // config是Vue的配置选项,这里表示不让vue产生额外的提示信息
const vm = new Vue({
el:'#root',
data:{
isHot: true // 作为info的变化媒介
},
computed:{
info(){
console.log('@----','isHot改变了') // 这里用于体现监听效果
return this.isHot ? '炎热' : '凉爽'
}
}
})
</script>
</body>
上面注意一个小点,就是在事件绑定的时候,处理值可以是一些简单的执行语句,其余情况还是用方法调用的方式比较友好,上面代码等同于下面代码
<body>
<!-- 给一个容器 -->
<div id="root">
<h1>今天的天气很{{info}}</h1>
<!-- 事件绑定时:@xxx="yyy" yyy可以是一些简单的语句 -->
<button @click="changeWeather">切换天气</button>
</div>
<script>
Vue.config.productionTip = false; // config是Vue的配置选项,这里表示不让vue产生额外的提示信息
const vm = new Vue({
el:'#root',
data:{
isHot: true
},
methods: {
changeWeather(){ // 将事件绑定的执行语句放到方法里面,之后再事件绑定中去调用该方法就行了
this.isHot = !this.isHot
}
},
computed:{
info(){
console.log('@----','isHot改变了')
return this.isHot ? '炎热' : '凉爽'
}
}
})
</script>
</body>
2.2Vue中的computed计算属性存在的问题
问题一
例如,我现在业务又要求,我想在一秒之后去再去改变h1标签里面的内容
<body>
<!-- 给一个容器 -->
<div id="root">
<h1>今天的天气很{{info}}</h1>
<!-- 事件绑定时:@xxx="yyy" yyy可以是一些简单的语句 -->
<button @click="changeWeather">切换天气</button>
</div>
<script>
Vue.config.productionTip = false; // config是Vue的配置选项,这里表示不让vue产生额外的提示信息
const vm = new Vue({
el:'#root',
data:{
isHot: true
},
methods: {
changeWeather(){
this.isHot = !this.isHot
}
},
computed:{
info(){
console.log('@----','isHot改变了')
setTimeout(() => { // 给info添加一个定时器,让其一秒钟之后才会有返回值
return this.isHot ? '炎热' : '凉爽'
},1000)
}
}
})
</script>
</body>
你会发现,初始化的时候值就不能被展示出来,且点击按钮过了一秒之后依旧没反应,但是不报错
问题二
例如,我现在又要把业务进行扩展,我需要在监听的时候,将新值和旧值一同展示出来
<body>
<!-- 给一个容器 -->
<div id="root">
<h1>今天的天气很{{info}}</h1>
<!-- 事件绑定时:@xxx="yyy" yyy可以是一些简单的语句 -->
<button @click="changeWeather">切换天气</button>
</div>
<script>
Vue.config.productionTip = false; // config是Vue的配置选项,这里表示不让vue产生额外的提示信息
const vm = new Vue({
el:'#root',
data:{ // data属性中新舔两个属性,一个是新值,一个是旧值
isHot: true,
newValue: '炎热',
oldValue: '凉爽'
},
methods: {
changeWeather(){
this.isHot = !this.isHot
}
},
computed:{
info(){ // 计算属性里面进行处理,展现监听isHot变化,并且同时展示旧值、新值的效果
console.log('@----',`今天的天气很${this.newValue},昨天天气很${this.oldValue}`);
let passValue = this.newValue;
this.newValue = this.oldValue;
this.oldValue = passValue;
return this.isHot ? passValue : this.oldValue
}
}
})
</script>
</body>
你会发现这样子做下来,代码显得很繁琐,新值和旧值还需要自己在data属性里面添加,无缘无故增加了Vue的负担
3.Vue中的watch监听属性
3.1Vue中的watch监听属性是什么?
Vue中可以使用监听器监听已有属性的变化(监听了未定义的属性也不会报错),并根据属性的变化作出响应。
3.2Vue中的watch监听属性的基本使用方式
watch监听属性下可以有多个监听对象,每一个监听对象中都有一个handler函数,该函数有两个参数,第一个参数为监听对象改变前的值,第二个参数为监听对象改变后的旧值
两个参数都不是必须的,需要用时用就好了
handler函数在监听对象发生改变时触发
<body>
<!-- 给一个容器 -->
<div id="root">
<h1>今天的天气很{{info}}</h1>
<!-- 事件绑定时:@xxx="yyy" yyy可以是一些简单的语句 -->
<button @click="changeWeather">切换天气</button>
</div>
<script>
Vue.config.productionTip = false; // config是Vue的配置选项,这里表示不让vue产生额外的提示信息
const vm = new Vue({
el: '#root',
data: {
isHot: true,
},
methods: {
changeWeather() {
this.isHot = !this.isHot
}
},
computed:{
info(){
return this.isHot ? '炎热' : '凉爽'
}
},
watch: {
info:{ // info就是需要监听的对象
handler(newValue,oldValue){
console.log('@----',`今天的天气很${newValue},昨天的天气很${oldValue}`)
}
}
}
})
</script>
</body>
我们仔细观察上面的动态图片会发现,我们点击按钮之前,浏览器的日志输出是空的,说明Vue没有在一开始的时候就去解析watch监听属性(有别于computed计算属性)
注意:
当我们给监听对像添加立即执行的额外配置(immediate:true)时,我们就会发现Vue会在一开始就去解析watch监听属性
watch: {
info:{ // info就是需要监听的对象
immediate:true,
handler(newValue,oldValue){
console.log('@----',`今天的天气很${newValue},昨天的天气很${oldValue}`)
}
}
}
我们可以看到,当给监听对象加上立即执行的额外配置(immediate:true)时,浏览器的日志输出在一开始就会有输出内容,也就是说Vue会在一开始就去解析watch监听属性,但是你会发现此时的oldValue值为undefined
3.3watch监听的深度监听
如果需要深度监听,必须给监听对象额外进行允许深度监听的配置(deep:true),该配置可以让Vue的负担减轻,因为不是每一个监听对象都需要进行深度监听,当我们需要深度监听的时候,我们手动配置就好了
未给watch配置深度监听
给watch配置了深度监听
<script>
Vue.config.productionTip = false; // config是Vue的配置选项,这里表示不让vue产生额外的提示信息
const vm = new Vue({
el: '#root',
data: {
obj: { // 用于深度监听测试
a : {
b : {
c : {
d: 20
}
}
}
}
},
watch: {
obj:{
deep:true, // 这是watch监听属性能深度监听属性的关键
handler(){
console.log('@----','obj发生了改变');
}
}
}
})
</script>
给watch配置了深度监听
3.4Vue中的监听属性另外的写法
语法格式
vm.$watch(监听对象,回调函数) // 监听对象需要打引号,回调函数包含两个参数
利用该语法实现业务
<body>
<!-- 给一个容器 -->
<div id="root">
<h1>今天的天气很{{info}}</h1>
<!-- 事件绑定时:@xxx="yyy" yyy可以是一些简单的语句 -->
<button @click="changeWeather">改变天气</button>
</div>
<script>
Vue.config.productionTip = false; // config是Vue的配置选项,这里表示不让vue产生额外的提示信息
const vm = new Vue({
el: '#root',
data: {
isHot:true
},
methods: {
changeWeather(){
this.isHot = !this.isHot
}
},
computed: {
info(){
return this.isHot ? '炎热' : '凉爽'
}
}
})
vm.$watch('info',function(newValue,oldValue){
console.log(`今天的天气很${newValue},昨天的天气很${oldValue}`)
})
</script>
</body>
3.5Vue中的watch监听属性的简写方式
当我们不需要给watch的监听对象进行额外配置时,我们才可以使用watch的简写形式,简写形式相当于就是将监听对象和handler函数融为一起了
不是简写形式
watch: {
info:{ // info就是需要监听的对象
handler(newValue,oldValue){
console.log('@----',`今天的天气很${newValue},昨天的天气很${oldValue}`)
}
}
}
简写形式
watch: {
info(newValue,oldValue){
console.log('@----',`今天的天气很${newValue},昨天的天气很${oldValue}`)
}
}
3.6利用Vue中的watch监听属性来实现业务
<body>
<!-- 给一个容器 -->
<div id="root">
<h1>今天的天气很{{info}}</h1>
<!-- 事件绑定时:@xxx="yyy" yyy可以是一些简单的语句 -->
<button @click="changeWeather">切换天气</button>
</div>
<script>
Vue.config.productionTip = false; // config是Vue的配置选项,这里表示不让vue产生额外的提示信息
const vm = new Vue({
el: '#root',
data: {
isHot: true,
},
methods: {
changeWeather() {
this.isHot = !this.isHot
}
},
computed:{
info(){
return this.isHot ? '炎热' : '凉爽'
}
},
watch: {
info:{ // info就是需要监听的对象
handler(newValue,oldValue){
setTimeout(() => { // 过一秒钟之后才会提示监听信息,完成了异步任务
console.log('@----',`今天的天气很${newValue},昨天的天气很${oldValue}`) // 很容易拿到新值、旧值
},1000)
}
}
}
})
</script>
</body>
当我们观察上面现象就可以发现,利用Vue的watch监听属性可以很好的处理异步任务,并且很简单那的就能拿到新值、旧值,这两点也很好的解决了刚才使用Vue的computed计算属性去完成业务所出现的问题
注意:
上面使用定时函数setTimeout的时候,我们使用的是箭头函数,为什么这个时候使用箭头函数?因为如果是普通函数,那么JS认定setTimeout函数就是Window调用的,所以setTimeout中的this会指向Window,而如果用箭头函数,那么箭头函数是没有自己的this的,所以这个时候的this指向handler函数的this,所以在Vue中,我们定义函数时一定要考虑清楚this的指向问题
4.总结
computed能完成的功能,watch都可以完成
watch能完成的功能,computed不一定能够完成,例如:watch可以进行异步操作
被Vue管理的函数,最好写成普通函数,这样this的指向才是vm 或 组件实例对象
所以不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等),最好写成箭头函数,这样this的指向才是vm 或 组件实例对象