zoukankan      html  css  js  c++  java
  • vue3

    总结

    • 计算属性
    const count = ref(1)
    const plusOne = computed(() => count.value + 1)
    // 或
    const plusOne = computed({
      get: () => count.value + 1,
      set: val => {
        count.value = val - 1
      }
    })
    
    • watchEffect:可以监听多个数据的变动,来执行副作用,默认情况在所有组件 update 前执行,允许传入配置项 flush: 'post' 在页面渲染之后执行,类似 nextTick。
      • 会在 setup 中创建时立即执行,可以被停止。
      • 当监听的数据变动时副作用进入队列,在同一个 tick 中去抖动。可以传入 flush:'sync' 强制立即执行。
      • onInvalidate 用于清除副作用,在该副作用被重新执行或侦听器被停止时(如果在 setup() 或生命周期钩子函数中使用了 watchEffect,则在组件卸载时?)。
      • 在异步副作用中,清理函数必须要在 Promise 被 resolve 之前被注册
    const count = ref(0)
    
    const stop = watchEffect(async onInvalidate => {
      onInvalidate(() => {
        // dosome
      })
      console.log(count.value)
    },{
      flush: 'post'
    })
    stop()
    
    • watch 可以把一个函数作为侦听对象,类似于监听了计算属性,还可以使用数组同时侦听多个源
      • 使用侦听器来比较一个数组或对象的值,这些值是响应式的,要求它有一个由值构成的副本。(数组和对象是引用类型,如果不是副本 count, prevCount 会是同一个)
      • 尝试检查深度嵌套对象或数组中的 property 变化时,仍然需要 deep 选项设置为 true。
      • 与 watchEffect共享停止侦听,清除副作用 (相应地 onInvalidate 会作为回调的第三个参数传入)、副作用刷新时机和侦听器调试行为。
    watch(
      () => state.count,
      (count, prevCount) => {
        
      }
    )
    // 直接侦听ref
    const count = ref(0)
    watch(count, (count, prevCount) => {
      
    },{ deep: true })
    // 侦听多个数据源
    const firstName = ref('');
    const lastName = ref('');
    watch([firstName, lastName], (newValues, prevValues) => {
      console.log(newValues, prevValues);
    })
    

    原文地址 v3.cn.vuejs.org

    # 计算值

    有时我们需要依赖于其他状态的状态——在 Vue 中,这是用组件计算属性处理的,以直接创建计算值,我们可以使用 computed 方法:它接受 getter 函数并为 getter 返回的值返回一个不可变的响应式 ref 对象。

    const count = ref(1)
    const plusOne = computed(() => count.value + 1)
    
    console.log(plusOne.value) 
    
    plusOne.value++ 
    

    或者,它可以使用一个带有 getset 函数的对象来创建一个可写的 ref 对象。

    const count = ref(1)
    const plusOne = computed({
      get: () => count.value + 1,
      set: val => {
        count.value = val - 1
      }
    })
    
    plusOne.value = 1
    console.log(count.value) 
    

    # watchEffect

    为了根据响应式状态_自动应用_和_重新应用_副作用,我们可以使用 watchEffect 方法。它立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数。

    const count = ref(0)
    
    watchEffect(() => console.log(count.value))
    
    
    setTimeout(() => {
      count.value++
      
    }, 100)
    

    # 停止侦听

    watchEffect 在组件的 setup() 函数或生命周期钩子被调用时,侦听器会被链接到该组件的生命周期,并在组件卸载时自动停止。

    在一些情况下,也可以显式调用返回值以停止侦听:

    const stop = watchEffect(() => {
      
    })
    
    stop()
    

    # 清除副作用

    有时副作用函数会执行一些异步的副作用,这些响应需要在其失效时清除 (即完成之前状态已改变了) 。所以侦听副作用传入的函数可以接收一个 onInvalidate 函数作入参,用来注册清理失效时的回调。当以下情况发生时,这个失效回调会被触发:

    • 副作用即将重新执行时
    • 侦听器被停止 (如果在 setup() 或生命周期钩子函数中使用了 watchEffect,则在组件卸载时)
    watchEffect(onInvalidate => {
      const token = performAsyncOperation(id.value)
      onInvalidate(() => {
        // id has changed or watcher is stopped.
        // invalidate previously pending async operation
        token.cancel()
      })
    })
    

    我们之所以是通过传入一个函数去注册失效回调,而不是从回调返回它,是因为返回值对于异步错误处理很重要。
    在执行数据请求时,副作用函数往往是一个异步函数:

    const data = ref(null)
    watchEffect(async onInvalidate => {
       onInvalidate(() => {  }) 
      data.value = await fetchData(props.id)
    })
    

    我们知道异步函数都会隐式地返回一个 Promise,但是清理函数必须要在 Promise 被 resolve 之前被注册。另外,Vue 依赖这个返回的 Promise 来自动处理 Promise 链上的潜在错误。

    疑问:当 promise 内的其他异步错误时,会被当前 promise 捕获?

    # 副作用刷新时机

    Vue 的响应性系统会缓存副作用函数,并异步地刷新它们,这样可以避免同一个 “tick” 中多个状态改变导致的不必要的重复调用。在核心的具体实现中,组件的 update 函数也是一个被侦听的副作用。当一个用户定义的副作用函数进入队列时,默认情况下,会在所有的组件 update 执行:

    <template>
      <div>{{ count }}</div>
    </template>
    
    <script>
      export default {
        setup() {
          const count = ref(0)
    
          watchEffect(() => {
            console.log(count.value)
          })
    
          return {
            count
          }
        }
      }
    </script>
    

    在这个例子中:

    • count 会在初始运行时同步打印出来
    • 更改 count 时,将在组件更新前执行副作用。

    如果需要在组件更新 (例如:当与模板引用一起) 重新运行侦听器副作用,我们可以传递带有 flush 选项的附加 options 对象 (默认为 'pre'):

    // 在组件更新后触发,这样你就可以访问更新的 DOM。
    // 注意:这也将推迟副作用的初始运行,直到组件的首次渲染完成。
    watchEffect(
      () => {
        
      },
      {
        flush: 'post'
      }
    )
    

    flush 选项还接受 sync,这将强制效果始终同步触发。然而,这是低效的,应该很少需要。

    # 侦听器调试

    onTrackonTrigger 选项可用于调试侦听器的行为。

    • onTrack 将在响应式 property 或 ref 作为依赖项被追踪时被调用。
    • onTrigger 将在依赖项变更导致副作用被触发时被调用。

    这两个回调都将接收到一个包含有关所依赖项信息的调试器事件。建议在以下回调中编写 debugger 语句来检查依赖关系:

    watchEffect(
      () => {
        
      },
      {
        onTrigger(e) {
          debugger
        }
      }
    )
    

    onTrackonTrigger 只能在开发模式下工作。

    # watch

    watch API 完全等同于组件侦听器 property。watch 需要侦听特定的数据源,并在回调函数中执行副作用。默认情况下,它也是惰性的,即只有当被侦听的源发生变化时才执行回调。

    • watchEffect 比较,watch 允许我们:

      • 懒执行副作用;
      • 更具体地说明什么状态应该触发侦听器重新运行;
      • 访问侦听状态变化前后的值。

    # 侦听单个数据源

    侦听器数据源可以是返回值的 getter 函数,也可以直接是 ref

    注释:等价于监听了一个计算属性

    // 侦听一个 getter
    const state = reactive({ count: 0 })
    watch(
      () => state.count,
      (count, prevCount) => {
        
      }
    )
    
    // 直接侦听ref
    const count = ref(0)
    watch(count, (count, prevCount) => {
      
    })
    

    # 侦听多个数据源

    侦听器还可以使用数组同时侦听多个源:

    const firstName = ref('');
    const lastName = ref('');
    
    watch([firstName, lastName], (newValues, prevValues) => {
      console.log(newValues, prevValues);
    })
    
    firstName.value = "John";  // logs: ["John",""] ["", ""]
    lastName.value = "Smith";  // logs: ["John", "Smith"] ["John", ""]
    

    # 侦听响应式对象

    使用侦听器来比较一个数组或对象的值,这些值是响应式的,要求它有一个由值构成的副本。

    注释:因为数组和对象是引用类型,如果没有副本 old 和 new 会是同一个值

    const numbers = reactive([1, 2, 3, 4])
    
    watch(
      () => [...numbers],
      (numbers, prevNumbers) => {
        console.log(numbers, prevNumbers);
      })
    
    numbers.push(5)  // logs: [1,2,3,4,5] [1,2,3,4]
    

    尝试检查深度嵌套对象或数组中的 property 变化时,仍然需要 deep 选项设置为 true。

    const state = reactive({ 
      id: 1, 
      attributes: { 
        name: "",
      },
    });
    
    watch(
      () => state,
      (state, prevState) => {
        console.log(
          "not deep ",
          state.attributes.name,
          prevState.attributes.name
        );
      }
    );
    
    watch(
      () => state,
      (state, prevState) => {
        console.log(
          "deep ",
          state.attributes.name,
          prevState.attributes.name
        );
      },
      { deep: true }
    );
    
    state.attributes.name = "Alex";   // 日志: "deep " "Alex" "Alex"
    

    #watchEffect 共享的行为

    watchwatchEffect共享停止侦听清除副作用 (相应地 onInvalidate 会作为回调的第三个参数传入)、副作用刷新时机侦听器调试行为。

  • 相关阅读:
    SQLServer数据库自增长标识列的更新修改操作
    “~/Views/Login/Login.aspx”处的视图必须派生自 ViewPage、ViewPage<TModel>、ViewUserControl 或 ViewUserControl<TModel>。
    关于值类型与列类型不匹配,所需类型是 DataRow"的解决方案
    尝试为文件 F:visual studio 2010kbspaperCMSApp_DataProject.mdf 附加自动命名的数据库,但失败。已存在同名的数据库,或指定的文件无法打开或位于 UNC 共享目录中。
    Django快速开发之投票系统
    super() 的入门使用
    [python]模块及包
    [转]大话后端开发的奇淫技巧大集合
    [.net 多线程]ThreadPool的安全机制
    [.net 多线程]Task
  • 原文地址:https://www.cnblogs.com/qq3279338858/p/14516134.html
Copyright © 2011-2022 走看看