06-vue中计算属性computed及监听属性watch

Posted Ultraman_agul

tags:

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

计算属性及watch监听属性

  • 计算属性

    • 先看一个案例:动态渲染一个字母串,显示在页面时需要首字母大写,而从服务器请求回来的不一定会是首字母大写的情况,所以需要手动在前端作好处理。
        <div id="box">
            <!-- 将首字母大写,这里需要在页面中处理,这样的方式将业务逻辑写在了页面,会影响页面的可读性,这样的方式是不可取的。 -->
            myName.substr(0,1).toUpperCase() + myName.substr(1)
        </div>
        <script>
    
           
            var vm = new Vue(
                el:"#box",
                data:
                    myName:"tom"
                
               
            )
        </script>
    

    上面的案例,将js的业务处理放在了页面html中,违背了表现与行为分离的原则,页面变得臃肿,可读性降低,难以维护,这种现象我们称之为模板过重。要解决这样模板过重问题,可以使用vue中的计算属性computed

    • computed:定义计算属性的地方
        <div id="box">
            <!-- 将首字母大写,这里需要在页面中处理,这样的方式将业务逻辑写在了页面,会影响页面的可读性,这样的方式是不可取的。 -->
            <!-- myName.substr(0,1).toUpperCase() + myName.substr(1) -->
    
            <!-- 
                使用计算属性,
                他用计算属性,无需像调用方法一样,它本质上是已经是方法执行后的返回值。
             -->
             computedName 
        </div>
        <script>
            var vm = new Vue(
                el:"#box",
                data:
                    myName:"tom"
                ,
                // 定义计算属性的地方
                computed : 
                    //定义了一个计算属性computedName
                    //当myName发生改变,这里的计算属性也会同步的执行并更新结果
                    computedName()
                        return this.myName.substr(0,1).toUpperCase() + this.myName.substr(1)
                    
                
            )
        </script>
    
  • computed与methods的区别

    computed:注重结果

    1,逻辑计算,防止模板过重,有缓存 (计算属性在页面多次使用,方法不会重复调用,只有在模型数据发生更新时才会重新执行该函数 )

    2,监听:依赖修改,get方法必须有return

    methods(注重过程):

    1,函数表达式的逻辑处理,没有缓存(页面使用几次,函数就会执行几次,没有缓存)

    2,事件处理函数 ,return不是必需的

    • 对比案例:
        <div id="box">
            <!-- 
                多次使用计算属性
             -->
             computedName 
             computedName 
             computedName 
            <!-- 换行 -->
            <br>
            <!-- 
                多次调用方法
             -->
             comName() 
             comName() 
             comName() 
        </div>
        <script>
            var vm = new Vue(
                el:"#box",
                data:
                    myName:"tom"
                ,
                methods:
                    comName()
                        //页面使用几次,函数就会执行几次,没有缓存
                        console.log("执行了方法")
                        return this.myName.substr(0,1).toUpperCase() + this.myName.substr(1)
                    
                ,
                // 定义计算属性的地方
                computed : 
                    computedName()
                        //计算属性在页面多次使用,方法不会重复调用,只有在模型数据发生更新时才会重新执行该函数 
                        console.log("运行了计算属性")
                        return this.myName.substr(0,1).toUpperCase() + this.myName.substr(1)
                    
                
            )
        </script>
    

    运行结果:

  • 使用计算属性改造过滤搜索案例:
    <div id="box">
        <!-- v-model实现双向数据绑定 -->
        <input type="text" v-model="myVal">
        <ul>
            <!-- 使用计算属性遍历数组 -->
            <li v-for="item in computedData">
                item
            </li>
        </ul>
    </div>
    <script>
        var vm = new Vue(
            el:"#box",
            data:
                //绑定数据的模型
                myVal:"",
                list:["aaa","bbb","abc","bac","bbc","cbb","ccc"]
            ,
            computed:
                //计算属性处理逻辑,返回更新后的数组
                computedData()
                    //根据数据myVal的实时变化,返回过滤后的数组
                    return this.list.filter(item=>item.includes(this.myVal));
                
            
        )
    </script>
  • 计算属性的完整写法

    • 计算属性可以被赋值,前提是要使用计算属性的完整写法

      以上案例的计算属性写法均为简写,简写是无法给计算属性赋值的,否则会报错

下面我们来看看完整写法是怎样的:

案例:

    <div id="box">
        <!-- 使用计算属性的简写 -->
        简写方式输出: computedName 
        <br>
        <!-- 使用计算属性的完整写法 -->
        完整写法输出: compName 
    </div>
    <script>
        var vm = new Vue(
            el:"#box",
            data:
                myName:"tom"
            ,
            // 定义计算属性的地方
            computed : 
                //这样的方式不是计算属性的完整写法,这是简写,简写方式无法赋值
                computedName()
                    return this.myName.substr(0,1).toUpperCase() + this.myName.substr(1)
                ,
                //计算属性完整写法
                compName : 
                    get()
                        return this.myName.substr(0,1).toUpperCase() + this.myName.substr(1)
                    ,
                    set(data)
                        this.myName = data;
                    
                
            
        )
    </script>

