Vue3知识干货分享

在 Vue 3 中,setup 函数的写法有两种主要方式:一种是使用 <script setup> 标签,另一种是写在 export default 对象中作为 setup 函数。它们之间的区别如下:

<script setup> 标签

  • 位置 :使用 <script setup> 标签来编写 setup 函数。

  • 作用 :是 Vue 3 的 Composition API 的一种语法糖,简化了 setup 函数的使用。

  • 优点

    • 简化语法 : 省去了显式地定义 setup 函数,代码更简洁。
    • 更好支持 TypeScript: 更好的类型推断和更简洁的 TypeScript 支持。
    • 自动导入: 可以自动导入一些 Vue 内置的 API 和自定义的组件、函数等。
    vue 复制代码
    <template>
      <div>{{ message }}</div>
    </template>
    
    <script setup>
    import { ref } from 'vue';
    
    const message = ref('Hello Vue 3!');
    </script>
  • 注意 :此写法,definePropsdefineEmits是自动使用,无需显式导入

export default 对象中的 setup 函数

  • 位置 :在 export default 对象中定义 setup 函数。

  • 作用 :这种方式是 Vue 3 提供的标准方式,允许在对象中定义 setup 方法。

  • 优点

    • 与 Options API 兼容: 适用于需要结合使用 Composition API 和 Options API 的情况。
    • 传统方式: 适合于逐步迁移旧代码或与传统 Vue 2.x 的 Options API 结合使用。
    vue 复制代码
    <template>
      <div>{{ message }}</div>
    </template>
    
    <script>
    import { ref } from 'vue';
    
    export default {
      setup() {
        const message = ref('Hello Vue 3!');
        return { message };
      }
    }
    </script>
总结
  • <script setup>: 更简洁、易读,适合新开发的 Vue 3 组件和更复杂的逻辑组织。
  • export default 对象中的 setup: 更兼容旧有代码和 Options API,适合需要逐步迁移的项目。

声明变量

  • ref

    • 适用场景:主要用于定义单一的基本类型(如字符串、数字、布尔值)或对非响应式对象的包装。它也适用于创建响应式的引用类型数据(浅层响应式)。

    • 使用方法 :创建一个包含 .value 属性的响应式对象,你需要通过 .value 来访问和修改其值。

    • 示例

      vue 复制代码
      <template>
        <div>{{ count }}</div>
        <button @click="increment">Increment</button>
      </template>
      
      <script setup>
      import { ref } from 'vue';
      
      // 创建一个响应式的基本类型变量
      const count = ref(0);
      
      // 修改变量值
      function increment() {
        count.value++;
      }
      </script>
  • reactive:

    • 适用场景 :用于创建一个深度响应式的对象。它主要用于处理复杂的数据结构,如嵌套对象和数组。reactive 会对对象的所有嵌套属性进行响应式处理。

    • 使用方法 :使用 reactive 创建的对象本身就是响应式的,你可以直接访问和修改对象的属性,而不需要通过 .value

    • 示例

      vue 复制代码
      <template>
        <div>{{ user.name }}</div>
        <button @click="updateName">Change Name</button>
      </template>
      
      <script setup>
      import { reactive } from 'vue';
      
      // 创建一个响应式的对象
      const user = reactive({
        name: 'John Doe'
      });
      
      // 修改对象属性
      function updateName() {
        user.name = 'Jane Doe';
      }
      </script>

