Advertisement

组合式(Composition)API

阅读量:

1、选项式API与组合式API

在vue中我们有两种API,一种是选项式,一种是组合式,其中选项式主要用于vue2,组合式主要用于vue3。

选项式API(Option API)

在vue2中我们书写选项式API,每个选项都有固定的书写位置,使用data选项来书写响应式数据,methods中书写方法。

优点: 写代码的位置已经约定好,结构清晰

缺点: 代码组织性差,相似的逻辑代码不便于复用 ,逻辑复杂代码多了不好阅读,同一功能的上下文代码难找。

复制代码
        1. export default{

    
        2.     data(){
    
        3.         return{
    
        4.             list:[]
    
        5.         }
    
        6.     },
    
        7.     methods:{
    
        8.     //书写方法函数,在需要读取data中定义的数据时,需要使用this. 来获取,所以里面不能使用箭头函数
    
        9.        
    
        10.  },
    
        11.    
    
        12.     }

组合式API(composition)

所有与特定功能相关地代码可以写到一块,代码比较集中,在定义响应式数据时不在需要data,方法函数也不再写在metgods中

复制代码
 <script setup>

    
 import { computed,watch,ref ,reactive} from "vue";
    
 //定义响应式数据
    
 const num = ref('');
    
 const list = reactive([]);
    
 //定义方法
    
 const getNum=()=>{
    
     
    
 }
    
  
    
 </script>

2、生命周期函数

选项式API 组合式APT
beforeCreate 没有beforeCreate,在setup中做了beforeCreate、created中应该做的事
created
beforeMount onBeforeMount挂载DOM前
mounted onMounted挂载DOM后
beforeUpdate onBeforeUpdate更新组件前
updated onUpdated更新组件后
beforeDestroyed onBeforeUnmount 卸载销毁前
destroyed onUnmount销毁之后

最常用的两个钩子函数是**onMounted、onUpdated。在onMounted我们一般需要将页面需要的数据拿到,在页面渲染时,渲染到页面上。setup只会执行一次,在页面加载之前执行。**

3、响应式数据的定义

1、reactive

我们可以使用reactive()来创建一个数组或者对象

复制代码
 import { reactive } from 'vue'

    
 const todolist = reactive([])

在template中直接使用,在方法或者回调函数中使用todolist

reactive() 的局限性

仅对对象类型有效(对象、数组和 MapSet 这样的集合类型),而对 stringnumberboolean 这样的 原始类型 无效。

因为 Vue 的响应式系统是通过属性访问进行追踪的,因此我们必须始终保持对该响应式对象的相同引用。这意味着我们不可以随意地“替换”一个响应式对象,因为这将导致对初始引用的响应性连接丢失。

同时这也意味着当我们将响应式对象的属性赋值或解构至本地变量时,或是将该属性传入一个函数时,我们会失去响应性

2、ref()

ref()声明的值,在模板中可以直接使用,ref()将传入参数的值包裹在一个带有.value属性的ref对象中,所以在调用ref声明的值时,需要调用它的,value,才可以拿到对应的值。一个包含对象类型值的 ref 可以响应式地替换整个对象。

ref 被传递给函数或是从一般对象上被解构时,不会丢失响应性

复制代码
        1. //使用ref定义响应式数据

    
        2. const sum = ref(0);
    
        3. const todoval = ref('');
    
        4. const arr = ref([1,3,5]);
    
        5. ​
    
        6. //在模板中直接使用
    
        7. <template>
    
        8. <p>{{ count }}</p>
    
        9. <ul>
    
        10.     <li v-for="(item,index) in arr" :key="index"></li>
    
        11. </ul>
    
        12. </template>
    
        13. ​
    
        14. //在方法中使用需要使用.value才可以拿到对应的值
    
        15. const addTodo =()=>{
    
        16.     emit('add',todoVal.value)
    
        17.          todoVal.value=''
    
        18. };
    
        19. ​

3、toref()

转换响应式对象中某个属性为单独响应式数据 ,并且值是关联的。是基于响应式对象上的一个属性,创建一个对应的ref,这样创建的ref与原属性保持同步,改变原属性的值,将改变ref的值。

复制代码
        1. const state = reactive({

    
        2.   a: 1,
    
        3.   b: 2
    
        4. })
    
        5. const fooRef = toRef(state, 'a')
    
        6. // 更改该 ref 会更新源属性
    
        7. aRef.value++
    
        8. console.log(state.a) // 2
    
        9. // 更改源属性也会更新该 ref
    
        10. state.a++
    
        11. console.log(aRef.value) // 3
    
        12. ​
    
        13. 请注意,这不同于:
    
        14. const aRef = ref(state.a)//1 不会改变ref的值,因为他接受到的是一个纯数值

