当前位置: 首页 > article >正文

Vue.js --- Vue3中其他组合式API

1. 前言

组合式API可以让我们更加优雅的组织我们的代码,函数。让相关功能的代码更加有序的组织在一起。组合式 API 提供了更灵活的方式来组织和复用代码。在选项式 API 中,组件的逻辑是按照生命周期钩子、计算属性、方法等进行组织的,这在某些情况下可能会导致功能之间的耦合。而组合式 API 允许将相关的功能组织到一个或多个“组合函数”(composables)中,并在不同组件中复用。

2. 浅层次响应

2.1 shallowReactive

与reactive不同的是,shallowReactive只会对对象的第一层属性进行响应式处理,而不会递归地处理深层的嵌套属性。也就是说,只有顶层属性会被代理,深层次的对象则不会被代理

import { shallowReactive } from 'vue';

const state = shallowReactive({
  a: 1,
  b: { x: 10, y: 20 }
});

state.a = 2;  // 响应式,修改会触发视图更新
state.b.x = 30;  // 非响应式,修改不会触发视图更新

2.2 readonly

用于创建一个只读的响应式对象,通过 readonly 创建的对象,所有属性都变成了只读的,即不能对该对象进行修改。如果尝试修改它的属性,Vue 会在开发环境中发出警告,但不会抛出错误。

import { readonly } from 'vue';

const state = readonly({
  a: 1,
  b: { x: 10, y: 20 }
});

state.a = 2;  // 会发出警告,不能修改属性
state.b.x = 30;  // 会发出警告,不能修改嵌套属性

2.3 shallowReadonly

与readonly类似,但可以看出多了一个shallow,也只会局限于第一层属性,而不会递归处理、

更深层属性仍可以被修改,只有顶层属性是只读的

import { shallowReadonly } from 'vue';

const state = shallowReadonly({
  a: 1,
  b: { x: 10, y: 20 }
});

state.a = 2;  // 会发出警告,不能修改顶层属性
state.b.x = 30;  // 不会发出警告,可以修改嵌套属性

3. 数据代理

3.1 toRaw

用来获取响应式对象的原始非响应式版本,当你在 Vue 中创建一个响应式对象时,Vue 会为该对象添加代理,进行数据的响应式追踪。而有时你可能需要访问该对象的原始数据,toRaw 就是用来实现这个功能的。

简单来讲就是储存原始的响应式对象的数据,随便我怎么改变响应式数据,toRaw的对象都是返回原始数据

import { reactive, toRaw } from 'vue';

const state = reactive({
  a: 1,
  b: { x: 10, y: 20 }
});

const rawState = toRaw(state);

state.a = 2;  // 修改响应式对象
console.log(rawState.a);  // 输出 1,原始数据不受影响

3.2 markRaw

用来标记某个对象不需要被 Vue 代理。当你想让某个对象避免成为响应式对象时,可以使用 markRaw。该对象会被 Vue 视为普通的非响应式对象,Vue 不会为其创建代理,也不会进行响应式追踪。

import { markRaw } from 'vue';

const rawObject = markRaw({
  a: 1,
  b: { x: 10, y: 20 }
});

console.log(rawObject);  // 不会被 Vue 代理,保持原始状态

4. 自定义响应 customRef

4.1 声明

customRef是一个允许开发者自定义响应式引用的 API。它使你能够控制响应式对象的 getter 和 setter 行为,提供了更灵活的方式来处理响应式数据。与 Vue 内置的 ref 不同,customRef 允许你定义如何在响应式更新过程中处理数据。

通过设置getter去获取数据,setter去设置数据

声明

import { customRef } from 'vue';

export default {
  setup() {
    const value = customRef((track, trigger) => {
      let internalValue = 0;

      return {
        get() {
          track();  // 触发依赖追踪
          return internalValue;
        },
        set(newValue) {
          if (Math.abs(newValue - internalValue) > 5) {  // 设置条件
            internalValue = newValue;
            trigger();  // 触发视图更新
          }
        }
      };
    });

    return {
      value
    };
  }
};

track与trigger是由Vue传入的内部函数,该函数返回一个包含get,set的对象。

track用于追踪依赖,可以理解为找到目标数据

trigger用于在数据更新时触发视图更新

4.2 调用

想要调用或者修改customRef对象中的数值,需要使用后缀.value的方式

value.value= 10;

例子:

<template>
  <h1>{{value}}</h1>
  <button @click="changeValue">点我改变数值</button>
</template>

<style>

</style>

<script>
  import {customRef} from 'vue'
  export default {
    setup() {
      let sum = 0;

      const value = customRef((track,trigger) => {
        let interValue = 0;
        return {
          get() {
            track();
            return interValue;
          },
          set(newValue) {
            if (newValue > interValue) {
              interValue = newValue;
              trigger();
            }
          }
        }
      })

      function changeValue() {
        value.value = 50;
      }

      return {sum,value,changeValue}
    }
  }
</script>

5. 数据传递 provide与inject

provide:在父组件中使用,目的是将数据提供给后代组件。它将某些数据提供到组件树中,所有嵌套的子组件(不论是直接子组件还是间接子组件)都可以通过 inject 来访问这些数据。

inject:在子组件中使用,用来接收父组件通过 provide 提供的数据。inject 使得子组件可以访问到父组件提供的特定数据,而不需要通过逐层的 props 传递。

