vue学习16之compositionAPI2

reactive判断的API

  • isProxy:检查对象是否由reactive或readonly创建的proxy
  • isReactive: 判断是否由reactive创建的响应式原理
  • isReadonly
  • toRaw:返回reactive代理的原始对象
  • shallowReactive:创建一个响应式代理,跟踪自身property的响应性,但不执行嵌套对象的深层响应式转换

shallowReadonly:创建一个proxy,使其自身的property为只读,但不执行嵌套对象的深度只读转换 从vue中导入 import .. from 'vue'

toRef和toRefs的使用

如果想要结构出来reactive处理的对象,这些属性结构出来不具有响应式.可以使用toRefs,可以将reactive对象属性都转成ref

javascript 复制代码
  export default {
    setup() {
      const info = reactive({name: 'juju', age: 18});
      let { name, age } = info;
      const btnClick = () => {
        // info.age++
        age++
        console.log(age)
      }
      return {
        info,
        btnClick
      }
    }
  }

这时就可以使用toRef,这样使得结构出来的属性具有响应式,且修改其中属性,reactive代理对象的属性也会改变

javascript 复制代码
<template>
  <div>
    <button @click="btnClick">年龄增加</button>
    {{ name }} - {{ age }}
  </div>
</template>
  import { reactive, toRefs } from 'vue';
  export default {
    setup() {
      const info = reactive({name: 'juju', age: 18});
      let { name, age } = toRefs(info);
      console.log(age)
      const btnClick = () => {
        // info.age++
        age.value++
        console.log(age.value) //此时age是一个ref对象,因此要使用age.value++
      }
      return {
        name,
        age,
        btnClick
      }
    }
  }

toRef对其中一个属性转成ref

ini 复制代码
let age = toRef(info, "age");

ref其他API

  • unref,获取ref中的value
  • isRef:判断是否是一个ref对象
  • shallowRef:创建一个浅层的ref对象
  • triggerRef:手动触发和shollowRef相关联的副作用
ini 复制代码
const info = shallowRef({name: 'juju'})
//只有info.value = {name: 'kobe'}时才是响应式,info.value.name不会改变

computed

xml 复制代码
<template>
  <div>
    {{ fullName }}
    <button @click="btnClick">改变名字</button>
  </div>
</template>

<script>
  import { ref, computed } from 'vue'
  export default {
    setup() {
      const firstName = ref("kobe");
      const lastName = ref("Bryant");
      // 用法一传入一个getter函数
      const fullName = computed(() => firstName.value + " " + lastName.value);
        // 用法二传入一个对象,包括getter和setter.computed返回值是一个ref对象
      const fullName = computed({
        get: () => firstName.value + " " + lastName.value,
        set(newVal) {
          const names = newVal.split(" ");
          firstName.value = names[0];
          lastName.value = names[1];
        }
      })
      const btnClick = () => {
        lastName.value = "james"
        
        //用法二
        fullName.value = "juju L"
      }
      return {
        firstName,
        lastName,
        fullName,
        btnClick
      }
    }
  }
</script>

侦听数据的变化watch

在前面的OPtionAPI中,我们可以通过watch选项来侦听data或者props数据变化。在compositionAPI,我们可以使用watchEffect和watch来完成响应式数据的侦听。

  • watchEffect用于自动收集响应式数据的依赖,默认会执行一次
  • watch需要手动指定侦听的数据源。
ini 复制代码
      const name = ref("juju");
      const age = ref(18);
      const changeName = () => {
        name.value = "harden"
      }
      const changeAge = () => {
        age.value++;
      }

      // 默认执行一次,看看用到哪些ref对象,用到的自动进行监听
      watchEffect(() => {
        console.log("name:",name.value)
      })

watchEffect停止侦听

watchEffect返回一个函数,执行这个函数,停止侦听

scss 复制代码
      const stop = watchEffect(() => {
        console.log("name:",name.value,"age:",age.value)
      })
      const changeAge = () => {
        age.value++;
        if(age.value > 25) {
          stop();
        }
      }

watchEffect清除副作用

当我们给watchEffect传入的函数被回调时,可以获取一个参数: onInvalidata,当副作用即将重新执行或者侦听器被停止时会执行该函数传入的回调函数

javascript 复制代码
      const stop = watchEffect((onInvalidate) => {
        onInvalidate(()=> {
          // 在这个函数中清楚额外的副作用
          // request.cancel
        })
        console.log("name:",name.value,"age:",age.value)
      })

在setup中获取到元素ref

