4. vue Reactivity
4.1 data
我们使用data
选项来声明组件的反应状态。选项值应该是一个返回对象的函数。Vue
会在创建新组件实例时调用该函数,并将返回的对象包装在其响应系统中。此对象的任何顶级属性都代理在组件实例上(this
在方法和生命周期挂钩中):
data() {
return {
}
}
这些实例属性仅在首次创建实例时添加,因此您需要确保它们都存在于函数返回的对象中data
。如有必要,使用null
或undefined
其他一些占位符值来表示所需值尚不可用的属性。
4.2 methods
Vue 自动绑定this
值,methods
以便它始终引用组件实例。这可确保方法在this
用作事件侦听器或回调时保留正确的值。定义 时应避免使用箭头函数methods
,因为这会阻止 Vue 绑定适当的this
值:
export default {
methods: {
increment: () => {
}
}
}
4.3 computed
能够将计算结果缓存起来的属性(将行为转化成了静态的属性)
计算属性就是一个提前定义好的方法, 该方法可以看作是一个特殊的值, 可以在插值表达式中使用.
计算属性的主要特性就是为了将不经常变化的计算结果进行缓存,以节约我们的系统开销;
computed
比较适合对多个变量或者对象进行处理后返回一个结果值,也就是数多个变量中的某一个值发生了变化则我们监控的这个值也就会发生变化
var app = new Vue({
el:"#app",
// 计算属性必须放在Vue的computed中
computed:{
// 定义计算属性
// 有方法的皮, 但是却是当作属性使用
// 这里一定要有return, 否则, 调用的时候无法拿到结果
属性名() {
return "返回值";
}
}
});
setup
import {
computed } from 'vue'
setup(){
// 简写语法
let fullName = computed(() => {
return person.firstName + '-' + person.lastName
})
// 完整语法
let fullName = computed({
get(){
return person.firstName + '-' + person.lastName
},
set(value){
const nameArr = value.split('-')
person.firstName = nameArr[0]
person.lastName = nameArr[1]
}
})
return fullName
}
4.4 watch
计算属性允许我们以声明方式计算派生值。但是,在某些情况下,我们需要执行“副作用”以响应状态更改——例如,改变 DOM
,或根据异步操作的结果更改另一部分状态。
watch
中的属性 一定是data
中 已经存在的数据
watch
类似于onchange
事件,可以在属性值修改的时候,执行某些操作.
<div id="app">
<div>
<span>名:</span>
<span>
<input type="text" v-model='firstName'>
</span>
</div>
<div>
<span>姓:</span>
<span>
<input type="text" v-model='lastName'>
</span>
</div>
<div>{
{fullName}}</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
firstName: 'Jim',
lastName: 'Green',
fullName: 'Jim Green'
},
//watch 属性 定义 和 data 已经 methods 平级
watch: {
// 注意: 这里firstName 对应着data 中的 firstName
// 当 firstName 值 改变的时候 会自动触发 watch
firstName: function(val) {
this.fullName = val + ' ' + this.lastName;
},
// 注意: 这里 lastName 对应着data 中的 lastName
lastName: function(val) {
this.fullName = this.firstName + ' ' + val;
}
}
});
</script>
当需要监听一个对象的改变时,普通的watch
方法无法监听到对象内部属性的改变,只有data
中的数据才能够监听到变化,此时就需要deep属性对对象进行深度监听
var app = new Vue({
el:"#app",
data:{
message:"白大锅",
person:{
"name":"heima", "age":13}
},
// watch监听
watch:{
// 监听message属性值,newValue代表新值,oldValue代表旧值
message(newValue, oldValue){
console.log("新值:" + newValue + ";旧值:" + oldValue);
},
// 监控person对象的值,对象的监控只能获取新值
person: {
// 开启深度监控;监控对象中的属性值变化
deep: true,
// 获取到对象的最新属性数据( newValue 代表新对象)
handler(newValue, oldValue){
console.log("name = " + newValue.name + "; age=" + newValue.age);
}
}
}
});
setup
// 情况一:监视 ref 定义的响应式数据
watch(sum, (newValue, oldValue) => {
console.log('sum变化了', newValue, oldValue)
}, {
immediate:true})
// 情况二:监视多个 ref 定义的响应式数据
watch([sum, msg], (newValue,oldValue) => {
console.log('sum或msg变化了', newValue,oldValue)
})
// 情况三:监视 reactive 定义的响应式数据
// 若 watch 监视的是 reactive 定义的响应式数据,则无法正确获得 oldValue , 而且强制开启了深度监视
watch(person, (newValue, oldValue) => {
console.log('person变化了', newValue, oldValue)
}, {
immediate:true, deep:false }) // 此处的deep配置不再奏效
// 情况四:监视 reactive 定义的响应式数据中的某个属性
watch(() => person.job, (newValue, oldValue) => {
console.log('person的job变化了', newValue, oldValue)
}, {
immediate:true, deep:true })
// 情况五:监视reactive定义的响应式数据中的某些属性
watch([() => person.job, () => person.name], (newValue, oldValue) => {
console.log('person的job变化了', newValue, oldValue)
}, {
immediate:true, deep:true })
// 特殊情况:此处由于监视的是reactive定义的对象中的某个属性,所以deep配置有效
watch(() => person.job, (newValue, oldValue) => {
console.log('person的job变化了', newValue, oldValue)
}, {
deep:true })
4.5 watchEffect
和watch
的区别是,watch
既要指明监视的属性,也要指明监视的回调。而watchEffect
,不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性,不用写返回值。
// 回调中用到的数据只要发生变化,则直接重新执行回调
watchEffect(() => {
const x1 = sum.value
const x2 = person.age
console.log('watchEffect配置的回调执行了')
})