- computed & watch & methods
computed & watch:当某一个数据(依赖数据)发生变化的时候,自动调用相关的函数去实现数据的变动。
methods:用来定义函数,需要调用。但是,methods也可以在模板中使用。
- 当模版中的某个循环的值需要进行一定逻辑运算时,可以使用methods方法,将对应的值传入,然后计算出结果返回到模版显示,computed中无法传参,在这种情况下无法实现。但是methods无缓存,开销要大一点。
<div v-for="(item, idx) in arr">
{{ matching(item) }}
</div>
methods: {
matching (key) {
if (this.obj[key]) {
return this.obj[key]
} else {
return 'not found'
}
}
}
computed是计算属性,事实上和data对象里的数据属性是同一类的(使用上),在取值的时候,用this.fullName去取用,就和取data一样(不要当成函数调用!!)
-
所依赖的属性一定是响应式依赖,否则计算属性不会执行
-
具有缓存性,页面重新渲染值不变化,计算属性会立即返回之前的计算结果,而不必再次执行函数,节省开销
-
举例:对data数据进行操作,可以直接在模板中对某值进行计算,比如将数组转化为字符串,这种方式会造成额外开销,而因为computed具有缓存性,依赖未更新返回值不会改变,减少开销。
-
computed擅长处理的场景:一个数据受多个数据影响
-
复杂的渲染数据计算,用computed计算属性可以减少一定计算开销,增加可维护性
-
简化tempalte里面{{}}计算和处理props或$emit的传值
-
表单校验,这个应用场景应该是比较常见的,利用正则表达式对每个表单项的实时监控,判断表单是否可以提交
-
从Vuex Store中收集相关信息,对Vuex中的数据做计算的时候的要特别注意computed的缓存属性,在对Vuex中的对象值进行属性修改的时候,并不会触发computed的中值的变化,这时需要Object.assign({},obj)对依赖对象进行跟新返回一个新对象触发依赖跟新
-
watch:用来监听data中数据变动,
-
也可以获取属性的新值和旧值。
-
还可以用来监听路由的变化
watch:{
//不能使用箭头函数,因为this会向上绑定
selected:function (newV,oldV) {
console.log(newV);
this.$router.push({
name:newV,//按名字跳到指定的路由
})
}
}
- 结果不会被缓存,页面重新渲染时值不变化也会执行
data:{
firstname:"",
lastname:""
},
watch:{
firstname:function(newValue,OldValue){
console.log(newValue);
console.log(OldValue);
},
'$route.path':function(newValue,OldValue){
console.log(newValue);
console.log(OldValue);
}
}
watch擅长处理的场景:一个数据影响多个数据 ;
-
应用:监听props,$emit或本组件的值执行异步操作,当执行异步操作时必须用watch而不是computed
例子:当在模版中调用getObj.a时,加异步操作就会导致没有返回值同时调用对象的属性,就会报错;而调用obj1.a却不一样,模版会先显示hello,watch监测的属性发生变化,setTimeout触发,一秒钟之后模版会显示helloword。
<div>{{ obj1.a }}</div>
data: {
obj: {a: 'hello'},
obj1: {a: 'hello'},
test: 'aaa'
},
computed: {
getObj () {
setTimeout(() => {
this.obj.a = this.test + 'word'
return this.obj
}, 1000)
}
},
watch: {
test () {
setTimeout(() => {
this.obj1.a = this.test + 'word'
}, 1000)
}
},
mounted () {
this.test = 'hello'
}
简单实现:
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)
}
function watch(ctx, obj) {
Object.keys(obj).forEach(key => {
defineReactive(ctx.data, key, ctx.data[key], function(value) {
obj[key].call(ctx, value)
})
})
}
网友评论