Vue3语法糖setup(二)

在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函数,这两个是有区别的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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一个函数,调用会停止监听
可以传入一个函数,第一次执行时自动收集获取依赖 

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

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的值

我们可以看一下运行结果

可以看到,在刷新浏览器时,程序自动运行了一次,而且我们是可以监听到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属性,看一下浏览器输出

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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
  }
} 

我们给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,
  }
} 

我们监听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
  }
} 

定义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
  }
} 

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

可以看到,是没问题的

监听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

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

可以正常监听,显示内容

监听多个数据

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

watch第三个参数,配置项

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

结束

到此结束,明天接着更新 

你可能感兴趣的:(javascript,前端,vue.js)