修改计算属性结果:

  • 计算属性get和set方法的使用场景

    • 在购物车案例中使用,使用计算性属性实现判断是否全部选中的功能
    
    <body>
        <div id="box">
            <div class="all" v-if="list.length === 0">购物车空空如也</div>
            <template v-else>
                <!-- <div class="all"><input type="checkbox" v-model="isChecked" @change="allCheck()">全选|全不选</div> -->
                <!-- 使用计算属性来判断是否全部选中 -->
                <div class="all"><input type="checkbox" v-model="isCheckedComputed">全选|全不选</div>
                    <ul>
                        <li v-for="(item,index) in list" :key="item.id">
                            <div>
                                <!-- <input type="checkbox" v-model="checkGroup" :value="item" @change="isAllCheck()"/> -->
                                <!-- 使用计算属性无需再使用isAllCheck()方法了 -->
                                <input type="checkbox" v-model="checkGroup" :value="item"/>
                            </div>
                            <div>
                                <img :src="item.pic" alt="">
                            </div>
                            <div>
                                <div>名称:item.name</div>
                                <div>价格:¥item.price</div>
                            </div>
                            <div>
                                <button @click="item.number--" :disabled="item.number===1">-</button>
                                <span>item.number</span>
                                <button @click="item.number++" :disabled="item.number===item.limit">+</button>
                            </div>
                            <div>
                                <button @click="deleteGood(index,item.id)">删除</button>
                            </div>
                        </li>
                    </ul>
                    <div class="all">总金额: totalPrice()</div>
            </template>      
        </div>
        <script>
            var vm = new Vue(
                el:"#box",
                data:
                    isChecked:false,
                    checkGroup:[],
                    list:[.....]
                ,
                methods:
                    totalPrice()
                        var total = 0;
                        this.checkGroup.forEach((ele)=>
                            total += ele.price * ele.number;
                        )
                        return total
                    ,
                    //删除商品
                    deleteGood(index,goodId)
                        //删除原商品
                        this.list.splice(index,1);
                        //更新选中的商品
                        this.checkGroup = this.checkGroup.filter(ele => ele.id !== goodId)
                        //删除单个商品时也要检测是否全部被选中
                        this.isAllCheck();
                    ,
                    //全选全不选
                    // allCheck()
                    //     if(this.isChecked)
                    //         this.checkGroup = this.list
                    //     else
                    //         this.checkGroup = [];
                    //     
                    // ,
                    //选择单个商品时,判断是否为全部选中
                    // isAllCheck()
                    //     if(this.checkGroup.length === this.list.length)
                    //         this.isChecked = true;
                    //     else
                    //         this.isChecked = false;
                    //     
                    // 
                ,
                //定义计算属性判断是否全部被选中
                computed : 
                    isCheckedComputed : 
                        get()
                            //选择后的商品个数与原商品个数相同,说明全部被选中,否则为没有全部被选中
                            return this.checkGroup.length === this.list.length;
                        ,
                        set(isChecked)
                            if(isChecked)
                                //全选按钮选中后,商品全部选中
                                this.checkGroup = this.list;
                            else
                                this.checkGroup = [];//取消全选,选中的数组列表这空
                            
                        
                    
                
            )
        </script>
    </body>
    
  • watch监听属性

    • watch属性:监听,关注过程,无需return,无需调用。

      监听指定数据状态,只要指定的数据发生改变,watch中所定义的对应属性会执行。

        <div id="box">
            <input type="text" v-model="myTest">   
             myTest 
        </div>
        <script>
            var vm = new Vue(
                el:"#box",
                data:
                    myTest:""
                ,
                //监听
                watch : 
                    //定义要监听的属性
                    myTest(data)
                        console.log(data)//只要myTest的状态发生改变,这个程序就会执行,改变的状态值会以形参data的方式传递过来 
                    
                
            )
        </script>
    

    运行效果:

  • watch实现购物车全选全不选功能
    <div id="box">
        <div class="all" v-if="list.length === 0">购物车空空如也</div>
        <template v-else>
            <!-- <div class="all"><input type="checkbox" v-model="isChecked" @change="allCheck()">全选|全不选</div> -->
            <!-- 使用watch监听isChecked状态,无需再触发点击事件执行allCheck()方法 -->
            <div class="all"><input type="checkbox" v-model="isChecked">全选|全不选</div>
                <ul>
                    <li v-for="(item,index) in list" :key="item.id">
                        <div>
                            <input type="checkbox" v-model="checkGroup" :value="item" @change="isAllCheck()"/>
                        </div>
                        <div>
                            <img :src="item.pic" alt="">
                        </div>
                        <div>
                            <div>名称:item.name</div>
                            <div>价格:¥item.price</div>
                        </div>
                        <div>
                            <button @click="item.number--" :disabled="item.number===1">-</button>
                            <span>item.number</span>
                            <button @click="item.number++" :disabled="item.number===item.limit">+</button>
                        </div>
                        <div>
                            <button @click="deleteGood(index,item.id)">删除</button>
                        </div>
                    </li>
                </ul>
                <div class="all">总金额: totalPrice()</div>
        </template>      
    </div>
    <script>
        var vm = new Vue(
            el:"#box",
            data:
                isChecked:false,
                checkGroup:[],
                list:[.....]<

以上是关于06-vue中计算属性computed及监听属性watch的主要内容,如果未能解决你的问题,请参考以下文章

06-vue中计算属性computed及监听属性watch

watch和computed区别 及二者使用场景

06.VUE学习之非常实用的计算属性computed实例

Vue计算属性和监听属性

vue计算属性与watch监听

vue计算属性computed与监听属性watch的基本使用