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

1. 前言

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

2. 浅层次响应

2.1 shallowReactive

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

javascript 复制代码
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 会在开发环境中发出警告,但不会抛出错误。

javascript 复制代码
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,也只会局限于第一层属性,而不会递归处理、

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

javascript 复制代码
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的对象都是返回原始数据

javascript 复制代码
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 不会为其创建代理,也不会进行响应式追踪。

javascript 复制代码
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去设置数据

声明

javascript 复制代码
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的方式

javascript 复制代码
value.value= 10;

例子:

javascript 复制代码
<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定义全局参数,这样更加的方便快捷

父组件提供数据

javascript 复制代码
import {provide} from 'vue'
export default{
    setup(){
        provide('myValue',''HelloWorld);
    }
}

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

子组件接受数据

inject后直接接受参数名即可

javascript 复制代码
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组件控制标签位置到指定目标容器

格式:

javascript 复制代码
<teleport to="body">
</teleport>

to指向目标容器

示例:模拟弹窗

javascript 复制代码
<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 代码和组件。

javascript 复制代码
import { defineAsyncComponent } from 'vue';

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

在defineAsyncComponent方法中传入一个函数

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

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

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

8.2 suspense结构

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

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

javascript 复制代码
<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>
相关推荐
cnsxjean16 分钟前
SpringBoot集成Minio实现上传凭证、分片上传、秒传和断点续传
java·前端·spring boot·分布式·后端·中间件·架构
ZL_56734 分钟前
uniapp中使用uni-forms实现表单管理,验证表单
前端·javascript·uni-app
沉浮yu大海1 小时前
Vue.js 组件开发:构建可重用且高效的 UI 块
前端·vue.js·ui
代码欢乐豆1 小时前
软件工程第13章小测
服务器·前端·数据库·软件工程
sunly_1 小时前
Flutter:启动屏逻辑处理02:启动页
android·javascript·flutter
EasyNTS1 小时前
H5流媒体播放器EasyPlayer.js网页直播/点播播放器如果H.265视频在播放器上播放不流畅,可以考虑的解决方案
javascript·音视频·h.265
莘薪2 小时前
JQuery -- 第九课
前端·javascript·jquery
好青崧2 小时前
CSS 样式入门:属性全知晓
前端·css·tensorflow
在路上`2 小时前
vue实现列表滑动下拉加载数据
javascript·vue.js·ecmascript
光头程序员2 小时前
工程化开发谷歌插件到底有爽
前端·react·工程化·前端工程化·谷歌插件