Vue3组合式API

144 阅读4分钟

vue3组合式

1-响应式基础

1-1 reactive

作用:创建响应式对象,非包装对象,可以认为是模板中的状态。它适用于对象或数组。

import { reactive } from 'vue';

const state = reactive({
  count: 0
});
console.log(state.count); // 0

1-2 ref

作用:作用:创建一个包装式对象,含有一个响应式属性value。 它和reactive的差别,就是前者没有包装属性value。它适用于number,string,boolean,数组,对象等。

import { ref } from 'vue';

const count = ref(0);
console.log(count.value); // 0

1-3 两者的区别

  1. 返回值类型

    • reactive 创建一个响应式对象,将整个对象变成响应式。它适用于对象或数组。

    • ref 创建一个包装对象,对象中有一个名为 value 的属性。ref 主要用于包装基本类型,使其具备响应性。

  2. 访问方式

    • reactive 创建一个响应式对象,将整个对象变成响应式。
    • ref 使用 .value 来访问和修改数据。
  3. 适用场景

    • reactive 适用于对象和复杂的数据结构。当你有一个需要响应性的对象时,或者需要在对象中定义多个属性时,可以使用 reactive
    • ref 适用于简单的基本数据类型,如数字、字符串等。如果你有一个简单的状态需要响应性,可以使用 ref
  4. 原理

    • reactive reactive 使用 Proxy 来实现对象的响应式。
    • ref ref 的内部实现是通过 Object.defineProperty,在 value 属性上设置 getter 和 setter 来实现的。

1-4 ref嵌套在reactive中

  • (ref转换reactive响应式对象)
import { ref,reactive } from 'vue';
const count = ref(0)
const state = reactive({
    count
})

1-5 toRefs

  • (reactive响应式对象转换成ref对象)
import { reactive, toRefs } from 'vue';

const originalObject = reactive({
  name: 'John',
  age: 25
});

const { name, age } = toRefs(originalObject);

console.log(name.value); // 'John'
console.log(age.value); // 25

1-6 通过ref访问到dom或组件

<template>
    <div>
        <div ref="msg">app</div>
        <button @click="handleClick">click</button>
    </div>
</template>

<script>
import { ref } from 'vue';

    export default {
        setup(){
            const msg = ref()
            const handleClick =()=>{
                console.log(msg.value); //<div>app</div>
            }
            return {
                msg,
                handleClick
            }
        }
    }

</script>

2-计算属性

计算属性是一种特殊的属性,其值是通过对其他属性进行计算得到的,并且具有缓存机制,只有在依赖的响应式数据发生变化时,计算属性的值才会重新计算。

<template>
  <div>
    <p>{{ message }}</p>
    <p>{{ reversedMessage.value }}</p>
  </div>
</template>

<script>
import { ref, computed } from 'vue';

export default {
  setup() {
    const message = ref('Hello, Vue!');

    // 使用 computed 函数创建计算属性
    const reversedMessage = computed(() => {
      return message.value.split('').reverse().join('');
    });

    return {
      message,
      reversedMessage
    };
  }
};
</script>

3-watch和watchEffect

3-1 watch

watch 是一个用于监听数据变化并执行相应操作的选项。你可以在组件的选项中使用 watch 来观察一个数据,当该数据变化时,执行一些操作,比如异步请求、更新其他数据等。

  1. watch 的第一个参数可以是不同形式的“数据源”:它可以是一个 ref (包括计算属性)、一个响应式对象、一个 getter 函数、或多个数据源组成的数组
  2. 第二个参数可以执行监听时候的回调
<template>
    <div>
        app-watch函数
        <input type="text" v-model="mytext">
        <input type="text" v-model="myage">
        <input type="text" v-model="obj.mytext">
    </div>
</template>

<script>
import { reactive, ref, watch } from 'vue';

    export default {
        setup(){
            const mytext = ref("")
            const myage = ref("")
            const obj = reactive({
                mytext:""
            })
            
            //ref对象
            //方式一 ref  单个ref 
            // watch(mytext,(newvalue,oldvalue)=>{
            //     console.log("异步",newvalue);
            // })

            //方式二 函数形式 
            // watch(()=>mytext.value,(newvalue,oldvalue)=>{
            //     console.log("异步",newvalue);
            // })

            //方式三 多个ref 用数组
            // watch([myage,mytext],(newvalue,oldvalue)=>{
            //     console.log("异步",newvalue);
            // })

            //reactive对象
            //方式一 reactive 响应式对象的一个属性
            // watch(()=>obj.mytext,(newvalue,oldvalue)=>{
            //     console.log("异步",newvalue);
            // })

            //方式二 reactive  响应式对象
            watch(obj,(newvalue,oldvalue)=>{
                console.log("异步",newvalue);
            })

            return {
                mytext,
                myage,
                obj
            }
        }
    }
</script>

3-2 watchEffect

watchEffect 是一个用于监视响应式数据并执行副作用函数的函数。与 watch 不同,watchEffect 不需要显式地指定要监视的数据,而是自动追踪函数体内使用到的响应式数据,并在这些数据发生变化时执行函数。

<template>
    <div>
        app-watch函数
        <input type="text" v-model="mytext">
        <input type="text" v-model="myage">
        <input type="text" v-model="obj.mytext">
    </div>
</template>

<script>
import { reactive, ref, watch, watchEffect } from 'vue';

    export default {
        setup(){
            const mytext = ref("")
            const myage = ref("")
            const obj = reactive({
                mytext:""
            })
            //第一次执行
            //不需要主动监听
            watchEffect(()=>{
                console.log("基于mytext和myage的条件改变,发ajax",mytext.value,myage.value);
            })
            
            return {
                mytext,
                myage,
                obj
            }
        }
    }
</script>

4-props和事件

props 父组件给子组件传递数据

emit() 通过调用emit方法自定义事件给父组件传递数据

setup()中第一个参数是props,第二个参数是一个上下文对象,它包含了当前组件实例的一些属性和方法。

props:["mytite"], //正常接收
setup (props, { emit }) {
    console.log(props.mytitle)
    const handleClick = () => {
      emit('event')
    }

    return {
      handleClick
    }
  }

5-provide和inject

provide 提供数据 inject 注入数据 两者结合实现跨组件通信

import { provide } from 'vue'

export default {
  setup() {
    provide(/* 注入名 */ 'message', /* 值 */ 'hello!')
  }
}
import { inject } from 'vue' 
export default { 
    setup() { 
        const message = inject('message') 
        return { message } 
    } 
}