Vue-03-计算属性和监视属性

计算属性

姓名案例

我们想要让我们的姓名是动态变化的,就要使用v-model双向绑定指令。
姓名的全名是由姓和名共同组成。

普通的实现方式

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

针对全名进行一些有条件的输出,如以下:

        姓名:<span>{{firstName.slice(0,3)}}-{{lastName}}</span>

如果姓名还要做一些其他的操作,就会显得代码十分臃肿,因此我们使用methods:

 全名:<span>{{this.fullName()}}</span>

    new Vue({
            el:'#app',
            data:{
                firstName:'张',
                lastName:'三'
            },
            methods:{
                fullName(){
                    return this.firstName+'-'+this.lastName
                }
            }
        })

通过方法调用可以解决我们模板看起来臃肿的问题,把数据的操作交给函数去处理。

计算属性实现

computed的实现原理是Object_defineProperty。使用get和set方法。
计算属性computed实现了缓存,值未改变时会使用缓存,否则得到set修改的值。


        全名:<span>{{fullName}}</span>

 computed:{
                fullName: {
                    //当有人读取fullName时,就会调用get方法,返回值作为fullName的值
                    get(){
                        console.log('fullName被读取了')
                        return this.firstName + '-'+this.lastName
                    },
                }
            }

计算属性get什么时候被调用?

  1. 初始读取计算属性的时候被调用
  2. 计算属性所依赖的数据发生变化。

set的调用
使用value调用,对值进行分割,获取名和姓然后再赋值


      set(value){
                        console.log('fullName被修改了')
                        //转化为数组形式,以-为分割符
                        const arr = value.split('-')
                        this.firstName = arr[0]
                        this.lastName = arr[1]
                    }

总结

计算属性:

  1. 定义:要用的属性不存在,通过已有的属性计算而来。
  2. 原理: 底层使用Object_defineProperty方法来提供setter和getter方法。
  3. get方法什么时候被调用:
    (1) 初始读取时会执行一次。
    (2)所依赖的数据发生改变的时候调用。
  4. 同methods方法相比,内部有缓存机制,效率更高,调用方便。
  5. 计算属性最终会出现在vm上,直接读取即可。
  6. 如果计算属性被修改,那必须写set函数响应修改,且set方法要引起所依赖的数据发生变化。

计算属性简写

确定只有getter,而没有setter,可以实现简写,相当于getter使用。

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

    <script type="text/javascript">
        Vue.config.productiontip=false
        const vm = new Vue({
            el: '#app',
            data:{
              firstName: '张',
              lastName: '三'
            },
            computed:{
                //只读不改才能简写
                fullName(){
                    //当有人读取fullName时,就会调用get方法,返回值作为fullName的值
                        console.log('fullName被读取了')
                        return this.firstName + '-'+this.lastName
                }
            }
        })
    </script>

实现了计算属性的只读不写。

计算属性

天气案例

在Visual Studio Code安装一个叫Vue 3 Snippets的插件。

天气凉爽和炎热状态切换。
基本实现

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>天气案例</title>
    <script src="/front-study/vue-study/vue-Devtools/vue.js"></script>
</head>
<body>
    <div id="app">
            <!-- 模板里面可以直接读取vm身上的数据 -->
            <h1>今天天气{{isHot ? '炎热' : '凉爽'}}</h1> 
    </div>

    <!-- 开发者工具发现数据没有用到,则开发工具不更新数据 -->
    <script type="text/javascript">
        Vue.config.productiontip = false  //阻止Vue生成提示
		
        const vm = new Vue({
            el: '#app',
            data:{
                isHot: true  //true表示天气热,否则天气凉爽
            },
        })
    </script>
</body>
</html>

通过计算属性实现

        <h1>今天天气{{info}}</h1>
       computed: {
                info(){
                    return this.isHot ? '炎热' : '凉爽' 
                }
            },

点击按钮实现天气转化:

	<button @click="changeWeather()">切换天气</button>
            methods: {
                changeWeather(){
                    this.isHot =  !this.isHot
                }

            },

简单的实现按钮状态切换:

        <button @click="isHot = ! isHot">切换天气</button>

监视属性(天气案例)

监视属性通过watch来实现,watch实现方式有两种:

  1. 在new Vue()内部去实现Watch的配置
  2. 使用vm.$watch去配置

监视属性的原理,当监视的数据发生变化时,就会触发handler回调函数,执行相应的回调处理。

具体实现如下:

           //实现1:在vm内部实现监视属性:已知监视谁
           watch: {
             //key: 监视属性
             isHot: {
                //配置项
                immediate: true,  //初始化时让handler调用一下
                //内部实现handler,isHot被修改了handler方法触发
                handler(newValue,oldValue){  //有俩参数
                    console.log('isHot被修改了',newValue,oldValue)
                }
             }
           }, 
		 vm.$watch('isHot',{
            immediate:true,
            handler(newValue,oldValue){
                console.log('isHot被修改了',newValue,oldValue)
            }
        })

