第十二节:Vue选项:computed计算属性

1 计算属性的基本了解

1.1 认识Mustache语法的不做

模板中的表达式非常便利,但设计的初衷时为了简单的运算,如果时复杂的逻辑运算,会比较难以维护,不容易理解其中的意思,

例如:

<div id="app">
    <!-- 正常绑定数据 -->
    {{msg}}

    <!-- 对数据进行逻辑处理, 反向字符串 -->
    {{msg.split("").reverse().join("")}}

    <!-- 多次使用功能反向逻辑 -->
    {{msg.split("").reverse().join("")}}
    {{msg.split("").reverse().join("")}}
    {{msg.split("").reverse().join("")}}
</div>

<script>   

    const vm = new Vue({
        el: "#app",
        data: {
            msg: "hello",
        }
    })
</script>

这样就非常不方便,因为如果我需要多次使用这个逻辑时就不那么方便了,所以对于任何复杂的逻辑运算,你都需要使用逻辑运算。

同时将太多的逻辑放入模板中处理,就会使得模板很臃肿,这样不利于代码的维护。


1.2 使用方法弥补Mustache的不足

那么我们首先可能会想到的及时使用方法, 把这些复杂的逻辑定义为一个方法, 然后通过多次调用这个方法来达到逻辑复用的目的

例如

<div id="app">

    <!-- 利用方法来处理逻辑 -->
    {{ reverseStr() }}


    <!-- 多次调用方法复用代码逻辑 -->
    {{ reverseStr() }}
    {{ reverseStr() }}
    {{ reverseStr() }}

</div>

<script>   
    const vm = new Vue({
        el: "#app",
        data: {
            msg: "hello",
        },
        methods: {
            reverseStr(){
                return this.msg.split("").reverse().join("")
            }
        }
    })
</script>

其实我们发现这样可以达到复用的目的, 但是如果我们测试就会发现,函数在每一次调用的时候都会执行, 都会重新计算, 如果调用100次,函数就会执行100次, 对于性能不是特别好, 因为每一次的结果都是一样的

那么我们有没有办法吧数据缓存下来呢, 就不用每次都计算了呢?还真有


1.3 计算属性的了解

Vue给我们提供了一个计算属性Computed, 计算属性中的方法也是函数, 但是跟方法不同, 计算数据会将计算的结果挂在到Vue实例对象的属性上. 这样每次调用的时候,都是在调用Vue实例的属性, 这样我们同样的逻辑计算的结果就得到了缓存,每次使用属性值就可以了

例如:

<div id="app">

    <!-- 利用计算属性来处理逻辑 -->
    {{ reverseMsg }}
    {{ reverseMsg }

</div>

<script>   

    const vm = new Vue({
        el: "#app",
        data: {
            msg: "hello",
        },
        methods: {
            reverseStr(){
                console.log(11)
                return this.msg.split("").reverse().join("")
            }
        },
        computed:{
            reverseMsg(){
                return this.msg.split("").reverse().join("")
            }
        }
    })
</script>

这里我们在Vue 的 computed 属性中定义了一个方法 reverseMsg , Vue会自动计算这个方法的结果, 不需要我们自己调用, vue会将计算后的结果添加给Vue 实例对象的同名属性. 这就是我们所说的计算属性

因为是属性的关系,我们在{{}}中使用的使用不需要添加()执行, 就跟我们平时调用data 属性中的数据一样使用就好了


而且我们可以测试在多次调用计算属性的时候, 计算属性会不会被多次调用,

computed:{
    reverseMsg(){
        console.log(22)
        return this.msg.split("").reverse().join("")
    }
}

我们会发现无论你使用多少次计算属性, 计算属性的方法都只会执行一次,

这样就有弥补了Mustache语法和方法复用逻辑带来的问题


1.4 数据发生变化

如果如果我的数据发生了变化, 那计算后的结果也应该发生变化, 那么在数据发生变化的时候, 计算属性会不会执行呢,答案是肯定的.

例如:

<div id="app">

    <!-- 利用计算属性来处理逻辑 -->
    {{ reverseMsg }}
    {{ reverseMsg }}

    <!-- 点击按钮改变数据 -->
    <button @click="changeMsg">点击改变数据</button>
</div>

<script>   

    const vm = new Vue({
        el: "#app",
        data: {
            msg: "hello",
        },
        methods: {
            changeMsg(){
                this.msg = "word"
            }
        },
        computed:{
            reverseMsg(){
                console.log(22)
                return this.msg.split("").reverse().join("")
            }
        }
    })
</script>

通过案例; 当我们点击改变数据按钮的时候, 数据发生变化, 数据一定发生变化,就会自动触发依赖这个数据的计算属性的方法, 通过计算的得到的结果将会覆盖原来的属性的结果, 也就会重现渲染页面结果


1.5 为什么称呼为计算属性

很多小伙伴要问? 为什么说他是属性而不是方法呢,铭铭就是定义了一个函数嘛

其实这个问题只要理解对象的属性和方法的区别就能理解

例如

var obj = {
    name:'姓名',
    eat: function(){
        console.log("吃饭")
    }
}

这个对象,我们称obj对象有一个属性name,和方法eat,为什么这么叫

其实eat也是obj对象的属性, 只不过这个属性值是一个函数,我们把属性值为函数的属性成为方法, 因为函数能实现一定的功能.

理解了属性和方法的区别以后,我们在来理解Vue的计算属性.

此时我们去控制台打印Vue实例化对象

计算属性.png

代码就是上面计算属性那一节的代码,

通过在控制台的打印我们发现,Vue初始化的选项对象中,无论是data属性,methods属性还是computed属性中的值都会挂载在Vue实例化对象身上,成为Vue实例对象的属性.

此时也会发现,

  1. methods属性中的值在成为Vue实例对象属性时值为函数,所以叫methods为方法属性.

  2. data属性中的中数据成为Vue实例对象属性是值就是data中定义的值,

  3. 有趣的是computed属性中定义的reverseMsg是一个函数, 但是在成为Vue实例对象属性后,结果却不是函数,而是函数的执行结果

所以现在能理解为什么称为计算属性了吧,因为computed属性中的方法名会成为Vue实例对象的属性,但是值不是函数,所以不会被称呼为方法,同时因为属性的值是计算而来的,一次称呼计算属性.


2. 计算属性的getter和setter

2.1 计算属性语法的了解

重点要注意这个属性,computed是属性不是方法

方法是不会有缓存的,但是computed会根据依赖(依赖是归vue管理的数据,可以响应式的变化)的变化重新处理逻辑进行数据的缓存

其实计算由两部分组成,为get和set(不能只写set),一般情况下通过js赋值影响其他人或者表单元素设置值的时候会调用set方法

其实想想就能理解, 对象的属性, 获取的时候不就是get 当你改变对象属性的值,不就是重新赋值了嘛,也就是set啊,

语法:

{
    computed:{
         // 计算属性写成对象,就需要手动设置get方法,set方法
        sum:{
            get(){
                // 获取时调用的方法  
            },
            set(val){
                    // 设置时调用
           }
        },
            
        // 如果计算属性写成函数,默认调用的就是get方法,没有set方法
         sum(){

         }
    }
}


2.2 get 语法

那么我们首先来看get 获取计算属性的值

计算属性默认只有 get ,不过在需要时你也可以提供一个 set

我们默认的计算就是只有get操作

例如:

一般都没有set,只有输入框这种可能有set

<div id="app">

    <!-- 显示计算属性结果-->
    <div>
        firstname:
        <input type="text" v-model="firstName">
    </div>
    <div>
        lastname:
        <input type="text" v-model="lastName">
    </div>
    <div>
        getfullname:
        <input type="text" v-model="fullName">
    </div>
    <div>
        setfullname:
        <input type="text" v-model="fullName">
    </div>

</div>

<script>   

    const vm = new Vue({
        el: "#app",
        data: {
            firstName:"Foo",
            lastName: "Bar",
        },

        computed:{
            // 这里Fullname只有get功能
            fullName(){
                return this.firstName + ' ' + this.lastName
            }
        }
    })
</script>

我们发现每次计算属性FullName所依赖的firstname 和lastname 值一旦发生变化, FullName也将重新计算获取最新的计算结果,


2.3 set语法

但是如果我想改变计算属性的值,能不能反向的修改firstname 和lastname的值呢, 发现不可以,因为我们没有添加set计算属性设置

如果想添加计算属性的set功能,我们就的改变咱们计算属性的写法

<script>   

    const vm = new Vue({
        el: "#app",
        data: {
            firstName:"Foo",
            lastName: "Bar"
        },

        computed:{
            fullName:{
                // 计算属性的get
                get(){
                    console.log("get")
                    return this.firstName + ' ' + this.lastName
                },
                // 计算属性的set, set是设置,设置就需要新值传入
                set(value){
                    console.log("set")
                    let fullNameArr = value.split(" ");
                    this.firstName = fullNameArr[0] ? fullNameArr[0]: '';
                    this.lastName = fullNameArr[1] ? fullNameArr[1]: '';
                }
            }
        }
    })
</script>


3. 案例区

案例: 全选按钮
<div id="app">

    <!-- 全选案例-->
    <div>
        全选: <input type="checkbox" v-model="checkAll">
    </div>
    <ul>
        <li
            v-for="fruit in fruits" 
            :key="fruit.title"
            >
            <input type="checkbox" v-model="fruit.isSelect">
            {{fruit.title}}: 价格{{fruit.price}}元/斤
        </li>
    </ul>
</div>

<script>   

    const vm = new Vue({
        el: "#app",
        data: {
            fruits:[
                {
                    title:"西瓜",
                    price: 10,
                    isSelect:false,
                },
                {
                    title:"苹果",
                    price: 22,
                    isSelect:false,
                },
                {
                    title:"香蕉",
                    price: 11,
                    isSelect:false,
                }
            ]
        },

        computed:{
            checkAll:{
                get(){
                    console.log(11)
                    // 如果用户全部选中,那么计算数据返回true,否则返回false
                    return this.fruits.every((fruit) => {
                        return fruit.isSelect;
                    })
                },
                set(isCheckAll){
                    // 更加用户是否点击全选改变数据里的选中问题
                    this.fruits.forEach(fruit => {
                        fruit.isSelect = isCheckAll
                    });

                }
            }
        }
    })
</script>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,047评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,807评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,501评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,839评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,951评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,117评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,188评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,929评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,372评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,679评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,837评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,536评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,168评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,886评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,129评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,665评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,739评论 2 351