计算属性

  • 基本用法:用来进行数据的衍生计算。

    vue 复制代码
    <template>
      <div>
        <p>Count: {{ count }}</p>
        <p>Doubled Count: {{ doubledCount }}</p>
        <button @click="count++">Increment</button>
      </div>
    </template>
    
    <script>
    import { ref, computed } from 'vue';
    
    export default {
      setup() {
        const count = ref(0);
        
        // 定义计算属性
        const doubledCount = computed(() => count.value * 2);
        
        return {
          count,
          doubledCount
        };
      }
    };
    </script>
  • 特性:

    • 响应式:计算属性会自动依赖其内部使用的数据,并且在这些数据发生变化时会重新计算。Vue 会智能地缓存计算属性的值,直到它的依赖数据发生变化。

    • 只读:默认情况下,计算属性是只读的。如果你需要计算属性具有 setter(写入)功能,可以提供一个对象的形式来定义计算属性,如下所示:

      js 复制代码
      import { ref, computed } from 'vue';
      
      export default {
        setup() {
          const count = ref(0);
          
          // 定义具有 getter 和 setter 的计算属性
          const doubledCount = computed({
            get: () => count.value * 2,
            set: (newValue) => {
              count.value = newValue / 2;
            }
          });
          
          return {
            count,
            doubledCount
          };
        }
      };

生命周期钩子函数

onBeforeMount

  • 用途: 在组件挂载之前被调用。此钩子在模板编译完成但尚未挂载到 DOM 上时触发。

  • 函数签名:

    js 复制代码
    import { onBeforeMount } from 'vue';
    
    onBeforeMount(() => {
      console.log('Component is about to mount');
    });

onMounted

  • 用途: 在组件挂载到 DOM 后调用。用于访问 DOM 元素或执行需要在 DOM 渲染后才能完成的操作。

  • 函数签名

    js 复制代码
    import { onMounted } from 'vue';
    
    onMounted(() => {
      console.log('Component has been mounted');
    });

onBeforeUpdate

  • 用途: 在组件更新之前被调用。此钩子在组件的数据发生变化并将要重新渲染时触发。

  • 函数签名

    js 复制代码
    import { onBeforeUpdate } from 'vue';
    
    onBeforeUpdate(() => {
      console.log('Component is about to update');
    });

onUpdated

  • 用途: 在组件更新之后调用。用于处理更新后的逻辑或与新的 DOM 状态相关的操作。

  • 函数签名

    js 复制代码
    import { onUpdated } from 'vue';
    
    onUpdated(() => {
      console.log('Component has been updated');
    });

onBeforeUnmount

  • 用途: 在组件卸载之前被调用。用于清理资源或移除事件监听器等操作。

  • 函数签名

    js 复制代码
    import { onBeforeUnmount } from 'vue';
    
    onBeforeUnmount(() => {
      console.log('Component is about to unmount');
    });

onUnmounted

  • 用途: 在组件卸载后调用。用于执行卸载后需要完成的操作,如清理外部资源或停止定时器。

  • 函数签名

    js 复制代码
    import { onUnmounted } from 'vue';
    
    onUnmounted(() => {
      console.log('Component has been unmounted');
    });

onErrorCaptured

  • 用途: 当组件的子组件发生错误时调用。可以用于捕获错误并处理它们。

  • 函数签名

    js 复制代码
    import { onErrorCaptured } from 'vue';
    
    onErrorCaptured((error, instance, info) => {
      console.error('Error captured:', error);
      return false; // 如果返回 false,错误不会被进一步处理
    });

onActivated

  • 用途 : 当组件被激活时调用。主要用于 <keep-alive> 包裹的组件,组件从缓存中激活时触发。

  • 函数签名

    js 复制代码
    import { onActivated } from 'vue';
    
    onActivated(() => {
      console.log('Component has been activated');
    });

onDeactivated

  • 用途 : 当组件被停用时调用。主要用于 <keep-alive> 包裹的组件,组件被缓存时触发。

  • 函数签名

    js 复制代码
    import { onDeactivated } from 'vue';
    
    onDeactivated(() => {
      console.log('Component has been deactivated');
    });

