vue中的watch与computed的区别

vue中的watch与computed的区别

一、watch(侦听器:用来监听data中或者prop中属性的变化)

1. 监听简单数据类型

最初绑定的时候是不会执行的,要等到 firstName 改变时才执行监听计算

<div>
	<div>
		<p>FullName: {{fullName}}</p>
		<p>FirstName: <input type="text" v-model="firstName"></p>
	</div>
</div>
export default {
	data () {
		return {
			firstName: 'Foo',
			fullName: '',
		}
	},
	watch: {
		firstName(newName, oldName){
			this.fullName = newName
		}
	}
}

在这里插入图片描述


2.handler方法和immediate属性

注意用到immediate属性一定要用到handler方法,之前我们写的 watch 方法其实默认写的就是这个handler,Vue.js会去处理这个逻辑,最终编译出来其实就是这个handler。handler为false时,就跟上面一样不会在绑定的时候就执行;handler为true时,表示在 wacth 里声明了 firstName 之后,就会立即先去执行里面的handler方法。

export default {
	data () {
		return {
			firstName: 'Foo',
			fullName: '',
		}
	},
	watch: {
		firstName:{
          handler(newName, oldName){
            this.fullName = newName
          },
          // *代表在wacth里声明了firstName这个方法之后立即先去执行handler方法*
          immediate: true
        }
	}
}

在这里插入图片描述


3.deep属性

默认值是 false,代表是否深度监听
当需要监听一个对象的改变时,普通的watch方法无法监听到对象内部属性的改变,只有data中的数据才能够监听到变化,此时就需要deep属性对对象进行深度监听。

<div>
	<input type="text" v-model="cityName.name"/>
</div>
export default {
	data () {
		return {
			cityName: {id: 1, name: 'shanghai'},
		}
	},
	watch: {
        cityName:{
          handler(newName, oldName){
            console.log("newName",newName)
            console.log("oldName",oldName)
          },
          deep:true // 可以深度检测到cityName对象的属性值的变化
        }
	}
}

console.log打印的结果发现oldName和newName值是一样的,所以深度监听虽然可以监听到对象的变化,但是无法监听到具体对象里面那个属性的变化
oldName和newName值一样的原因是它们索引同一个对象/数组。Vue 不会保留修改之前值的副本 ——> vm.$watch的深度监听
在这里插入图片描述

3.1监听对象单个属性

如果监听对象的话(相当于给对象的所有属性都加上了监听器,层层遍历),这样性能开销就会非常大了,修改obj里面任何一个属性都会触发这个监听器里的 handler,所以我们可以使用字符串形式监听。

方法一:可以直接对用对象.属性的方法拿到属性

watch: {
	'cityName.name':{
	     handler(newName, oldName) {
	       console.log("newName",newName)
           console.log("oldName",oldName)
	    },
	    deep: true,
	    immediate: true
	}
}

在这里插入图片描述

方法二:watch如果想要监听对象的单个属性的变化,必须用computed作为中间件转化,因为computed可以取到对应的属性值

computed:{
	cityNameChange(){
		return this.cityName.name
	}
},
watch: {
	cityNameChange(newName, oldName){
		console.log('cityName的name属性值变化了')
	}
}

在这里插入图片描述


4.监听路由

可以使用watch来进行路由的监听

watch: {
    '$route'(to,from){//to表示去往的界面,from表示来自于哪个界面
      console.log("to",to;"from",from);   
      if(to.path=="/personal"){
        console.log("个人页面");
      }
    }
}

5.watch不支持缓存,支持异步
<div>
  <p>
    Ask a yes/no question:
    <input v-model="question">
  </p>
  <p>{{ answer }}</p>
</div>
export default {
	data () {
	    return {
	      question: '',
	      answer: 'I cannot give you an answer until you ask a question!'
	    }
	},
	watch: {
		question: function (newQuestion, oldQuestion) {
			this.answer = 'Waiting for you to stop typing...'
			this.debouncedGetAnswer()
		}
	},
	mounted() {
		//引用外部的js文件
		//1.简单粗暴,直接在Vue项目的index.html 中使用全局的方式引入:<script src="../xxx.js"></script> 
		//2.如果是下载到本地的静态文件,可以使用import 的方式导入:import { xxx } from '../js/xxx.js' //注意路径
		//3.在Vue组件加载完后,手动操作DOM插入js插件:如下面代码
		let script = document.createElement('script');
		script.type = 'text/javascript';
		script.src = 'https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js';
		document.body.appendChild(script);
	},
	created: function () {
		this.debouncedGetAnswer = this.getAnswer
	},
	methods: {
	  getAnswer: function () {
	    if (this.question.indexOf('?') === -1) {
	      this.answer = 'Questions usually contain a question mark. ;-)'
	      return
	    }
	    this.answer = 'Thinking...'
	    var vm = this
	    axios.get('https://yesno.wtf/api')
	      .then(function (response) {
	        vm.answer = _.capitalize(response.data.answer)
	      })
	      .catch(function (error) {
	        vm.answer = 'Error! Could not reach the API. ' + error
	      })
	  }
	}
}

