vue2计算属性(computed)与侦听器(watch)详解

Posted 初映CY的前说

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue2计算属性(computed)与侦听器(watch)详解相关的知识,希望对你有一定的参考价值。

🥳博       主:初映CY的前说(前端领域)

🌞个人信条:想要变成得到,中间还有做到!

🤘本文核心:计算属性与侦听属性的用法

目录(文末有给大家准备好的Xmind思维导图

一、计算属性computed

①默认get()方法,仅是获取值

②不仅仅是获取值,还具有修改属性功能的写法

二、侦听器

①值类型

 ②引用类型 

总结:计算属性与侦听属性的区别


一、计算属性computed

概念:处理数据用来解决代码的冗余

用法:当数据需要通过计算才能得到比如我们求商品的总和与全选功能

计算属性语法:

①一定要在vue实例的对象computed中声明一个函数

②这个函数的返回值return就是计算属性的属性值

特殊的机制:缓存机制(提高性能)

(1)计算属性在第一次使用时,会执行一次函数体,之后就会将返回值缓存起来

(2)下一次使用计算属性的时候,不会执行这个函数,而是直接从缓存中读取

(3)只有当计算属性中的数据发生变化时,这个函数才会重新执行一次


写法:有两种

①默认get()方法,仅是获取值

语法格式:

computed:
变量名()
return this.//一大堆需要计算的数据比如翻转数组

看下面这个例子:(大家可以下直接cv到自己新的html中,我的vue引入是在线的)

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <!-- 导包 -->
    <!-- <script src="./vue.js"></script> -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> 

</head>

<body>
    <div id="app">
        <p></p>
        <!-- 翻转字符串 -->
        <p>  msg.split('').reverse().join('') </p>
        <p> revMsg</p>
        <p> revMsg</p>
    </div>
    `
    <script>
        let app = new Vue(
            el: '#app',
            data: 
                msg: '我爱敲代码',
            ,
            computed:
                revMsg()
                    console.log(1);
                return this.msg.split('').reverse().join('') 
                
            
        
        )
    </script>
</body>
</html>

上述代码实现的效果见下图

 看这个例子,我们定义了一个 resMsg 属性计算方法,并通过将字符串分隔(split()方法)此时已经成为了数组 [ "我", "爱", "敲", "代", "码" ],再翻转下,用字符转拼接作return的返回值给resMsg属性,这样我们就可以配合我们的插值表达式进行解析变量了。

我们还发现了,这样写实现了我们想要的效果,减少了代码的冗余并且可以发现我们的resMsg调用不需要写()直接放进插值表达式就可被解析了。

我们也利用它的特殊机制了,只是调用了一次,之后的调用我们从缓存中获取到。


②不仅仅是获取值,还具有修改属性功能的写法

语法:

            computed: 
                变量名: 
                    get() 
                        return this.firstName + this.lastName
                    ,
                    // set的形参是get的返回
                    set(val) 
                        console.log(val);
                    
                
            

        1. 默认情况下,计算属性只有get方法。只能获取,不能修改。否则程序会报错

        2. 如果希望计算属性可以修改,则可以实现set方法

看下面这个例子:(大家可以下直接cv到自己新的html中,我的vue引入是在线的)

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <!-- 导包 -->
    <!-- <script src="./vue.js"></script> -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> 

</head>
<body>
    <!-- HTML结构 -->
    <div id="app">
        全选<input type="checkbox" v-model="allCheck" >
        <ul>
            <li v-for="(item,index) in list">
                <!-- v-model双向绑定 当时单选框(表单元素无条件用v-model!)的时候这个就是选中状态-->
                <input type="checkbox"  v-model="item.select">item.name <label for=""></label>
            </li> 
        </ul>
    </div>

    <script>
        /* 
        1. 默认情况下,计算属性只有get方法。只能获取,不能修改。否则程序会报错
        2. 如果希望计算属性可以修改,则可以实现set方法
        */
        /* 创建vue实例 */
        var app = new Vue(
            //el:挂载点
            el: '#app',
            //data: 要渲染的数据
            data: 
                active:0,
                list: [
                     name: '前端', select: false ,
                     name: 'UI', select: false ,
                     name: 'Java', select: false ,
                     name: 'php', select: false ,
                     name: 'python', select: false ,
                     name: 'c', select: false ,
                     name: '测试', select: false ,
                     name: '产品', select: false ,
                ]
            ,
            //计算属性
            computed: 
                allCheck:
                    get()
                    // every返回是布尔值,一假则假,全真为真
                    //some 返回的也是布尔值,当有一个元素符合条件的时候返回true
                    return this.list.every(item=>item.select)
                    ,
                    set(val)
                        console.log(val);
                        this.list.forEach(element => 
                            element.select=val
                        );
                    

                
            
        )
    </script>
</body>

</html>

下面是上述代码实现的效果图

核心代码:

实现上述例子的思路是:

 例子分析:这个例子难点在于怎么通过获取到各个单选框的数据与怎么与全选框进行绑定的。

  1. 看到表单项我们获取数据用v-model实现双向绑定。这样我们就可达到修改了之后就可以实时得到反馈
  2. 遍历我们的列表将list渲染出来
  3. 定义一个计算属性方法 allCheck() ,在get() 中开始用every()方法做判断(every方法用于遍历数组,当数组元素都是true的时候返回true,否则返回false)用于小选控制全选,当我全部选中的时候,return的值就是我们allCheck的属性值。
  4. 下面的set()用于全选控制小选(我们的allCheck是绑定在全选框上的),当我们做出改变修改的时候会触发allCheck的set()方法,当我选中全选框的时候,此时的allCheck是true,在set()中作为val的实参传进去了,因此列表每一项都是true选中状态了!!!


二、侦听器

概念:监听data中的某一个数据变化

写法:有两种

①值类型

            watch:
                '要侦听的属性名'(newVal,oldVal) 
            

兄弟姐妹们,上个例子大家可以下直接cv到自己新的html中,我的vue引入是在线的)

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <!-- 导包 -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> 

</head>

<body>

    <!-- HTML结构 -->
    <div id="app">
        用户: <input type="text" placeholder="请输入用户名" v-model="username"><span></span>
        <br>
        密码: <input type="text" placeholder="请输入密码" v-model="password">
    </div>

    <script>

        /* 创建vue实例 */
        let app = new Vue(
            //el:挂载点
            el: '#app',
            //data: 要渲染的数据
            data: 
                username: '',
                password: ''
            ,
            methods: 
                fn() 
                    return setTimeout(() =>  console.log("这是异步操作") , 1000)
                
            ,
            //侦听器
            watch: 
                // 一个监听器检测检测一项东西,前面新的,后面之前数据
                username(newIfo, oldInfo) 
                    console.log('当前值为', `$newIfo`, '之前值为', `$oldInfo`);
                    if (newIfo === 'admin') 
                        console.log('当前用户名不可取,请输入其他用户名')
                        this.fn()
                    
                
            
        )



    </script>
</body>

</html>

 核心代码:

我们运行下查看效果: 

可以看到,当我们username的时候,浏览器是检测到了我们输入的是admin就弹出了相应的提示('当前用户名不可取,请输入其他用户名),同时我们在值类型在写了一个fn()里面是个异步函数也可以被执行,因此侦听属性的值类型可以执行异步操作。

 ②引用类型 

watch:
data属性(new,old)
deep:true//开启深度侦听
handler()
//写需要处理的操作

<!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>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>

<body>
    <div id="app">

        <input type="text" v-model="obj.name">
        <input type="text" v-model="obj.age">

    </div>
    <script>
        new Vue(
            el: "#app",
            data: 
                obj: 
                    name: "初映",
                    age: 22,
                    fn() 
                        return setTimeout(() =>  console.log("这是异步操作") , 1000)
                    
                
            ,

            watch: 
                obj: 
                    deep: true,
                    immediate: false,//当页面加载完成马上调用一次,记录为新值,救值必须删除
                    handler(newVal, oldVal) 
                        console.log(`新的值为:` + newVal.name, `旧值为:` + oldVal.name);
                        this.obj.fn()
                    ,
                
            ,
            methods: 
        )
    </script>
</body>

</html>

核心代码:

 运行结果:

 可以看到我们的深度监听,侦听到了引用类型数值发生了改变,我们也是实时侦听到了数据,同时深度侦听也可以支持异步操作。


总结:计算属性与侦听属性的区别:

(1)功能不同,计算属性用于解决模板冗余问题。侦听器侦听data中某一个数据变化

(2)计算属性具有缓存机制,侦听器没有缓存机制

(3)计算属性不支持异步操作,侦听器支持异步操作

(4)计算属性可以给vue新增属性,侦听器是 data中已有属性

(5)计算属性只要使用了就会执行一次,侦听器默认只有第一次改变才会执行


下面是给兄弟姐妹准备好的Xmind图总结:


下篇文章将讲解【vue cli脚手架 与VueTools工具】的使用,本专栏将持续更新,欢迎关注~

Vue学习3:计算属性computed与监听器

下面是计算属性相关代码:

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>vue3</title>
 6     <meta name="viewport" content="width=device-width, initial-scale=1">
 7     <!--<link rel="stylesheet" type="text/css" href="main.css"/>-->
 8     <script src="vue.js"></script>
 9 </head>
10 <body>
11 <!--计算属性computed,可以用在一些复杂逻辑上-->
12 <div id="app">
13     <!--1.模板中逻辑过重,不易维护-->
14     <p>{{msg.split(\'\').reverse().join(\'\')}}</p><br>
15     <!--2.用上computed属性,适用于复杂逻辑-->
16     <p>原值:{{msg}}</p>
17     <p>使用computed:字符串反转后的值:{{reverseMsg}}</p><br>
18     <!--3.用methods-->
19     <p>原值:{{msg}}</p>
20     <p>使用methods:字符串反转后的值:{{reverseMsg1()}}</p><br>
21     <!--我们可以发现computed属性和methods得到的结果是一样的。但是computed是基于它的缓存依赖(例子中指vm.msg),
22     只有相关依赖改变才会重新取值;但是methods,每次重新渲染时,都会重新取值-->
23     <!--所以说一般computed性能更好-->
24 
25 
26     <!--计算属性默认只有getter,不过我们可以设置setter-->
27     <p>{{fullName}}</p>
28     <p>{{firstName}}</p>
29     <p>{{lastName}}</p>
30 </div>
31 
32 <script>
33     var vm=new Vue({
34         el: \'#app\',
35         //选项对象
36         data:{
37             msg:\'hello\',
38             firstName:\'Smith\',
39             lastName: \'Lee\'
40         },
41         //声明计算属性,提供的函数将用作vm.reverseMsg的getter
42         //vm.reverseMsg依赖于vm.msg;vm.msg改变时,vm.reverseMsg也会改变
43         computed:{
44             //计算属性的getter
45             reverseMsg:function(){
46                 return this.msg.split(\'\').reverse().join(\'\');
47             },
48             fullName:{
49                 get:function(){
50                     return this.firstName+\' \'+this.lastName;
51                 },
52                 set:function(newValue){
53                     var value=newValue.split(\' \');
54                     this.firstName=value[0];
55                     this.lastName=value[1];
56                 }
57             }
58 
59         },
60         methods:{
61            reverseMsg1:function(){
62               return this.msg.split(\'\').reverse().join(\'\');
63            }
64         }
65     });
66     vm.fullName=\'John Lee\';
67 </script>
68 </body>
69 </html>
View Code

 

2.下面是监听器相关代码:

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>vue4 监听属性</title>
 6     <meta name="viewport" content="width=device-width, initial-scale=1">
 7     <!--<link rel="stylesheet" type="text/css" href="main.css"/>-->
 8     <script src="vue.js"></script>
 9 </head>
10 <body>
11 <div id="app">
12     <input type="text" v-model="meter">
13     <input type="text" v-model="kilometer">
14     <p class="test"></p>
15 </div>
16 <!--其实计算属性在大多数时候更合适,但是当数据执行异步操作或开销较大的操作时,需要采用监听器操作-->
17 <script>
18     var vm=new Vue({
19         el: \'#app\',
20         data:{
21             meter:\'\',
22             kilometer: \'\'
23         },
24         watch:{
25             //watch创建了meter和kilometer两个方法
26             meter:function(val){
27                 this.meter=val;
28                 this.kilometer=val/1000;
29             },
30             kilometer:function(val){
31                 this.kilometer=val;
32                 this.meter=val*1000;
33             }
34         },
35 
36 
37     });
38     vm.$watch(\'meter\',function(newValue,oldValue){
39         document.getElementsByClassName(\'test\')[0].innerHTML="meter新值:"+newValue+ ";" + "meter旧值:"+oldValue;
40     })
41 </script>
42 </body>
43 </html>
View Code

在第一个输入框中输入123后,运行结果:

 

 

 

 

参考:https://cn.vuejs.org/v2/guide/http://www.runoob.com/vue2

以上是关于vue2计算属性(computed)与侦听器(watch)详解的主要内容,如果未能解决你的问题,请参考以下文章

Vue2基础

vue2.0的基本特性

Vue学习3:计算属性computed与监听器

Vue中的计算属性computed和侦听器watch

Vue中的计算属性computed和侦听器watch

Vue2 computed中的setter