javascript 复制代码
<template>
  <div>
    <h2 ref="title">哈哈哈哈哈哈</h2>
  </div>
</template>
const title = ref(null);
      return {
        title
      }

此时可以在挂载完成之后获得ref为title的值

watchEffect执行时机

默认情况下,watchEffect会立即执行。如果想要在某种情况发生之后执行,需要传入第二个参数

javascript 复制代码
      const stop = watchEffect((onInvalidate) => {
        onInvalidate(()=> {
          // 在这个函数中清楚额外的副作用
          // request.cancel
        })
        console.log(title.value)
      },{
        flush: "post"   //挂载完成之后执行,pre是立即执行
      })

watch侦听器的参数类型

watch侦听特定的数据源,只有当侦听的源发生变化才会执行回调 与watchEffect比较,watch运行我们

  • 第一次不会直接执行
  • 更具体说明哪些状态发生变化,触发侦听器
  • 访问侦听变化前后的值

watch侦听函数有两种类型: 一个getter函数,但是该getter函数必须引用可响应式对象(比如reactive或ref) 直接写入一个可响应式对象,ref(如果是一个reactive对象侦听,需要进行某种转换)

第一种用法,侦听watch传入getter函数

xml 复制代码
<template>
  <div>
    {{ info.name }}
    <button @click="btnClick">改变</button>
  </div>
</template>

<script>
  import { ref, reactive, computed, watchEffect,watch } from 'vue'
  export default {
    setup() {
      const info = reactive({name: 'juju', age: 18});
      watch(() => info.name, (newVal, oldVal) => {
        console.log("newVal:", newVal,"oldVal:", oldVal)
      })

      const btnClick = () => {
        info.name = 'harden'
      }
      return {
        info,
        btnClick
      }
    }
  }
</script>

<style scoped>

</style>

第二种用法,侦听watch传入reactive对象

javascript 复制代码
       const info = reactive({name: 'juju', age: 18});
      // 获取到的oldval和oldval都是reactive对象
      watch(info, (newVal, oldVal) => {
        console.log("newVal:", newVal,"oldVal:", oldVal)
      })

如果希望newval和oldval是普通对象,可以结构reactive对象

javascript 复制代码
      watch(() => {
        return {...info}
      }, (newVal, oldVal) => {
        console.log("newVal:", newVal,"oldVal:", oldVal)
      })

第三种,传入ref对象

javascript 复制代码
      const name = ref("why")
      watch(name, (newVal, oldVal) => {
        console.log("newVal:", newVal,"oldVal:", oldVal)
      })

      const btnClick = () => {
        name.value = 'harden'
      }

侦听多个数据源

javascript 复制代码
      watch([info,name], (newVal,oldVal) => {
        console.log("newVal:", newVal,"oldVal:", oldVal)
      })

获取新旧值可以进行结构

css 复制代码
      watch([info,name], ([newInfo, newName],[oldInfo,oldName]) => {
        console.log(newInfo, newName,oldInfo, oldName)
      })

深度监听

默认对reactive对象深度监听

javascript 复制代码
      watch(() => {
        return {...info}
      }, (newVal,oldVal) => {
        console.log(newVal, oldVal)
      },{
        deep: true,
        immediate: true
      })
相关推荐
●VON24 分钟前
使用 Electron 构建天气桌面小工具:调用公开 API 实现跨平台实时天气查询V1.0.0
前端·javascript·electron·openharmony
码上成长27 分钟前
包管理提速:pnpm + Workspace + Changesets 搭建版本体系
前端·前端框架
Bigger31 分钟前
Tauri(十九)——实现 macOS 划词监控的完整实践
前端·rust·app
ganshenml1 小时前
【Web】证书(SSL/TLS)与域名之间的关系:完整、通俗、可落地的讲解
前端·网络协议·ssl
这是个栗子2 小时前
npm报错 : 无法加载文件 npm.ps1,因为在此系统上禁止运行脚本
前端·npm·node.js
HIT_Weston3 小时前
44、【Ubuntu】【Gitlab】拉出内网 Web 服务:http.server 分析(一)
前端·ubuntu·gitlab
华仔啊3 小时前
Vue3 如何实现图片懒加载?其实一个 Intersection Observer 就搞定了
前端·vue.js
JamesGosling6664 小时前
深入理解内容安全策略(CSP):原理、作用与实践指南
前端·浏览器
不要想太多4 小时前
前端进阶系列之《浏览器渲染原理》
前端
g***96904 小时前
Node.js npm 安装过程中 EBUSY 错误的分析与解决方案
前端·npm·node.js