在这里插入图片描述在这里插入图片描述在这里插入图片描述


二、computed(计算属性)

计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。
是一个计算属性,类似于过滤器,对绑定到view的数据进行处理。
当你有一些数据需要随着其它数据变动而变动时,你很容易滥用 watch,然而,通常更好的做法是使用计算属性而不是命令式的 watch 回调。

1. computed用来监控自己定义的变量,该变量不在data里面声明,直接在computed里面定义,然后就可以在页面上进行双向数据绑定展示出结果或者用作其他处理

你可以像绑定普通 property 一样在模板中绑定计算属性。Vue 知道 vm.reversedMessage 依赖于 vm.message,因此当 vm.message 发生改变时,所有依赖 vm.reversedMessage 的绑定也会更新。而且最妙的是我们已经以声明的方式创建了这种依赖关系:计算属性的 getter 函数是没有副作用 (side effect) 的,这使它更易于测试和理解。

<div>
  <p>Original message: "{{ message }}"</p>
  <p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
export default {
	data () {
	return {
        message: 'Hello'
      }
    },
	computed: {
	  // 计算属性的 getter
	  reversedMessage: function () {
	    // `this` 指向 vm 实例
	    return this.message.split('').reverse().join('')
	  }
	}
}

在这里插入图片描述


2. computed比较适合对多个变量或者对象进行处理后返回一个结果值,也就是数多个变量中的某一个值发生了变化则我们监控的这个值也就会发生变化

举例:购物车里面的商品列表和总金额之间的关系,只要商品列表里面的商品数量发生变化,或减少或增多或删除商品,总金额都应该发生变化。这里的这个总金额使用computed属性来进行计算是最好的选择

<div>
  <table border=1 width="200">
    <tr>
      <th width="100px">商品</th>
      <th width="100px">价格</th>
      <th width="100px">数量</th>
    </tr>
    <tr v-for="(item,index) in results" :key="index"  align="center">
      <td>{{item.name}}</td>
      <td>{{item.price | priceFilter}}</td>
      <td><input  v-model="item.theNum"></td>
    </tr>
    <tr>
      <td colspan="3" style="text-align:right">总计:{{totalMoney | priceFilter}}元</td>
    </tr>
  </table>
</div>
export default {
	data () {
      return {
        results:[
          {
            name:"苹果",
            price:1000,
            theNum:3
          },
          {
            name:"香蕉",
            price:1500,
            theNum:2
          },
          {
            name:"西瓜",
            price:3000,
            theNum:1
          },
        ]
      }
    },
    filters:{
      priceFilter(value){
        if (!value) return ''
        return '¥'+(value/100).toFixed(2)
      },
    },
	computed: {
	  totalMoney(){
	    let total = 0;
	    let _this = this;
	    _this.results.forEach(item => {
	        //计算总价格
	        total += item.price * item.theNum;
	   });
	   return total
	  }
	}
}

在这里插入图片描述

3. 计算属性的 setter

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

<div>
	<p>firstName:{{ firstName }}</p>
	<p>lastName:{{ lastName }}</p>
	<p>fullName:{{ fullName }}</p>
</div>
export default {
	data () {
		return {
			firstName: 'Foo',
			lastName: 'Bar'
        }
    },
	computed: {
		fullName:{
		   get(){//回调函数 当需要读取当前属性值是执行,根据相关数据计算并返回当前属性的值
		          return this.firstName + ' ' + this.lastName
		        },
		      set(val){//监视当前属性值的变化,当属性值发生变化时执行,更新相关的属性数据
		            //val就是fullName的最新属性值
					const names = val.split(' ');
					this.firstName = names[0];
					this.lastName = names[1];
		      }
		}
	}
}

在这里插入图片描述
现在再运行 app.fullName = ‘John Doe’ 时,setter 会被调用,app.firstName 和 app.lastName 也会相应地被更新。
在这里插入图片描述


三、computed和watch的区别

1. watch特性

1. 是观察的动作
2. 应用:监听props,$emit或本组件的值执行异步操作
3.无缓存性,页面重新渲染时值不变化也会执行
4.watch里监听的属性必须是已存在的,其要么是data里的属性,要么是computed里计算出来的属性
5.一次只能监听一个属性,这个属性函数接收两个参数,一个是新值一个是旧值

2. computed特性

1. 是计算值
2. 应用:就是简化tempalte里面{{}}计算和处理props或$emit的传值
3. 具有缓存性,页面重新渲染值不变化,计算属性会立即返回之前的计算结果,而不必再次执行函数
4.computed里自定义的属性不能与data里的属性重复,否则会报错
5.可以监听一个或多个它所依赖的数据项

四、vue在线测试工具:点击跳转

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值