相比以往的props传参,vuex定义全局参数,这样更加的方便快捷

父组件提供数据

import {provide} from 'vue'
export default{
    setup(){
        provide('myValue',''HelloWorld);
    }
}

结构体为(参数名,参数内容) 

子组件接受数据

inject后直接接受参数名即可

import {inject} from 'vue'

export default()
{
    setup(){
        const injectedValue = inject('myValue')
        return {injectedValue}
    }
}

6. 响应式数据的判断

isRef()判断是否为响应数据
isReactive()判断是否为响应对象
isReadonly()判断是否为只读属性
isProxy()判断是否为响应式系统,包括ref,reactive

7. 渲染DOM组件 - Teleport组件

Teleport是一个非常实用的组件,允许将子组件的内容渲染到DOM中不同的位置,而不依赖于父组件的嵌套结构。对于管理模态框,弹出层,工具提示,通知等UI元素非常有用,特别是当这些元素需要在DOM的不同位置进行渲染时,避免了许多的嵌套和复杂的样式问题

例如,消息通知栏常常需要放置在顶部,但又受到某一子组件的控制,通过Teleport组件控制标签位置到指定目标容器

格式:

<teleport to="body">
</teleport>

to指向目标容器

示例:模拟弹窗

<template>
  <div>
    <h1>Vue3 Teleport 示例</h1>
    <button @click="closeModel">点我</button>
    <teleport to="body">
      <div class="model" v-if="controller">
        <p>这是一个模板!</p>
        <button @click="closeModel">关闭</button>
      </div>
    </teleport>
  </div>
</template>

<style>
  .model{
    position:fixed;
    top:50%;
    left:50%;
    background-color:yellow;
    border-radius:8px;
  }
</style>

<script>
  export default {
    data() {
      return {
        controller:false
      }
    },
    methods: {
      closeModel() {
        this.controller = !this.controller
      }
    }
  }
</script>

8. 异步组件

8.1 异步加载组件

让我们先来了解异步加载组件

它允许我们根据需要加载和渲染组件,而不是在应用加载时一次性加载所有组件。这样可以显著提高应用的性能,尤其是在大型应用中,避免一次性加载所有的 JavaScript 代码和组件。

import { defineAsyncComponent } from 'vue';

export default {
  components: {
    AsyncComponent: defineAsyncComponent(() =>
      import('./AsyncComponent.vue') // 异步加载组件
    )
  }
}

在defineAsyncComponent方法中传入一个函数 

suspense组件用于处理异步组件的加载和显示一个加载状态。它为开发者提供了一种优雅的方式来处理异步数据加载的状态,特别是在处理组件加载、API 请求或其他需要等待的操作时,Suspense 让应用能够在等待数据或资源时优雅地过渡。

在vue中还提供了异步组件的加载状态,加载失败和超时处理的功能

const AsyncComponent = () => ({
  // 需要加载的组件 (should be a promise)
  component: import('./components/AsyncComponent.vue'),
  
  // 加载中时的组件
  loading: LoadingComponent,
  
  // 加载失败时的组件
  error: ErrorComponent,
  
  // 超过时间后显示的组件
  timeout: 3000
});

8.2 suspense结构

default插槽:用于放置异步组件,vue会等待其最终的加载完成

fallback插槽:当异步组件正在加载时,会显示fallback插槽中的内容,通常是文字或者加载动画

<template>
  <Suspense>
    <!-- 异步组件 -->
    <template #default>
      <AsyncComponent />
    </template>

    <!-- 加载时显示的内容 -->
    <template #fallback>
      <p>加载中...</p>
    </template>
  </Suspense>
</template>

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

export default {
  components: {
    AsyncComponent: defineAsyncComponent(() =>
      import('./AsyncComponent.vue') // 异步加载组件
    )
  }
}
</script>


http://www.kler.cn/a/409710.html

相关文章:

  • JavaScript中的this指向绑定规则(超全)
  • ES6 、ESNext 规范、编译工具babel
  • 【时时三省】NIT计算机考试基础知识
  • VSCode 汉化教程【简洁易懂】
  • NVR管理平台EasyNVR多个NVR同时管理:全方位安防监控视频融合云平台方案
  • manin动画编程(安装+入门)
  • 语言模型中的多模态链式推理
  • 【Linux】线程ID与互斥、同步(锁、条件变量)
  • 第4章 三个域对象
  • 深度解析:Vue 自定义指令到底是什么?快来了解
  • 鸿蒙面试题-某迈-2024年11月22日
  • 对于某些原型或UI软件的个人看法(2024/11)
  • 【Qt】控件LineEdit
  • MySql:库和表的操作
  • 在Kubernetes使用CronJob实现定时删除指定天数外的文件(我这里使用删除备份mysql数据库文件为例)
  • WPF——ICON按钮制作
  • Apache Spark
  • 【C++11】可变参数模板/新的类功能/lambda/包装器--C++
  • 【网络通信】数据集合集!
  • 函数模板(进阶)
  • PPO算法实践(基于cleanrl)
  • Kubernetes(k8s)入门到实战教程
  • 如何部署开源大模型
  • 【时间之外】IT人求职和创业应知【44】-机械手游戏+
  • JavaScript 中通过Array.sort() 实现多字段排序、排序稳定性、随机排序洗牌算法、优化排序性能,JS中排序算法的使用详解(附实际应用代码)
  • C# 需要安装额外的开发环境吗