响应式属性监听

  • watch

    • 作用 :一个用于监听数据变化并执行回调函数的 API。可以用于监视响应式数据的变化、执行副作用操作或处理复杂的逻辑。提供了更灵活的方式来处理数据变化,与计算属性 (computed) 的响应性相比,watch 更适合处理需要副作用的场景。

    • 基本用法

      • 允许你观察一个或多个响应式数据源,并在这些数据源发生变化时执行回调函数

        js 复制代码
        import { ref, watch } from 'vue';
        
        export default {
          setup() {
            const count = ref(0);
        
            // 监视 `count` 的变化
            watch(count, (newValue, oldValue) => {
              console.log(`Count changed from ${oldValue} to ${newValue}`);
            });
              
            const info = reactive({
                name: 'dfc'
            });
              
            // 监视 `name` 的变化
            watch(() => info.name, (newName, oldName) => {
                console.log(`info.name changed from ${oldName} to ${newName}`);
        	})
        
            return {
              count
            };
          }
        };
        js 复制代码
        import { ref, watch, toRefs } from 'vue';
        
        export default {
          setup() {
            const count = ref(0);
            const name = ref('Alice');
        
            // 监视多个数据源
            watch([count, name], ([newCount, newName], [oldCount, oldName]) => {
              console.log(`Count changed from ${oldCount} to ${newCount}`);
              console.log(`Name changed from ${oldName} to ${newName}`);
            });
              
            const info = reactive({
                name: 'dfc',
                age: 12,
            });
              
            // 监视多个数据源
            watch([() => info.name, () => info.age], ([newName, oldName], [newAge, oldAge]) => {
              console.log(`info.name changed from ${oldName} to ${newName}`);
              console.log(`info.age changed from ${oldAge} to ${newAge}`);
        	});
        
            return {
              count,
              name,
              info,
              // ...toRefs(info)
            };
          }
        };
    • 其他特性

      • 深度监视 :需要深度监视对象的嵌套属性,可以使用 deep 选项

        js 复制代码
        import { ref, watch } from 'vue';
        
        export default {
          setup() {
            const user = ref({ name: 'Alice', age: 30 });
        
            // 深度监视 `user` 对象
            watch(user, (newValue, oldValue) => {
              console.log('User object changed:', newValue);
            }, { deep: true });
        
            return {
              user
            };
          }
        };
      • 立即执行 :初始化时立即执行一次回调,可以使用 immediate 选项

        js 复制代码
        import { ref, watch } from 'vue';
        
        export default {
          setup() {
            const count = ref(0);
        
            // 立即执行回调
            watch(count, (newValue, oldValue) => {
              console.log(`Count changed from ${oldValue} to ${newValue}`);
            }, { immediate: true });
        
            return {
              count
            };
          }
        };
      • 停止监听 :需要在某些条件下停止监听,可以使用 watch 函数返回的停止函数

        js 复制代码
        import { ref, watch } from 'vue';
        
        export default {
          setup() {
            const count = ref(0);
        
            const stopWatch = watch(count, (newValue, oldValue) => {
              console.log(`Count changed from ${oldValue} to ${newValue}`);
            });
        
            // 停止监听
            setTimeout(() => {
              stopWatch();
              console.log('Stopped watching count');
            }, 5000);
        
            return {
              count
            };
          }
        };
  • watchEffect

    • 作用 :一个用于自动追踪响应式数据并执行副作用的 API。它与 watch 不同,因为 watchEffect 不需要明确地指定要观察的数据源,而是自动追踪函数内部使用的所有响应式数据。这使得 watchEffect 更加简洁和直观,特别是当你不需要对数据变化做复杂的处理时。

    • 基本用法

      js 复制代码
      import { ref, watchEffect } from 'vue';
      
      export default {
        setup() {
          const count = ref(0);
      
          // 使用 watchEffect 追踪 count 的变化
          watchEffect(() => {
            console.log(`Count is: ${count.value}`);
          });
      
          // 修改 count 的值
          setTimeout(() => {
            count.value = 1;
          }, 1000);
      
          return {
            count
          };
        }
      };
    • 处理副作用 : watchEffect 主要用于处理副作用,如更新 DOM、发送网络请求等。它在数据源变化时会重新执行回调函数,因此非常适合处理那些与数据变化有关的操作。

    • 停止追踪

      js 复制代码
      import { ref, watchEffect } from 'vue';
      
      export default {
        setup() {
          const count = ref(0);
      
          // 使用 watchEffect 追踪 count 的变化
          const stop = watchEffect(() => {
            console.log(`Count is: ${count.value}`);
          });
      
          // 停止追踪
          setTimeout(() => {
            stop();
            console.log('Stopped watching count');
          }, 5000);
      
          return {
            count
          };
        }
      };
    watch 的对比

    watchEffectwatch 都可以用来处理响应式数据的变化,但它们的使用场景和方式有所不同:

    • watchEffect: 自动追踪函数内所有响应式数据的变化,适合处理简单的副作用,不需要手动指定数据源。
    • watch: 需要明确指定要观察的数据源,适合处理更复杂的逻辑和副作用,允许对数据源变化进行更细粒度的控制。
    深度追踪
    js 复制代码
    import { ref, watch } from 'vue';
    
    export default {
      setup() {
        const user = ref({ name: 'Alice', age: 30 });
    
        // 使用 watch 进行深度追踪
        watch(user, (newValue, oldValue) => {
          console.log('User object changed:', newValue);
        }, { deep: true });
    
        return {
          user
        };
      }
    };

