vue 怎么监听变量值_Vue中计算属性、方法与侦听属性的区别?

本文总结了Vue中计算属性computed和侦听属性watch的特性和应用场景。计算属性用于简化模板中的复杂计算,具有缓存性;而watch主要用于监听数据变化执行异步操作,无缓存。两者在数据监听和处理上存在明显区别。
摘要由CSDN通过智能技术生成

总结:

1. 计算属性computed在使用时,一定要注意,函数里面的变量都会被监听,只要里面的某一个值变动,便会将整个函数执行一遍。 而 watch 只是监听某一个值,若是监听的值里面也有很多变量,也会全部监听

2. 计算后的属性可不在 data 中定义,如果定义会报错,因为对应的computed作为计算属性定义并返回对应的结果给这个变量,变量不可被重复定义和赋值。 而 watch 监听 data 中定义的变量变化

computed特性

1.是计算值,

2.应用:就是简化tempalte里面{{}}计算和处理props或$emit的传值

3.具有缓存性,页面重新渲染值不变化,计算属性会立即返回之前的计算结果,而不必再次执行函数

watch特性

1.是观察的动作,

2.应用:监听props,$emit或本组件的值执行异步操作

3.无缓存性,页面重新渲染时值不变化也会执行

接下来介绍下 各自的方法:

1. 计算属性 computed

在一个计算属性里可以完成各种复杂的逻辑,包括运算、函数调用等,只要最终返回一个结果就可以。

Original message: "{{ message }}"

Computed reversed message: "{{ reversedMessage }}"

// 我们把复杂处理放在了计算属性里面了

var vm = new Vue({

el: '#example',

data: {

message: 'Hello'

},

computed: {

reversedMessage: function () {

// `this` 指向 vm 实例

return this.message.split('').reverse().join('')

}

}

});

结果:

Original message: "Hello"

Computed reversed message: "olleH"

计算属性还可以依赖多个Vue 实例的数据,只要其中任一数据变化,计算属性就会重新执行,视图也会更新。

每一个计算属性都包含一个getter和一个setter ,我们上面的两个示例都是计算属性的默认用法, 只是利用了getter 来读取。

在你需要时,也可以提供一个setter 函数, 当手动修改计算属性的值就像修改一个普通数据那样时,就会触发setter 函数,执行一些自定义的操作,例如:

{{ fullName }}

var vm = new Vue({

el: '#demo',

data: {

firstName: 'zhang',

lastName: 'san'

},

computed: {

fullName: {

//getter 方法

get(){

console.log('computed getter...')

return this.firstName + ' ' + this.lastName

},

//setter 方法

set(newValue){

console.log('computed setter...')

var names = newValue.split(' ')

this.firstName = names[0]

this.lastName = names[names.length - 1]

return this.firstName + ' ' + this.lastName

}

}

},

updated () {

console.log('updated')

}

})

我们可以看到,input 是直接绑 v-model="fullName",如果我们这里直接修改了fullName的值,那么就会触发setter,同时也会触发getter以及updated函数。其执行顺序是setter -> getter -> updated,如下:

console.log('computed setter...')

console.log('computed getter...')

console.log('updated')

注意:并不是触发了setter也就会触发getter,他们两个是相互独立的。我们这里修改了fullName会触发getter是因为setter函数里有改变firstName 和 lastName 值的代码。

2. 方法

除了使用计算属性外,我们也可以通过在表达式中调用方法来达到同样的效果,如:

{{reverseTitle()}}

methods: {

reverseTitle: function () {

return this.title.split('').reverse().join('')

}

}

我们可以将同一函数定义为一个方法而不是一个计算属性,两种方式的最终结果确实是完全相同的。只是一个使用reverseTitle()取值,一个使用reverseTitle取值。

然而,不同的是计算属性是基于它们的依赖进行缓存的。计算属性只有在它的相关依赖发生改变时才会重新求值。

这就意味着只要 title还没有发生改变,多次访问 reverseTitle计算属性会立即返回之前的计算结果,而不必再次执行函数。

3. 侦听属性 watch

watch监控自身属性变化:

new Vue({

el: '#app',

data: {

firstName: 'hello',

lastName: 'vue',

fullName: 'hello.ve'

},

watch: {

'firstName': function(newval, oldval) {

// console.log(newval,oldval);

this.fullName = this.firstName + this.lastName;

},

'lastName': function(newval, oldval) {

// console.log(newval,oldval);

this.fullName = this.firstName + this.lastName;

}

}

});

watch监控路由对象:

new Vue({

el: '#app',

router: router, //开启路由对象

watch: {

'$route': function(newroute, oldroute) {

console.log(newroute, oldroute);

//可以在这个函数中获取到当前的路由规则字符串是什么

//那么就可以针对一些特定的页面做一些特定的处理

}

}

})

watch监听对象的单个属性:

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

data(){

return{

'first':{

second:0

}

}

},

computed:{

secondChange(){

return this.first.second

}

},

watch:{

secondChange(){

console.log('second属性值变化了')

}

},

简单实现 computed和watch

公共类

function defineReactive(data, key, val, fn) {

let subs = [] // 新增

Object.defineProperty(data, key, {

configurable: true,

enumerable: true,

get: function() {

// 新增

if (data.$target) {

subs.push(data.$target)

}

return val

},

set: function(newVal) {

if (newVal === val) return

fn && fn(newVal)

// 新增

if (subs.length) {

// 用 setTimeout 因为此时 this.data 还没更新

setTimeout(() => {

subs.forEach(sub => sub())

}, 0)

}

val = newVal

},

})

}

computed实现

function computed(ctx, obj) {

let keys = Object.keys(obj)

let dataKeys = Object.keys(ctx.data)

dataKeys.forEach(dataKey => {

defineReactive(ctx.data, dataKey, ctx.data[dataKey])

})

let firstComputedObj = keys.reduce((prev, next) => {

ctx.data.$target = function() {

ctx.setData({ [next]: obj[next].call(ctx) })

}

prev[next] = obj[next].call(ctx)

ctx.data.$target = null

return prev

}, {})

ctx.setData(firstComputedObj)

}

watch实现

function watch(ctx, obj) {

Object.keys(obj).forEach(key => {

defineReactive(ctx.data, key, ctx.data[key], function(value) {

obj[key].call(ctx, value)

})

})

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值