vue里的computed与watch是什么,两者又有什么区别?

本文深入探讨Vue中的计算属性(computed)和侦听器(watch),通过实例讲解它们的工作原理及应用场景,对比数据处理方式,帮助读者掌握高效利用计算属性优化前端性能的技巧。

computed

计算属性!
我们通过代码来逐步了解什么是computed

<body>
    <div id="app"></div>
    
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        
        let users = [
            { id: 1, username: 'baogege', gender: '男' },
            { id: 2, username: 'mt', gender: '男' },
            { id: 3, username: 'haigege', gender: '男' },
            { id: 4, username: 'zMouse', gender: '男' },
            { id: 5, username: 'reci', gender: '女' },
            { id: 6, username: 'lisi', gender: '女' }
        ]

        let app = new Vue({
            el: "#app",
            data: {
                users,
                showUser:users, // filter处理不了原数据的时候,需要准备一个变量存储处理过了的数据
            }
        })
    </script>
</body>

我们现在有一个数组 users 我们要做的就是要数据驱动视图 所以我们需要操控一下数据

<body>
    <div id="app">
		<div>
            <button>全部</button>
            <button></button>
            <button></button>
        </div>
        <hr>
        <ul>
            <li v-for="user of users">
                {{user.username}}
            </li>
        </ul>
	</div>
</body>

我们现在的需求就是,点击全部就全部显示,点击男就性别为男的显示,点击女就显示性别为女的

我们先定义一个方法

methods: {
	getUsers(gender) {
		if (gender === "") {
			this.showUser =  this.users;
		} else {
			this.showUser = this.users.filter(user => user.gender === gender);
		}
	}
}

我们调用一下刚才定义的方法

<button :class="{active:gender===''}" @click="getUsers('')">全部</button>
<button :class="{active:gender==='男'}" @click="getUsers('男')"></button>
<button :class="{active:gender==='女'}" @click="getUsers('女')"></button>

然后我们的需求就实现了,这只是为了让大家知道,data里的users是原数据,showUsers是计算后得到的数据(计算属性)

我们现在增加一个需求,点击那个按钮,就让那个按钮亮起,告诉用户是那个按钮执行的

.active{
	background-color: pink;
}

...

<button :class="{active:gender===''}" @click="getUsers('')">全部</button>
<button :class="{active:gender==='男'}" @click="getUsers('男')"></button>
<button :class="{active:gender==='女'}" @click="getUsers('女')"></button>

...

let app = new Vue({
	el: "#app",
	data: {
		users,
		showUser:users, 
		gender:""	// 新增
	},
	methods: {
		getUsers(gender) {
			this.gender = gender;	// 新增
			if (gender === "") {
				this.showUser =  this.users;
			} else {
			this.showUser = this.users.filter(user => user.gender === gender);
			}
		}
	}
})

页面效果
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
我们现在来看一下通过computed计算属性如何完成上述功能

我们上述代码的功能里边的getUsers这个函数,实际上需要放在computer里边去写


	data: {
		users,
		gender:""
	},
	
	computed: {
		showUser:{
		// 当showUser这个数据被获取是,触发
			get(){
          		if(this.gender === ""){
                	return this.users
          		}else{
                	return this.users.filter(user => user.gender === this.gender);
				}
			}
		},
	}

data 与 computed 的区别

  1. data:存储这没有经过计算的数据
  2. computed: 依赖于data中的数据, 存储着 被计算过的数据 以及计算的过程, 如果数据需要被二次或者多次处理,就属于计算属性

计算得到的数据

  1. computed是一个对象,里面存放是属性。类似data,而不是methods,所以统称为计算属性
  2. 里面的属性可以像 data 里面存放的数据一去使用
  3. 这些属性的值是通过运算得到的
  4. 它的结构类似(defineProperty),getter/setter
  5. 计算属性的值同时还会根据它所依赖的数据的变化 而自动变化

现在我们通过新需求来了解到computed的set方法

	<div id="app">
        <div>
            <button :class="{active:gender===''}" @click="gender = ''">全部</button>
            <button :class="{active:gender==='男'}" @click="gender = '男'"></button>
            <button :class="{active:gender==='女'}" @click="gender = '女'"></button>
        </div>
        <span> {{gender}} </span>
        <hr>
        <ul>
            <li v-for="user of showUser">
                <input type="checkbox" v-model="user.checked">
                {{user.username}}
            </li>
        </ul>
        <!-- 
        	v-model : 代替标签自身的事件,不同的标签触发的事件不同
                        input : onchange
        -->
        <input type="checkbox" v-model="checkAll"/> 全选
    </div>

