• Vue3语法糖setup(二)


    在vue2中watch和computed这两个api对我们的帮助非常大,今天就说一说这两个Api

    computed

    computed在vue3中以函数形式存在,传入一个对象,当里面的依赖被读取是,调用get函数,被修改时调用set函数
    会返回一个ref对象 
    
    • 1
    • 2

    写一个经典案例

    有个需求,给你一个姓,一个名,需要我们输出姓名,有的同学可能会直接采用字符串拼接,这样也可以,但是我们现在使用计算属性来试一下

    set和get

    set函数中所依赖的变量,一但被修改,便会立即执行set函数

    get函数中所依赖的变量,只要被读取,就会执行get函数

    这两个函数很简单,是vue2中响应式的原理

    案例

    定义lastName,firstName,update更新函数,fullName为姓名

    setup() {
      const firstName = ref("李")
      const lastName = ref("华")
      const update = ()=>{
        firstName.value = "孙"
      }
      let fullName = computed({
        get(){
          console.log("get"+'函数被调用');
          return firstName.value+lastName.value
        },
        set(value){
          console.log(“set函数被调用”);
        }
      })
      return {
        fullName,
        update
      }
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    fullName为计算属性,当get依赖被修改时,会立即执行get函数,并且返回新的数据,当fullname本身被修改时才会调用,set函数,这两个是有区别的

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UZMaZeEW-1655790549116)(https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/52d0189e8e8b42a2877883187bce5ef2~tplv-k3u1fbpfcp-zoom-in-crop-mark:1956:0:0:0.image?)] 我们可以看到,当我们打开网页时,会先执行一次get函数,然后修改fristName时会再执行一次get函数

    Watch函数

    在setup里面提供了watchEffect和watch两个api,这两个都可以做监听,区别我们后面总结

    watchEffect

    watchEffect自动收集依赖,初始化运行,返回值为stop一个函数,调用会停止监听
    可以传入一个函数,第一次执行时自动收集获取依赖 
    
    • 1
    • 2

    这个函数不需要我们指定依赖,它会在第一次执行时,获取所对应的依赖

    setup() {
      const name = ref("scc")
      const age = ref(18)
      const update = ()=>{
        age.value++
    
      }
      watchEffect(()=>{
        console.log(age.value);
      })
      return {
        name,
        age,
        update
      }
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    定义一个name,age变量,update方法更新age,watchEffect监听age的值

    我们可以看一下运行结果

    watchEffect.gif 可以看到,在刷新浏览器时,程序自动运行了一次,而且我们是可以监听到age值得变化的

    flush属性

    先说一下setup中如何获取到dom元素,在vue2中,我们通过$refs获取dom元素,vue3中我们可以给dom元素一个ref属性,在setup中定义这个属性,并且传递出去,就可以通过这个属性获取到dom元素

    setup() {
          const root = ref(null)
          const name = ref("scc")
          watchEffect(()=>{
            console.log(root.value);
          })
          return {
            root
          } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    我们定义root,并且传递出去,给dom元素添加ref属性,看一下浏览器输出

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hDP7EQcQ-1655790549117)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f03b417d3116461a8ed10cbb8e6b4c49~tplv-k3u1fbpfcp-zoom-in-crop-mark:1956:0:0:0.image?)] 此时我们是可以获取到dom元素的,但是它执行两次,大家发现了没有,第一次输出了null,第二次才是dom元素

    这是为什么呢? 因为我们的watchEffect函数在dom没有刷新时初始化一次,dom挂载时又执行一次

    如何避免这种情况,能不能只执行一次

    是可以的,我们可以使用flush对象

    在watchEffect后面可以配置一个flush对象,默认为pre,初始化运行,可以修改为post初始化不运行

    我们尝试一下

    setup() {
      const root = ref(null)
      watchEffect(()=>{
        console.log(root.value);
      },{
        flush:"post"
      })
      return {
        root
      }
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    我们给watchEffect添加一个对象

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y2733LLa-1655790549118)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/21f7c00f0a034312827bd9c6c03fc9e6~tplv-k3u1fbpfcp-zoom-in-crop-mark:1956:0:0:0.image?)] 此时watchEffect只执行了一次

    stop

    watchEffect返回值为一个函数,执行此函数可以停止监听

    setup() {
      const name = ref("scc")
      const age = ref(18)
      const update = ()=>{
        age.value++
      }
      const stop = watchEffect(()=>{
        console.log(age.value);
        if(age.value>25){
          stop()
        }
      })
      return {
        name,
        age,
        update,
      }
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    我们监听age属性,当他大于25时,就停止监听

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bvbTvCgx-1655790549118)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3fd279adcad7431b88f2bfe312e6981d~tplv-k3u1fbpfcp-zoom-in-crop-mark:1956:0:0:0.image?)] 我们可以看到,当大于25时,页面还更新,但是已经不输出数据了

    watch

    watch第一个参数是要监听的值,可以是ref对象,reactive对象,回调函数,第二个参数是回调函数,当监听的值发生变化,就会调用回调函数

    监听reactive对象

    setup() {
      const info = reactive({age:18})
      const update = ()=>{
        console.log(info.age);
        info.age++
      }
      watch(info,(newValue,oldValue)=>{
        console.log(newValue+"------------------"+oldValue);
      },{
        deep:true
      })
      return{
        info,
        update
      }
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    定义info,updat更改info.age,watch监听info

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L7HRtseL-1655790549118)(https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/cb20ff4c06b3472da3eeafa070b41747~tplv-k3u1fbpfcp-zoom-in-crop-mark:1956:0:0:0.image?)] 确实可以监听info但是,oldvalue,newvalue似乎和预期的不一样

    这是因为newValue,oldValue也是reactive对象,想要变成值可以把reactive对象转换成对象()=>{return {…info}}

    setup() {
      const info = reactive({age:18,name:"scc"})
      const update = ()=>{
        console.log(info.age);
        info.age++
      }
      watch(()=>({...info}),(newValue,oldValue)=>{
        console.log(newValue,oldValue);
      })
      return{
        info,
        update
      }
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    我们对info进行解构,对结构后的对象进行监听

    watchReactive.gif

    可以看到,是没问题的

    监听ref对象

    setup() {
      const age = ref(18)
      const update = ()=>{
        console.log(age.value);
        age.value++
      }
      watch(age,(newValue,oldValue)=>{
        console.log(newValue,oldValue);
      })
      return{
        age,
        update
      }
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    创建ref对象age,update更新age,watch监听age

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yALsRxdW-1655790549119)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e8e1ee824b9a452f97b25d0449f187f3~tplv-k3u1fbpfcp-zoom-in-crop-mark:1956:0:0:0.image?)]

    可以正常监听,显示内容

    监听多个数据

    如果需要监听多个数据,可以传入一个数组 
    
    • 1

    watch第三个参数,配置项

    deep深度侦听默认为true,结构出来对象没有侦听,需要开启
    immediate最开始是否运行 
    
    • 1
    • 2

    结束

    到此结束,明天接着更新 
    
    • 1
  • 相关阅读:
    VD6283TX环境光传感器驱动开发(2)----获取光强和色温
    一些与“区别“相关的知识点
    React--路由详解
    女孩起名字:诗经中惊艳的女孩名字
    信号弹图像立体匹配算法研究
    Python学习基础笔记十三——函数
    Vue 路由 ElementUI组件库
    你们团队是否有RocketMQ创建Topic、GID创建规范呢
    【webrtc】 对视频质量的码率控制的测试与探索
    笔记:QtConcurrent :: run 两个线程中的信号与槽
  • 原文地址:https://blog.csdn.net/web220507/article/details/125389561