总结

1.当监视的属性发生变化时,会触发回调函数handler去处理相应的逻辑,其中handler(newValue,oldValue)有两个参数。

2.监视的属性一定要存在的,这样才会被监视到。

3.监视分为两种:

  1. 通过在new Vue时传入watch配置
  2. 通过vm.$watch监视

深度监视

data中有一个numbers对象,其中numbers对象包含a,b两个属性。

要求只监视a属性,而不监视b属性?

<div id="app">
        <h3>a的值是{{numbers.a}}</h3>
        <button @click="numbers.a++">点击我a+1</button>
        <h3>b的值是{{numbers.b}}</h3>
        <button @click="numbers.b++">点击我b+1</button>
 </div>
<script type="text/javascript">
        Vue.config.productionTip= false
        const vm = new Vue({
            el:'#app',
            data:{
                numbers:{
                    a: 1,
                    b: 2
                }
            },
           watch:{
                'numbers.a':{
                    //内部实现handler方法进行回调
                    handler(newValue,oldValue){
                        console.log('numbers.a被修改了')
                    }
                }
            }
      
                    })
    </script>
运行结果:

在这里插入图片描述

深度监视是针对于对象的多层属性。让其能监测到对象内部值的变化。

通过deep:true实现,如下所示:

           //监视整个对象的任何属性的变化
            watch:{
                numbers:{
                    deep:true, //配置深度监视
                    //Vue提供的Watch不会帮我们监视对象内布值的变化,需要监视的话需要配置deep:true
                    handler(){
                        console.log('numbers被改变了')
                    }
                }
            }

总结:
1.深度监视:
(1) Vue提供的watch默认不监视对象内部值的改变(一层)
(2) 如果要监视对象内部值的改变需要配置deep:true。
注意:
(1) Vue自身可以监测对象内部值的数据,但Vue提供的Watch不能够监测到。
(2) 使用深度监视还是普通监视,需要根据数据的具体结构。

监视简写

监视属性的简写就是不写其他的配置项,默认是使用自定义函数名实现了handler方法。

1.new Vue内部实现

           //实现1 简写形式
           watch:{
             isHot(newValue,oldValue){
                console.log('isHot被修改了')
             }
           }

2.vm.$watch实现

      vm.$watch('isHot',function(newValue,oldValue){
            console.log('isHot被修改了',newValue,oldValue)
        })

简写Vue不能够实现深度监视以及初始化的时候调用handler方法。

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

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

计算属性本身就是一个属性,不需要在data中声明,计算属性结果依赖于return的返回值。

    <div id="app">
        姓:<input type="text" v-model="firstName">
        名:<input type="text" v-model="lastName">
        全名: <span>{{fullName}}</span>
    </div>
<script type="text/javascript">
        Vue.config.productiontip=false

        const vm = new Vue({
            el:'#app',
            data:{
                firstName: '张',
                lastName: '三',
                fullName: '张-三'  //监视属性需要依赖fullName
            	},
                computed: {
	                fullName(){
	                    return this.firstName+'-'+this.lastName
	                }
            },

通过监视属性实现姓名案例

         watch: {
                //姓或名一改,全名得改
                firstName(value){
                this.fullName =  value+'-'+this.lastName
                },
                lastName(value){
                    this.fullName = this.firstName+'-'+value
                }
            },
 data:{
                firstName: '张',
                lastName: '三',
                fullName: '张-三'  //监视属性需要依赖fullName
            },

对比发现,同样的功能,计算属性实现起来比较容易,但计算属性并不都会满足要求,例如进行异步操作时。

要求改变data数据后 , 全名就会延迟一秒发送。

通过监视属性实现

firstName(value){
                  setTimeout(()=>{
                    this.fullName =  value+'-'+this.lastName
                  },1000);
                },
                lastName(value){
                    this.fullName = this.firstName+'-'+value
                }

能够实现要求。

但通过computed实现,无法实现要求,主要跟return有关。

        computed: {
             fullName(){
                setTimeout(()=>{
                    //计算属性是依赖于return的返回值,计算属性不能实现异步任务。
                    return this.firstName+'-'+this.lastName
              },1000);
             }

故计算属性是依赖于return的返回值,计算属性不能实现异步任务。

总结:
1.computed能完成的功能,watch也能够完成
2.watch能完成的功能,computed不一顶能完成,例如watch能实现异步操作。
注意:
1.所有被Vue管理的函数,最好写成普通函数,这样this指向的是vm
2.所有不被vue管理的函数(定时器的回调函数,ajax回调函数,promise函数,),最好写成箭头函数,这样this指向为vm或组件实例对象.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值