内置组件

Teleport
  • 作用:允许你将子组件的渲染内容"传送"到 DOM 中的不同位置

  • 示例

    vue 复制代码
    // teleport 将模态框渲染到 body 元素中,而不是其父组件的 DOM 结构中
    <template>
      <div>
        <button @click="showModal = !showModal">Toggle Modal</button>
    
        <teleport to="body">
          <div v-if="showModal" class="modal">
            <p>This is a modal!</p>
            <button @click="showModal = false">Close</button>
          </div>
        </teleport>
      </div>
    </template>
    
    <script>
    import { ref } from 'vue';
    
    export default {
      setup() {
        const showModal = ref(false);
    
        return {
          showModal
        };
      }
    };
    </script>
    
    <style>
    .modal {
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background: rgba(0, 0, 0, 0.5);
      display: flex;
      align-items: center;
      justify-content: center;
    }
    </style>
Suspense
  • 作用:用于处理异步组件的加载过程,它可以在组件异步加载时显示一个加载状态。这个功能非常适合在渲染异步数据或组件时提供用户反馈。

  • 示例

    vue 复制代码
    // Suspense 组件会在 AsyncComponent 加载时显示一个"Loading..."的文本,直到异步组件加载完成。
    <template>
      <suspense>
        <template #default>
          <AsyncComponent />
        </template>
        <template #fallback>
          <p>Loading...</p>
        </template>
      </suspense>
    </template>
    
    <script>
    import { defineAsyncComponent } from 'vue';
    
    const AsyncComponent = defineAsyncComponent(() => import('./AsyncComponent.vue'));
    
    export default {
      components: {
        AsyncComponent
      }
    };
    </script>
Fragment
  • 作用:支持多个根节点的功能,它允许一个组件返回多个根元素,而不需要额外的包裹元素。这个功能可以简化组件结构,避免不必要的 DOM 节点。

  • 示例

    vue 复制代码
    <template>
      <div></div>
      <p>First element</p>
      <p>Second element</p>
    </template>
    
    <script>
    export default {
      setup() {
        return {};
      }
    };
    </script>

    在Vue3中使用Fragment只需要在模板中使用template标签包裹多个根节点即可。

组件通信

组件通信

