Vue3.0学习第五天 computed和watch

332 阅读2分钟

1-组合API-computed函数

  • 使用computed函数定义计算属性 基本使用:
// 演示代码
<template>
  <div class="container">
    <div>今年:{{age}}岁</div>
    <div>后年:{{newAge}}岁</div>
  </div>
</template>
<script>
import { computed, ref } from 'vue'
export default {
  name: 'App',
  setup () {
    // 计算属性:当你需要依赖现有的响应式数据,经过加工处理得到一个新的数据。
    const age = ref(16)
    // 通过computed函数得到后年的年龄
    const newAge = computed(()=>{
      // 该函数的返回值就是计算属性的值
      return age.value + 2
    })
    return {age, newAge}
  }
}
</script>

高级用法:

// 演示代码
<template>
  <div class="container">
    <div>今年:{{age}}岁</div>
    <div>后年:{{newAge}}岁</div>
    <!-- 使用v-model绑定计算属性的值 -->
    <input type="text" v-model="newAge">
  </div>
</template>
<script>
import { computed, ref } from 'vue'
export default {
  name: 'App',
  setup () {
    const age = ref(16)
    
    // 计算属性高级用法,传入对象,对象中包含get和set属性
    const newAge = computed({
      // get函数,获取计算属性的值
      get(){
        return age.value + 2
      },
      // set函数,当你给计算属性设置值的时候触发
      set (value) {
        age.value = value - 2
      }
    })
    return {age, newAge}
  }
}
</script>

目的:让计算属性支持双向数据绑定。

  • 总结:计算属性两种用法
    • 给computed传入函数,返回值就是计算属性的值
    • 给computed传入对象,get获取计算属性的值,set监听计算属性改变。

2-组合API-watch函数

使用watch函数定义侦听器

1.侦听简单类型响应式数据

// 演示代码
const num = ref(0);

// 修改num值时会触发 watch的回调
// 第一个参数是需要监听的目标,第二个参数是改变后触发的函数
watch(num,(newNum,oldNum)=>{
  console.log(newNum, oldNum);  
})

num = 1 // logs: 0 1

2.侦听复杂类型响应数据的某一属性

// 演示代码
const state = reactive({count: 1});

// 修改count值时会触发 watch的回调
// 第一个参数传入函数,该函数返回需要侦听响应对象的属性
watch(()=>state.count,(newCount,oldCount)=>{
  console.log(newCount,oldCount);
})

state.count = 2 // logs: 1 2

3.侦听多个数据源

// 演示代码
const state = reactive({count: 1});

const num = ref(0);

// 修改num或count值时会触发 watch的回调(注意:如果同时更改num和count只会触发一次)
// 第一个参数传入数组,该数组中是所有需要侦听的数据源
watch([()=>state.count,num],([newCount,newNum],[oldCount,oldNum])=>{
  console.log('new:',newCount,newNum);
  console.log('old:',oldCount,oldNum);
})

4.侦听响应式数组

// 演示代码
const numbers = reactive([1, 2, 3, 4])

watch(
  () => [...numbers],
  (oldNumbers, newNumbers) => {
    console.log(oldNumbers, newNumbers)
  }
)

numbers.push(5) // logs: [1,2,3,4] [1,2,3,4,5]

5.深度监听和默认执行

// 演示代码
const state = reactive({count: 1})

// watch函数的第三个参数传入一个配置属性对象
// 对象中deep属性设置为true即可深度监听,immediate属性设置为true即可默认执行
watch(
  () => state,
  (oldState, newState) => {
    console.log(oldState.count, newState.count)
  },
  { 
      deep: true,     // 深度监听(监听复杂数据类型子级的变化)
      immediate: true // 默认执行(页面打开立即执行一次)
  }
)

3-组合API-watchEffect函数

会立即执行传入的回调函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数

1.基本使用

    const userID = ref(0)
    
    watchEffect(() => console.log(userID))
    
    setTimeout(() => {
      // 改变userID的值
      userID.value = 1
    }, 1000)
    
    // logs:
    // 0
    // 1

2.停止侦听

  • 隐式停止侦听:组件卸载时自动停止侦听
  • 显式停止侦听:watchEffect函数会返回一个停止侦听的函数,使用这个函数可以手动停止侦听
// watchEffect函数会返回一个停止侦听的函数
const stop = watchEffect(() => {
  /* ... */
})

// 调用停止侦听函数后将不再侦听
stop()

3.清除副作用(onInvalidate)

适用场景:侦听userId发生改变时,重新发送请求获取用户信息,如果频繁触发可以使用onInvalidate停止上次请求(有点像防抖)

// 官网例子
watchEffect(onInvalidate => {
  // id改变触发
  const token = performAsyncOperation(id.value)
  onInvalidate(() => {
    // 取消上次请求
    token.cancel()
  })
})