vue3的api解读-watch

目录

副作用(Side Effect)

纯粹计算背后的效果【我们做UI时非常需要】

副作用的封装(伪代码)

副作用失效(Invalidate)问题

API:WatchEffect

Coding:WatchEffect【演示代码】

/src/examples/WatchExamplese.tsx【watchEffect】

API:Watch

Coding:Watch

/src/examples/WatchExamplese.tsx【watch】

小结


副作用(Side Effect)

  • 副作用是计算之外的行为
  • view = f(props)with effect[]
function SomeComponent(a, b) {
    window.location.href = '...' // 副作用
    const c = ref(0) // 副作用
    watchEffect(..) // 副作用
    return 
{a+b+c.value}
}

纯粹计算背后的效果【我们做UI时非常需要】

  • 点击Tab时,切换了`activeKey`,同时改变当前url(history.replace)
  • 删除文件时操作目录结构,同时写入磁盘

副作用的封装(伪代码)

根据数据变化,触发副作用

function HomePage {
    watch(activeKey, () => {
        history.repace(...)    
    })
    
    return () => {
        return ...    
    }
}

副作用失效(Invalidate)问题

  • 快速切换页面的场景
const currentIndex = ref("")
// 点击打开A
currentIndex.value = "A"
// 点击打开B
currentIndex.value = "B"
// A还没打开,就继续执行打开B,这时候就是A副作用失效

API:WatchEffect

  • 目标:监听副作用,并封装副作用
  • 监听哪些副作用?
    • reactive值变化(track,tigger)
    • 页面渲染
  • watchEffect会依赖用到的reactive值(类似渲染函数)

Coding:WatchEffect【演示代码】

  • 常规用法
  • watchEffect的依赖收集
  • 执行时机
  • 副作用失效问题

/src/examples/WatchExamplese.tsx【watchEffect】

import { ref, defineComponent, watchEffect, onUnmounted } from 'vue'
export const WatchExample01 = defineComponent({
  setup() {
    // 常规用法
    const count = ref(0)
    // effect (效果)?? --副作用(side effect)
    // 提供副作用,封装副作用,也在依赖副作用,会先执行一次,收集依赖
    watchEffect(() => { // 副作用中用到了,才能追踪到
      // watchEffect的依赖收集
      console.log('im running...') // 单写打印,不会执行,因为没有依赖副作用,追踪不到
      // console.log('im running...', count.value) // 会执行,因为有依赖
      document.title = "count:" + count.value // 会执行,因为有依赖
      // history.replaceState({}, "", "/count/" + count.value)
    })
    return () => {
      return 
                {count.value}      
    }   } }) export const WatchExample02 = defineComponent({   setup() {     // 执行时机     const count = ref(0)     // effect (效果)?? --副作用(side effect)     // 提供副作用,封装副作用,也在依赖副作用,会先执行一次,收集依赖     watchEffect(() => { // 副作用中用到了,才能追踪到       console.log('im running...') // 单写打印,不会执行,因为没有依赖副作用,追踪不到       // console.log('im running...', count.value) // 会执行,因为有依赖       // document.title = "count:" + count.value // 会执行,因为有依赖       // history.replaceState({}, "", "/count/" + count.value)     }, {       flush: "sync" // post 后于render执行; pre 先于render执行; sync先于render执行     })     // 执行时间线 sync【同步依赖变化第一时间执行】 // ... tick【vue闲时执行】 ... pre ... render ... post     return () => {       console.log('render...')       return
                {count.value}      
    }   } }) export const WatchExample03 = defineComponent({   setup() {     // 副作用失效问题     const count = ref(0)     // effect (效果)?? --副作用(side effect)     // 提供副作用,封装副作用,也在依赖副作用,会先执行一次,收集依赖     watchEffect((onInvalidate) => { // 副作用中用到了,才能追踪到       console.log(count.value)       let I = setInterval(() => {         count.value++       }, 1000)       // onInvalidate第二次执行时会清除前一次的I,关于副作用失效的问题       onInvalidate(() => {// 如果没有它的话,会越来越快         clearInterval(I)       })       // console.log('im running...') // 单写打印,不会执行,因为没有依赖副作用,追踪不到     })     // 执行时间线 sync【同步依赖变化第一时间执行】 ... tick【vue闲时执行】 ... pre ... render ... post     return () => {       return
        {count.value}      
    }   } }) export const WatchExample04 = defineComponent({   setup() {     // 副作用失效问题     const count = ref(0)     let I = setInterval(() => {       count.value++     }, 1000)     onUnmounted(() => { // 组件卸载时候执行的钩子       clearInterval(I)     })     // effect (效果)?? --副作用(side effect)     // 提供副作用,封装副作用,也在依赖副作用,会先执行一次,收集依赖     // const stop = watchEffect((onInvalidate) => { // 副作用中用到了,才能追踪到     //   console.log(count.value)     //   let I = setInterval(() => {     //     count.value++     //   }, 1000)     //   // onInvalidate第二次执行时会清除前一次的I,关于副作用失效的问题     //   onInvalidate(() => {// 如果没有它的话,会越来越快     //     clearInterval(I)     //   })     //   // console.log('im running...') // 单写打印,不会执行,因为没有依赖副作用,追踪不到     // })     // stop() // 只执行一次     // 执行时间线 sync【同步依赖变化第一时间执行】 ... tick【vue闲时执行】 ... pre ... render ... post     return () => {       return
        {count.value}      
    }   } })

