vue3的api解读-effect scope

什么是scope

  • 英文:范围
  • 举例:变量的可见范围(variable scope)
  • 举例:闭包内变量的可见范围是词法作用域(lexical scope)
  • 举例:slot-scope绑定的变量的可见范围是template内部

effect scope

  • 人为设置一个范围,对其内部的所有effect进行管理【可见,集中处理】
const scope = effectScope()
scope.run(()=>{
    // 副作用1
    const doubled = computed(()=> couter.value * 2) 
    // 副作用2
    watch(doubled, ()=> console.log(doubled.value))
    // 副作用3
    watchEffect(() => console.log('Count:', doubled.value))
})

// to dispose all effects in the scope; 
// 处理范围中的所有效果; 一次性注销掉副作用1, 2, 3
scope.stop()

effect scope示例讲解

effect scope的用法【使用场景比较窄】

  • Coding:实现控制MouseMove事件的开关

/src/examples/ScopeExamples.tsx

import {
  defineComponent,
  effectScope,
  watch,
  watchEffect,
  ref,
  reactive,
  toRefs,
  onUnmounted,// 组件卸载时候的钩子
  onScopeDispose,
} from "vue"
import type {
  Ref,
  EffectScope
} from "vue"
export const ScopeExample01 = defineComponent({
  setup() {
    // 如果第一个参数传true,那就不听父域的管了。
    const scope = effectScope()
    const c = ref(0)
    scope.run(() => {
      watch(c, () => {
        console.log('watch effect', c.value)
      })
    })
    setInterval(() => {
      c.value++
    }, 300)
    setTimeout(() => {
      scope.stop()
    }, 2000)
    return () => {
      return 
        {c.value}      
    }   } }) export const ScopeExample02 = defineComponent({   setup() {     const scope = effectScope()     const c = ref(0)     scope.run(() => {       const subScope = effectScope() // 可以嵌套       subScope.run(() => {         watch(c, () => {           console.log('watch effect', c.value)         })       })     })     setInterval(() => {       c.value++     }, 300)     setTimeout(() => {       // 父域作用停止,子域也停止       // 如果第一个参数传true,那就不听父域的管了。       // effectScope(true)       scope.stop()     }, 2000)     return () => {       return
        {c.value}      
    }   } }) function useMouseMove() {   const point = reactive({ x: 0, y: 0 })   function handler(e: MouseEvent) {     point.x = e.clientX     point.y = e.clientY   }   window.addEventListener("mousemove", handler)   onScopeDispose(() => { // scope.stop(),就会执行它     window.removeEventListener("mousemove", handler)   })   return toRefs(point) } export const ScopeExample03 = defineComponent({   setup() {     let point: {       x: Ref,       y: Ref     } | null = null // point开始是null所以第一次渲染没有存依赖     let scope: EffectScope | null = null     const active = ref(false)     watch(active, () => {       if (active.value) {         scope = effectScope()         point = scope.run(() => {           return useMouseMove()         })! // 后面这个!是断言不可能为null       } else {         scope?.stop() // 存在,就停止         point = null       }     })     return () => {       return
        {active.value && point is :  {point?.x.value}, {point?.y.value}}              
    }   } }) function useMouseMove1() { // 更好的封装,不用scope   const point = reactive({ x: 0, y: 0 })   const active = ref(false)   function handler(e: MouseEvent) {     point.x = e.clientX     point.y = e.clientY   }   watch(active, () => {     if (active.value) {       window.addEventListener("mousemove", handler)     } else {       window.removeEventListener("mousemove", handler)     }   })   return {     ...toRefs(point),     active   } } export const ScopeExample04 = defineComponent({   setup() {     const { x, y, active } = useMouseMove1() // point开始是null所以第一次渲染没有存依赖     let scope: EffectScope | null = null     return () => {       return
        {active.value && point is :  {x.value}, {y.value}}              
    }   } })
  • 思考:
    • 这个场景不用Scope行不行?可以呀,在useMouseMove(),提供个开关就可以了
    • 这样的场景多不多?很少

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