4、torefs()

将一个响应式对象转换成一个普通的对象,这个普通对象的每个属性都是指向原对象相应属性的ref,每个单独的ref都是根据toref()创建的。

toRefs 在调用时只会为源对象上可以枚举的属性创建 ref。如果要为可能还不存在的属性创建 ref,需要调用toref

复制代码
        1. const state = reactive({

    
        2.   foo: 1,
    
        3.   bar: 2
    
        4. })
    
        5. ​
    
        6. const stateAsRefs = toRefs(state)
    
        7. // 这个 ref 和源属性已经“链接上了”
    
        8. state.foo++
    
        9. console.log(stateAsRefs.foo.value) // 2
    
        10. ​
    
        11. stateAsRefs.foo.value++
    
        12. console.log(state.foo) // 3

4、copmuted()

  • computed函数,是用来定义计算属性的,计算属性不能修改。

computed函数接受一个getter函数,返回一个只读的ref对象,该对象是一个响应式的,该对象通过.value暴露getter的返回值,它也可以创建一个带有get set的响应式ref对象。

创建一个只读的计算属性ref

复制代码
 const sum = ref(0);

    
  
    
 const sumadd = computed(()=>{
    
  console.log('sum',sum.value)
    
 });

创建一个可写的计算属性 ref,通过get set 创建一个响应式对象

复制代码
 const count = ref(1)

    
  
    
 const changecount = computed(()=>{
    
 get:()=>count.value++;
    
 set:(sum)=>{
    
 count.value=sum+1
    
 }
    
 })

5、watch事件监听函数

watch() 侦听一个或多个响应式数据源,并在数据源变化时调用所给的回调函数,watch() 默认是懒侦听的,即仅在侦听源发生变化时才执行回调函数。
第一个参数是侦听器的源。这个来源可以是以下几种:

  • 一个函数,返回一个值
  • 一个 ref
  • 一个响应式对象
  • ...或是由以上类型的值组成的数组

第二个参数是在发生变化时要调用的回调函数。

  • watch函数,是用来定义侦听器的
  • 监听ref定义的响应式数据
  • 监听多个响应式数据数据
  • 监听reactive定义的响应式数据
  • 某一个属性深度监听
  • 默认执行

当直接侦听一个响应式对象时,侦听器会自动启用深层模式

监听ref定义的响应式数据

复制代码
 import {ref,reactive,watch} from 'vue';

    
 const num =ref(0)
    
 const changeNum = ()=>{
    
     num.value +=1
    
 }
    
 watch(num,()=>{
    
     console.log('num改变了',num.value)
    
  
    
 })

监听reactive定义的响应式数组

复制代码
 const list =reactive([{name:'张三',id:1},{name:'李四',id:2}])

    
  
    
 const changeList = ()=>{
    
     list.push({name:'李华',id:2})
    
 }
    
  
    
 watch(list,()=>{
    
     console.log('list改变了',list)
    
 })

监听reactive定义的响应式对象,在读取以及修改数据时,要使用对姓名.键值 的方式

复制代码
 <h1>{{ person.name }}</h1>

    
 <button @click="getName">点我</button>
    
  
    
  
    
 const person = reactive({name:'xiaoming'})
    
 const getName=()=>{
    
     person.name='tom'
    
 }
    
 watch(person,()=>{
    
     console.log('person改变了',person)
    
 })

watchEffect()

watch选项来侦听data或者props的数据变化,当数据变化时执行某一些操作,watchEffect() 立即运行一个函数,同时响应式地追踪其依赖,并在依赖更改时重新执行。

复制代码
 const name = ref("jeck");

    
       const age = ref(18);
    
  
    
       const changeName = () => name.value = "bob"
    
       const changeAge = () => age.value++
    
  
    
       watchEffect(() => {
    
     console.log("name:", name.value, "age:", age.value);
    
       });

停止监听 stop()

复制代码
 const name = ref("jeck");

    
       const age = ref(18);
    
       const stop = watchEffect(() => {
    
     console.log("name:", name.value, "age:", age.value);
    
       });
    
       const changeName = () => name.value = "bob"
    
       const changeAge = () => {
    
     age.value++;
    
    
    
     if(age.value>23){
    
         stop()
    
     }
    
     }

取消 watchEffect()函数的副作用

复制代码
 watchEffect(async (onCleanup) => {

    
   const { response, cancel } = doAsyncWork(id.value)
    
   // `cancel` 会在 `id` 更改时调用
    
   // 以便取消之前
    
   // 未完成的请求
    
   onCleanup(cancel)
    
   data.value = await response
    
 })

全部评论 (0)

还没有任何评论哟~