API:Watch

  • 目标:监听某个reactive值的副作用/监听某个属性变化
  • 有针对性的监听语义更明确(推荐不用watchEffect)

Coding:Watch

  • 监听某个reactive值,封装副作用
  • 监听属性变化。依赖问题
  • 执行时机的问题

/src/examples/WatchExamplese.tsx【watch】

import { ref, defineComponent, watch } from 'vue'

export const WatchExample05 = defineComponent({
  // 监听某个reactive值,封装副作用
  setup() {
    const count = ref(0)
    // 指定响应式值的监听,不需要如watchEffect开始执行一次进行依赖收集
    watch(count, () => {
      console.log('count', count)
    })
    setTimeout(() => {
      count.value++
    }, 1000)
    return () => 
      {count.value}    
  } }) export const WatchExample06 = defineComponent({   setup() {     const a = ref(0)     const b = ref(0)     // const c = ref(a.value + b.value)     watch([a, b], (x, y) => {       // c.value = a.value + b.value // 第二种写法       // x是旧值,y是新值       console.log(x, y)     })     setInterval(() => {       a.value += 0.2     }, 500)     setInterval(() => {       b.value += 0.7     }, 500)     return () =>
      {a.value + b.value}       {/* {c.value} */}    
  } }) export const WatchExample07 = defineComponent({   // 监听属性变化。依赖问题   setup() {     const greetings = ref("hello")     setTimeout(() => {       greetings.value = "world!"     }, 1000)     return () => {       return
             
    }   } }) // const Item = ({ text }: { //   text: string // }) => { //   return
{text}
// } // 需要text变化时进行计算 const Item = defineComponent({   props: {     text: {       type: String     }   },   setup(props) {     // 子组件监听属性变化     // const textRef = ref(props.text)     // watch(textRef, ()=>{不执行,setup只执行一次})     // let x = 1     // watch(()=> x, ()=>{不触发,不是响应式值,vue不知道怎么触发})     watch(() => props.text, (to, from) => {       console.log("prop changed to", to, "old value is", from)     })     // setTimeout(() => {     //   x = 2     // }, 1000)     return () => {       return
{props.text}
    }   } }) export const WatchExample08 = defineComponent({   // 执行时机的问题   setup() {     const c = ref(0)     watch(c, () => { // 存在调度时间,会延迟一个周期执行       console.log("herep---------")     }, {       "immediate": true // 通常不会设置       // 设置为true,表示c变化之后,马上执行,例如c是某个事件的开关     })     return () => {       return
{         c.value++       }}>         {c.value}      
    }   } })

小结

  • 为什么不推荐用watchEffect?watch语法很有针对性,明确指出响应式值,减少耦合
  • 如何理解watch依赖副作用又触发副作用?watch监听响应式值变动,执行我们写的副作用,依赖的是vue这个渲染引擎,页面内容渲染也是副作用

你可能感兴趣的:(vue相关,#,vue3的api解读,vue.js,前端,typescript)