vue2_7、计算属性、监听属性

1、计算属性

案例:

在两个文本框输入值影响下面的全名:
image

1.1、插值语法实现:

<!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>初始vue</title>
    <!-- 引入vue-->
    <script src="/vueBaseJs/vue.js"></script>
</head>
<body>
    <div id="root">
        姓:<input type="text" v-model:value="firstName"><br/><br/>
        名:<input type="text" v-model:value="lastName"><br/><br/>
        全名:<span>{{firstName.slice(0,3)}}_{{lastName}}</span>
        
    </div>

    <script>

        Vue.config.productionTip=false;//阻止vue启动时生成生产提示

        const vm=new Vue({
            el:"#root",
            data:function(){
                return {
                    firstName:"张",
                    lastName:"三"
                }
            },           
        });

    </script>
    
</body>
</html>

1.2、methods实现

重新解析模板就会引起页面上的数据改变。重新解析模板时里面的插值语法里面的数据也会重新从_data里面获取。插值语法里的方法也会重新调用。

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

    <script>
        Vue.config.productionTip=false;//阻止vue启动时生成生产提示

        const vm=new Vue({
            el:"#root",
            data:function(){
                return {
                    firstName:"张",
                    lastName:"三"
                }
            }, 
            methods:{
                showInfo:function(){
                    //this就是实例vm
                    return this.firstName+"_"+this.lastName;
                }
            }           
        });

    </script>

1.3、计算属性实现

计算属性

1 .定义:要用的属性逻辑上其实不存在,需要通过已有属性(指vue管理的属性)计算得来

2 .原理:底层借助了 Objcet.defineproperty()方法提供的 gettersetter

3 . get函数什么时候执行?
a.vue初次读取模板时会执行一次
b.当依赖的数据发生改变时会被再次调用

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

5 .备注
a.计算属性最终会出现在vm上,直接读取使用即可
b.如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变
c.如果计算属性确定不考虑修改,可以使用计算属性的简写形式

6、使用:
vue配置对象里的computed属性里面配置对象里的就是计算属性。每个计算属性的值也是一个对象。

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

    <script>
        Vue.config.productionTip=false;//阻止vue启动时生成生产提示

        const vm=new Vue({
            el:"#root",
            data:function(){
                return {//属性
                    firstName:"张",
                    lastName:"三"
                }
            },
            computed:{//计算属性,这种属性也会作为vm的属性放在身上。
                fullName:{//计算属性的属性名:fullName
                    //get函数(getter)作用:当有人读取fullName时,get就会被调用,且返回值就作为fullName属性的属性值。
                    //get什么时候调用:
                    //1、vue初次读取fullName属性时。并且会执行缓存操作,这样在解析页面时就不会多次调用该方法。
                    //2、所依赖的数据发送改变时(所依赖的数据就是你这个计算属性是靠那个属性计算得到的)。
                    get:function(){
                        //console.log(this);//此次的this时vm实例。
                        return this.firstName+"_"+this.lastName;
                    },
                    //set在属性值被修改时就会调用。
                    set:function(value){
                        console.log("值被修改了,修改的值为:",value); 
                        const arr=value.split("_");
                        this.firstName=arr[0];
                        this.lastName=arr[1];                       
                    }
                }
            }          
        });

    </script>

image



2、监听属性

天气案例:

<!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>初始vue</title>
    <!-- 引入vue-->
    <script src="/vueBaseJs/vue.js"></script>
</head>
<body>
    <div id="root">
        <h2>今天天气很{{info}}</h2>
        <!-- 绑定事件的时候可以写一下简单的语句-->
        <!-- <button v-on:click="isHot=!isHot;">切换天气</button> -->
        <button v-on:click="changeWeather">切换天气</button>
        
    </div>

    <script>
        Vue.config.productionTip=false;//阻止vue启动时生成生产提示

        const vm=new Vue({
            el:"#root",
            data:function(){
                return{
                    isHot:true
                }
            },
            methods:{
                changeWeather:function(){
                    this.isHot=!this.isHot;
                }
            },
            computed:{
                info:{
                    get:function(){
                        return this.isHot?"炎热":"凉爽"
                    }
                }
            }
        });

    </script>
    
</body>
</html>

image


侦听属性基本用法

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

2 .监视的属性必须存在且是vue管理的,才能进行监视,既可以监视data里的属性 ,也可以监视计算属性

3 .配置项属性 immediate:false ,改为 true,则初始化时调用一次 handler(newValuejOldValue)

