Vue3语法糖setup(二)

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第8天,点击查看活动详情

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

computed

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

写一个经典案例

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

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
  }
}
复制代码

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

get函数.gif 我们可以看到,当我们打开网页时,会先执行一次get函数,然后修改fristName时会再执行一次get函数

Watch函数

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

watchEffect

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

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

setup() {
  const name = ref("scc")
  const age = ref(18)
  const update = ()=>{
    age.value++

  }
  watchEffect(()=>{
    console.log(age.value);
  })
  return {
    name,
    age,
    update
  }
}
复制代码

定义一个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
      }
复制代码

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

getDom.gif 此时我们是可以获取到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
  }
}
复制代码

我们给watchEffect添加一个对象

postWatchEffect.gif 此时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,
  }
}
复制代码

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

watchEffectAge.gif 我们可以看到,当大于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
  }
}
复制代码

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

watchINfo.gif 确实可以监听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
  }
}
复制代码

我们对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
  }
}
复制代码

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

ewfWatch.gif

可以正常监听,显示内容

监听多个数据

如果需要监听多个数据,可以传入一个数组
复制代码

watch第三个参数,配置项

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

结束

到此结束,明天接着更新
复制代码

猜你喜欢

转载自juejin.im/post/7087442636142804999