异步组件

  • defineAsyncComponent

    • 作用:用于定义异步组件的函数,允许你动态地加载组件,通常用于按需加载,以提高应用的性能和响应速度。

    • 示例

      js 复制代码
      // 定义一个异步组件 AsyncComponent,它会在组件需要被渲染时才会被动态加载。
      
      import { defineAsyncComponent } from 'vue';
      
      const AsyncComponent = defineAsyncComponent(() =>
        import('./MyAsyncComponent.vue')
      );
      
      export default {
        components: {
          AsyncComponent
        }
      };
    • 配置选项

      选项 是否必填 含义
      loader 返回一个 Promise,Promise 解析为异步组件
      loadingComponent 指定一个加载中组件,在异步组件正在加载时显示
      errorComponent 指定一个错误组件,如果异步组件加载失败时显示
      delay 指定加载组件的延迟时间(以毫秒为单位)
      timeout 指定加载组件的超时时间(以毫秒为单位)
    • 完整示例

      js 复制代码
      // AsyncComponent 将在加载时显示一个"Loading..."组件,如果加载失败,则显示一个错误组件。如果异步组件的加载超过了 10 秒,则会显示错误组件。
      
      import { defineAsyncComponent } from 'vue';
      
      // 定义异步组件,带有加载、错误处理和延迟配置
      const AsyncComponent = defineAsyncComponent({
        loader: () => import('./MyAsyncComponent.vue'),
        loadingComponent: {
          template: '<div>Loading...</div>'
        },
        errorComponent: {
          template: '<div>Error loading component</div>'
        },
        delay: 200, // 200ms 延迟显示 loadingComponent
        timeout: 10000 // 10秒超时
      });
      
      export default {
        components: {
          AsyncComponent
        }
      };

Vueuse(工具函数)

  • 介绍:用于 Vue 3 的工具库,提供了一系列有用的 Composition API 组合函数,帮助开发者更高效地处理常见任务。它通过简化状态管理、响应式数据和副作用的处理,提高了开发效率。

  • 主要功能

    • 状态管理 :如 useLocalStorageuseSessionStorage 让状态在浏览器存储中持久化。
    • 副作用 :如 useFetch 用于进行 HTTP 请求,useIntervaluseTimeout 用于定时任务。
    • 事件处理 :如 useEventListener 用于添加和移除事件监听器。
    • 响应式数据 :如 useDark 处理暗黑模式,useMouse 跟踪鼠标位置。
  • 安装与使用

    • 安装

      js 复制代码
      npm install @vueuse/core
    • 使用

      js 复制代码
      // 使用 useLocalStorage 管理本地存储:
      
      <template>
        <input v-model="name" placeholder="Enter your name" />
      </template>
      
      <script lang="ts">
      import { useLocalStorage } from '@vueuse/core';
      
      export default {
        setup() {
          const name = useLocalStorage('name', '');
      
          return { name };
        }
      };
      </script>
相关推荐
活宝小娜1 小时前
vue不刷新浏览器更新页面的方法
前端·javascript·vue.js
程序视点1 小时前
【Vue3新工具】Pinia.js:提升开发效率,更轻量、更高效的状态管理方案!
前端·javascript·vue.js·typescript·vue·ecmascript
coldriversnow1 小时前
在Vue中,vue document.onkeydown 无效
前端·javascript·vue.js
我开心就好o1 小时前
uniapp点左上角返回键, 重复来回跳转的问题 解决方案
前端·javascript·uni-app
开心工作室_kaic2 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
刚刚好ā2 小时前
js作用域超全介绍--全局作用域、局部作用、块级作用域
前端·javascript·vue.js·vue
沉默璇年3 小时前
react中useMemo的使用场景
前端·react.js·前端框架
yqcoder3 小时前
reactflow 中 useNodesState 模块作用
开发语言·前端·javascript
2401_882727574 小时前
BY组态-低代码web可视化组件
前端·后端·物联网·低代码·数学建模·前端框架
SoaringHeart4 小时前
Flutter进阶:基于 MLKit 的 OCR 文字识别
前端·flutter