4 .监视有两种写法:
a.创建Vue时传入watch: {)配置
b.通过 vm.$watch()监视

        const vm=new Vue({
            el:"#root",
            data:function(){
                return{
                    isHot:true
                }
            },
            methods:{
                changeWeather:function(){
                    this.isHot=!this.isHot;
                }
            },
            computed:{
                info:{
                    get:function(){
                        return this.isHot?"炎热":"凉爽"
                    }
                }
            },
            
            //方式一:在创建时候就通过配置项进行绑定监视
            // watch:{//watch用来存对属性进行监测的配置对象

            //     isHot:{//isHot为被监听的属性名,也就是isHot属性的监听。

            //         immediate:true,//初始化时让handler函数先调用一次。

            //         //handler函数什么时候调用?当isHot属性发送改变时
            //         handler:function(newValue,oldValue){
            //             console.log(`isHot被修改了,新的值:${newValue},旧的值:${oldValue}`);

            //         }


            //     }
            // },
            
        });

        //方式二:vm实例创建后再绑定监视

        vm.$watch("isHot",{
            handler:function(newValue,oldValue){
                console.log(`isHot被修改了,新的值:${newValue},旧的值:${oldValue}`);
            }
        });

2.1 深度侦听

1 . Vue中的watch默认不监测对象内部值的改变(一层)
2 .在watch中配置deep:true可以监测对象内部值的改变(多层)
注意
1 . Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以
2 .使用watch时根据监视数据的具体结构,决定是否采用深度监视

    <div id="root">
        <h2>今天天气很{{info}}</h2>
        <button v-on:click="changeWeather">切换天气</button><hr>

        <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>
        Vue.config.productionTip=false;//阻止vue启动时生成生产提示

        const vm=new Vue({
            el:"#root",
            data:function(){
                return{
                    isHot:true,
                    numbers:{
                        a:1,
                        b:2
                    }
                }
            },
            methods:{
                changeWeather:function(){
                    this.isHot=!this.isHot;
                }
            },
            computed:{
                info:{
                    get:function(){
                        return this.isHot?"炎热":"凉爽"
                    }
                },
            },
            
            watch:{
                isHot:{
                    //immediate:true,//初始化时让handler函数先调用一次。
                    handler:function(newValue,oldValue){
                        console.log(`isHot被修改了,新的值:${newValue},旧的值:${oldValue}`);
                    }
                },

                // //监视多层级结构中某个属性的变化
                // "numbers.a":{
                //     handler:function(newValue,oldValue){
                //         console.log(`numbers.a被修改了,新的值:${newValue},旧的值:${oldValue}`);
                //     }
                // },

                //监视多层级结构中所有属性的变化包括自己
                numbers:{
                    deep:true,//这行代码用于设置是否监视numbers属性的属性值里的属性是否变化。
                    //vue默认是可以监测到多层级的数据的改变的,但是在watch里面默认numbers只监视自己的属性值是否变化。

                    handler:function(newValue,oldValue){                        
                        console.log("numbers属性的值被修改或者numbers属性的值的属性被更改");
                    }
                }


            },
            
        });


    </script>

Vue中的watch属性的值的简写:简写就无法写别的配置对象,只有handler的功能。
如果监视属性除了handler没有其它配置项就可以使用简写。

watch:{
                isHot:function(newValue,oldValue){
                    console.log(`isHot被修改了,新的值:${newValue},旧的值:${oldValue}`);
                },
            },

2.2 计算属性和侦听属性的区别:

computed和watch之间的区别

  • computed能完成的功能,watch都可以完成

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

  • 两个重要的小原则
    ①所有被Vue管理的函数,最好写成普通函数,这样this的指向才是vm或组件实例对象
    ②所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等、Promise的回调函数),最好写成
    箭头函数,这样this的指向才是vm或组件实例对象。

<!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>初始vue</title>
    <!-- 引入vue-->
    <script src="/vueBaseJs/vue.js"></script>
</head>
<body>
    <div id="root">
        姓:<input type="text" v-model:value="firstName"><br/><br/>
        名:<input type="text" v-model:value="lastName"><br/><br/>
        全名:<span>{{fullName}}</span>        
    </div>

    <script>
        Vue.config.productionTip=false;//阻止vue启动时生成生产提示

        //计算属性里不能开启异步任务维护数据,因为读取计算属性就是要要靠它返回一个值。
        //但是watch可以开启异步任务维护数据,因为它不靠返回值,而是靠里的的操作维护数据。
        const vm=new Vue({
            el:"#root",
            data:function(){
                return {//属性
                    firstName:"张",
                    lastName:"三",
                    fullName:"张_三"
                }
            },
            watch:{
                firstName:{
                    handler:function(newVal,oldVal){
                        setTimeout(() => {//这里只能使用箭头函数,不能写成普通函数的形式。箭头函数绑定了父级作用域的上下文对象,因为箭头函数不会创建this。
                            //因为异步任务是存放定时器模块的,也就是还是js引擎执行的(window调用)。定时器不写成箭头函数的话,他的this就会往上指,
                            //而他的上一层就是Vue所管理的,所以指向的Vue,如果用普通函数的话就指向window了。
                            this.fullName=newVal+"_"+this.lastName;
                        }, 2000);
                    }
                },
                lastName:{
                    handler(newVal,oldVal){
                        this.fullName=this.firstName+"_"+newVal;
                    }
                }
             }                  
        });

    </script>

    
</body>
</html>
posted @ 2022-04-02 15:28  青仙  阅读(230)  评论(0编辑  收藏  举报