09 计算属性和监听属性(侦听属性)

278 阅读3分钟

1.计算属性

1.1相关概念

1.定义:要用的属性不存在,要通过已有属性计算得来。

2.原理:底层借助了Objcet.defineproperty方法提供的getter和setter。

3.get函数什么时候执行?

(1).初次读取时会执行一次。

(2).当依赖的数据发生改变时会被再次调用。

4.优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便。

5.备注:

1.计算属性最终会出现在vm上,直接读取使用即可。

2.如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变。

1.2计算属性的添加

在Vue实例中添加computed:

new Vue({
    el: '#root',
    data:{
        firstName:'李',
        lastName:'大龙'
    }
    
    //在computed中写入参与属性计算的语句
    computed:{
        
    }
})

2.小案例:输入姓、名,实现姓名的更新

2.1差值语法实现姓名案例

 <div id="root">
        姓:<input type="text" v-model="firstNme"><br><br>
        名:<input type="text" v-model="lastName"><br><br>
        姓名:<span>{{firstNme}}{{lastName}}</span>
    </div>
​
​
    <script>
        new Vue({
            el: '#root',
            data: {
                firstNme: '张',
                lastName: '三',
            }
        })
    </script>

2.2通过定义方法来实现姓名案例

 <div id="root">
        姓:<input type="text" v-model="firstNme"><br><br>
        名:<input type="text" v-model="lastName"><br><br>
​
​
        <!--  使用插值语法的形式调用函数,函数的返回值直接就是姓+名的组合
                当lastName 和 firstName发生改变时,Vue模板会重新解析,fullName()会被重新调用
        -->
        姓名:<span>{{fullName()}}</span>
    </div>
​
​
    <script>
        new Vue({
            el: '#root',
            data: {
                firstNme: '张',
                lastName: '三',
            },
            methods: {
                fullName() {
                    console.log('被调用了');
                    return this.firstNme + this.lastName
                }
            }
        })
    </script>

2.3 通过计算属性实现姓名案例

2.3.1 完整的写法

fullname 是我们计算后要得到的属性,

当有人调用fullName时,就调用get,且返回值就作为fullnamne的值。

get什么时候调用? 1.初次读取fullName的时候, 2.所依赖的数据发生变化时

const vm = new Vue({
    el: '#root',
    data: {
        firstNme: '张',
        lastName: '三',
    },
    
    computed:{
        
        fullname:{
        
            get(){
                 return this.firstNme + this.lastName
            },
            
            //当fullname被修改的时候,set被调用
            set(){
                //通过 - 更好地分割 姓和名
                const arr = value.splice('-');
                this.firstNme = arr[0];
                this.lastName = arr[1];
                this.fullName = this.firstNme + this.lastName;
            }
        }    
    }

2.3.2 简单的写法

所谓简单的写法就是直接将fullname写成函数的形式,里面只写get函数体的内容的,无需考虑修改fullname的情况(省去了set函数)

 computed:{
      fullName() {
          return this.firstNme + this.lastName
      }
 }
​

3.监视属性

监视属性watch:

1.当被监视的属性变化时, 回调函数自动调用, 进行相关操作

2.监视的属性必须存在,才能进行监视!!

3.监视的两种写法:

(1).new Vue时传入watch配置

(2).通过vm.$watch监视

3.1监视属性实现天气案例

点击按钮,让天气在炎热和凉爽之间切换

<div id="root">
        <h2>今天的天气很{{info}}</h2>
        <button @click="changeWeather">天气切换</button>
        <!-- <button @click="isHot = !isHot">天气切换</button> -->
</div><script>
        const vm = new Vue({
            el: '#root',
            data: {
                isHot: true
            },
            methods: {
                changeWeather() {
                    this.isHot = !this.isHot;
                }
            },
            computed: {
                info() {
                    return this.isHot ? '炎热' : '凉爽';
                }
            },
​
            监视属性
             watch: {
                    info: {
                   //初始化的时候会让handler调用一下
                    immediate: true,
                                                                                                                //handler  当ishot发生改变的时候 handler就会被调用,有两个参数                            一个是修改前的值,一个是修改后的值
                                                                                                    
                     handler(newValue, oldValue) {
                         console.log('info变化了');
                         console.log(newValue, oldValue);
                     },
                 }
             }
​
​
        })
​
        // 监视属性的另一种写法。通过Vue实例直接写
        vm.$watch('isHot', {
            immediate: true,
            handler(newValue, oldValue) {
                console.log('info变化了');
                console.log(newValue, oldValue);
            },
        })
    </script>

watch的用法

watch:{
    //info是被监控的属性,只要info发生变化就会触发handler
    info:{
        handler(newvalue,oldvalue){
            //写入需要进行的操作
            //newvalue 是监测到的新指,oldvalue是老值,按实际业务需求可以对这两个值进行操作
        }
    }
}

上面的这个案例不需要watch也能实现,只不过加上watch之后获取参数很方便,可以服务于更多的业务场景

3.2深度监视

当我们想要监视如下代码中的numbers时(numbers中任意一个值发生改变都能被监测到),watch就局限了,numbers中出现了多层级的数。

new Vue({
            el:'#root',
            data:{
                isHot:true,
                numbers:{
                    a:1,
                    b:1,
                    c:{
                        d:{
                            e:100
                        }
                    }
                }
            },

深度监视:

(1).Vue中的watch默认不监测对象内部值的改变(一层)。

(2).配置deep:true可以监测对象内部值改变(多层)。

具体做法

watch:{
				//监视多级结构中某个属性的变化
				'numbers.a':{
					handler(){
						console.log('a被改变了')
					}
				} 
				//监视多级结构中所有属性的变化
				numbers:{
					deep:true,
					handler(){
						console.log('numbers改变了')
					}
				}
}

3.3 watch实现姓名案例

<div id="root">
			姓:<input type="text" v-model="firstName"> <br/><br/>
			名:<input type="text" v-model="lastName"> <br/><br/>
			全名:<span>{{fullName}}</span> <br/><br/>
</div>

const vm = new Vue({
			el:'#root',
			data:{
				firstName:'张',
				lastName:'三',
				fullName:'张-三'
			},
			watch:{
				firstName(val){
					this.fullName = val + '-' + this.lastName
				},
				lastName(val){
					this.fullName = this.firstName + '-' + val
				}
			}
		})
		
		
		在监视属性中可以加入一些异步操作,例如,而计算属性就没地方可添加
		watch:{
				firstName(val){
				
				setTimeout(()=>{
						console.log(this)
						this.fullName = val + '-' + this.lastName
					},1000);
				}
				
			}

4.计算属性和监视属性的对比

computed和watch之间的区别:

1.computed能完成的功能,watch都可以完成。

2.watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作。

两个重要的小原则:

1.所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm 或 组件实例对象。

2.所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等、Promise的回调函数),最好写成箭头函数,

这样this的指向才是vm 或 组件实例对象。