我们在每条li内部加上一个inout框
并且添加一个全选按钮

<input type="checkbox" v-model="checkAll"/> 全选
	
	...
	
data: {
   users,
   gender:"",
   checkAll:false
},

需求:

  1. 所有li里边的多选框被选中后,全选就被选中。
  2. 全选被选中时,所有li里边的多选框也要被选中

那我们就可以吧checkAll理解为一个计算属性,那我们就把它放在computed里边

                checkAll:{
                    get(){
                        // every() 遍历制定目标的所有内容,一假即假
                        return this.users.every(user => user.checked)
                    },
                    set(newval){
                        return this.users.forEach(user => {
                            user.checked = newval
                        });
                    }
                }

现在处理一下数据,给每个数据加一个checked的属性

let users = [
            { id: 1, username: 'baogege', gender: '男' ,checked:false},
            { id: 2, username: 'mt', gender: '男' ,checked:false},
            { id: 3, username: 'haigege', gender: '男' ,checked:false},
            { id: 4, username: 'zMouse', gender: '男' ,checked:false},
            { id: 5, username: 'reci', gender: '女' ,checked:false},
            { id: 6, username: 'lisi', gender: '女' ,checked:false}
        ]
...

<li v-for="user of showUser">
	<input type="checkbox" v-model="user.checked">
	{{user.username}}
</li>

这样我们就实现了上述新需求

computed:计算属性的值,在依赖数据未发生改变时/或者没有依赖数据,自动缓存到应用中,下次获取时不重新计算

我们通过一个页面效果来看

<body>
    <div id="app">
        <p v-if="showDate"> {{getNow()}} </p>
        <button @click="showDate = !showDate">点我</button>
        <p v-if="showDate"> {{now}} </p>
     </div>
    <script>
        let app = new Vue({
            el:"#app",
            data:{
                showDate:true
            },
            methods: {
                getNow(){
                    return Date.now();
                }
            },
            computed: {
                // now:{
                //     get(){
                //         return Date.now();
                //     }
                // },
                // 如果某个计算属性只需要处理get(),那么可以简写
                now(){
                    return Date.now();
                },
            },
        })
    </script>
</body>

直接打开浏览器的反馈
在这里插入图片描述
点击按钮删除标签后重新创建加载到页面后
在这里插入图片描述

可以看出第二个是没有任何变化的

这也就证明了:computed在依赖数据未发生改变时/或者没有依赖数据,自动缓存到应用中,下次获取时不重新计算

watch

上述代码我们可以看出computed的惰性很大的,他不会主动监听你,但是watch是比较积极的,会去主动监听你。

我们下边就通过代码来看一下

<body>
    <div id="app">
        <input type="text" v-model.lazy="keyword">
        <ul>
            <li v-for="user of showUsers">
                {{user.username}}
            </li>
        </ul>
    </div>
    <script>
        let users = [
            { id: 1, username: 'baogege', gender: '男', checked: false },
            { id: 2, username: 'mt', gender: '男', checked: false },
            { id: 3, username: 'haigege', gender: '男', checked: false },
            { id: 4, username: 'zMouse', gender: '男', checked: false },
            { id: 5, username: 'reci', gender: '女', checked: false },
            { id: 6, username: 'lisi', gender: '女', checked: false }
        ]
        let app = new Vue({
            el:"#app",
            data: {
                keyword:"",
                users,
                showUsers:[]
            },
            watch: {
                keyword(){
                	// includes(指定的内容):查找是否包含指定的值
                    this.showUsers = this.users.filter(user => user.username.includes(this.keyword))

					// setTimeout(()=>{
                        // this.showUsers = this.users.filter(user => user.username.includes(this.keyword))
                    // },1000)
                }
            },
        })
    </script>
</body>

现在页面上来之后是没有数据的
在这里插入图片描述
但是在input框输入一个就会有对应的数据
在这里插入图片描述
我们也可以通过定时器来延迟拿到数据

总结上边我们可以看出

  1. computed是依赖数据变化才去计算
    watch主动处理数据变化
  2. computed没法处理异步的数据
    watch可以直接处理异步

各自使用场景:

  1. watch:适合处理 一个数据影响多个数据
    更适合处理数据相互独立的场景
    主动监听
  2. computed:适合处理 一个数据受多个数据的影响 / 多个数据影响一个数据
    数据相互不独立的场景,也可以
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值