-
Vue 2 响应式原理Vue 2 使用 Object.defineProperty() 方法来实现响应式系统。该方法可以直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回这个对象。实现原理核心方法:Object.defineProperty() 劫持对象属性的 getter 和 setter。当一个 Vue 实例创建时,Vue 会遍历 data 选项中的所有属性,使用 Object.defineProperty() 将这些属性转换为 getter/setter。依赖收集:当访问这些属性时,触发 getter,进行依赖收集;当属性值发生变化时,触发 setter,通知所有依赖更新。示例代码// 模拟 Vue 2 的响应式原理 function defineReactive(obj, key, val) { // 存储依赖的数组 const dep = []; Object.defineProperty(obj, key, { get() { // 收集依赖 if (Dep.target) { dep.push(Dep.target); } return val; }, set(newVal) { if (newVal !== val) { val = newVal; // 通知所有依赖更新 dep.forEach(watcher => watcher.update()); } } }); } // 模拟 Watcher class Watcher { constructor() { Dep.target = this; } update() { console.log('数据更新,触发视图更新'); } } // 全局变量,用于存储当前正在收集依赖的 Watcher Dep.target = null; // 创建一个对象 const obj = {}; // 使对象的属性变为响应式 defineReactive(obj, 'message', 'Hello, Vue 2!'); // 创建一个 Watcher new Watcher(); // 访问属性,触发 getter 进行依赖收集 console.log(obj.message); // 修改属性,触发 setter 通知依赖更新 obj.message = 'New message';局限性无法检测对象属性的添加和删除:因为 Object.defineProperty() 是对对象已有属性进行劫持,新增或删除属性时无法自动触发响应式更新。无法检测数组的某些变化:Vue 2 对数组的 push、pop 等方法进行了重写,但对于通过索引直接修改数组元素或修改数组长度的操作无法检测。Vue 3 响应式原理Vue 3 使用 ES6 的 Proxy 对象来实现响应式系统。Proxy 对象用于创建一个对象的代理,从而可以对该对象的基本操作进行拦截和自定义。实现原理核心方法:Proxy 可以拦截对象的各种操作,包括属性读取、属性设置、属性删除等。Vue 3 通过创建一个 Proxy 对象来代理 data 对象,当对代理对象进行操作时,会触发相应的拦截器。依赖收集和更新:在拦截器中进行依赖收集和更新通知,实现响应式。示例代码// 模拟 Vue 3 的响应式原理 function reactive(target) { // 存储依赖的 WeakMap const targetMap = new WeakMap(); function track(target, key) { let depsMap = targetMap.get(target); if (!depsMap) { targetMap.set(target, (depsMap = new Map())); } let dep = depsMap.get(key); if (!dep) { depsMap.set(key, (dep = new Set())); } if (activeEffect) { dep.add(activeEffect); } } function trigger(target, key) { const depsMap = targetMap.get(target); if (!depsMap) return; const dep = depsMap.get(key); if (dep) { dep.forEach(effect => effect()); } } return new Proxy(target, { get(target, key) { // 收集依赖 track(target, key); return target[key]; }, set(target, key, value) { target[key] = value; // 通知依赖更新 trigger(target, key); return true; } }); } // 模拟 effect let activeEffect; function effect(fn) { activeEffect = fn; fn(); activeEffect = null; } // 创建一个对象 const obj = { message: 'Hello, Vue 3!' }; // 使对象变为响应式 const reactiveObj = reactive(obj); // 创建一个 effect effect(() => { console.log(reactiveObj.message); }); // 修改属性,触发响应式更新 reactiveObj.message = 'New message';优势可以检测对象属性的添加和删除:Proxy 可以拦截对象属性的添加和删除操作,从而实现响应式更新。可以检测数组的所有变化:Proxy 可以拦截数组的所有操作,包括通过索引直接修改数组元素和修改数组长度。所以,Vue 3 的响应式原理相比 Vue 2 更加完善和强大,解决了 Vue 2 中存在的一些局限性。Vue 2 和 Vue 3 的响应式原理对性能有什么影响?Vue 2 和 Vue 3 的响应式原理在多个方面对性能产生不同的影响,下面从初始化性能、更新性能、内存占用等方面进行详细分析。初始化性能Vue 2原理特点:Vue 2 使用 Object.defineProperty() 对 data 选项中的每个属性进行递归遍历,并将其转换为 getter/setter。这意味着在初始化时,需要对对象的所有属性进行处理,对于嵌套层级较深的对象,会带来较大的性能开销。性能影响:当数据对象非常大且嵌套层级很深时,初始化过程会比较耗时,因为需要为每个属性都调用 Object.defineProperty() 方法。例如,一个包含大量嵌套对象和数组的复杂数据结构,初始化时会显著增加 CPU 的计算负担。Vue 3原理特点:Vue 3 使用 Proxy 对象来实现响应式。Proxy 是对整个对象进行代理,不需要对每个属性进行递归处理。在初始化时,只需要创建一个 Proxy 对象,当访问对象的属性时才会进行依赖收集。性能影响:相比 Vue 2,Vue 3 的初始化性能有明显提升,尤其是对于大型数据对象。因为它避免了对所有属性的递归处理,减少了初始化时的计算量。更新性能Vue 2原理特点:当修改 Vue 2 中响应式对象的属性时,会触发 setter 方法,通知所有依赖更新。但由于 Object.defineProperty() 的局限性,对于对象属性的添加和删除以及数组的某些操作(如通过索引直接修改数组元素),无法自动检测,需要使用特殊的方法(如 Vue.set、Vue.delete)来触发更新。性能影响:在更新操作时,如果使用不当,可能会导致不必要的更新或无法及时更新。而且,由于依赖收集是基于属性的 getter 和 setter,对于嵌套层级较深的对象,更新时可能需要层层触发 setter,性能开销较大。Vue 3原理特点:Vue 3 的 Proxy 可以拦截对象的各种操作,包括属性的添加、删除和数组的所有操作。当修改响应式对象时,Proxy 会立即捕获到变化,并通知所有依赖更新。性能影响:Vue 3 的更新性能更加稳定和高效。它能够更准确地检测到对象的变化,避免了 Vue 2 中因操作不当导致的更新问题。同时,由于 Proxy 的拦截机制,更新操作的响应速度更快,减少了不必要的性能损耗。内存占用Vue 2原理特点:由于 Vue 2 需要为每个属性创建 getter/setter,并且需要维护一个依赖收集系统,这会增加额外的内存开销。对于大型数据对象,每个属性都有对应的 getter/setter 和依赖信息,会占用较多的内存空间。性能影响:在处理大量数据时,Vue 2 的内存占用可能会成为性能瓶颈,尤其是在内存有限的设备上,可能会导致页面卡顿或崩溃。Vue 3原理特点:Vue 3 的 Proxy 只需要为整个对象创建一个代理,不需要为每个属性添加额外的 getter/setter,因此内存占用相对较少。同时,Vue 3 的依赖收集系统也进行了优化,减少了不必要的内存开销。性能影响:Vue 3 在内存使用上更加高效,能够更好地处理大型数据对象,减少了因内存占用过高导致的性能问题。所以我们可以看到,Vue 3 的响应式原理在初始化性能、更新性能和内存占用方面都优于 Vue 2,尤其是在处理大型数据对象时,性能提升更为明显。转载自https://www.cnblogs.com/wgjava/p/18776737
-
在 Vue 3 中,异步组件是一种强大的工具,它允许开发者在需要时才加载和渲染组件,从而优化应用的性能和资源分配。以下是对 Vue 3 异步组件的详细解析:一、定义与基本用法定义:Vue 3 中的异步组件指的是一种在需要时才加载和渲染的组件。这意味着组件不会在应用启动时立即加载,而是在真正需要显示该组件的时候,才会动态地从服务器或文件系统中加载它。基本用法:使用 defineAsyncComponent 函数来定义异步组件。这个函数是 Vue 官方提供的,它简化了异步组件的使用过程,并提供了丰富的配置选项。import { defineAsyncComponent } from 'vue'; const AsyncComp = defineAsyncComponent(() => import('./MyComponent.vue')); 在模板中,你可以像使用普通组件一样使用异步组件:<template> <AsyncComp v-if="showComponent" /> <button @click="showComponent = !showComponent">Toggle Component</button> </template> <script setup> import { ref } from 'vue'; import AsyncComp from './AsyncComponent.vue'; // 异步组件的定义 const showComponent = ref(false); </script> 二、配置选项defineAsyncComponent 函数接受一个可选的配置对象,该对象可以包含以下属性:loader:一个返回 Promise 的函数,这个 Promise 在解析时应该返回一个组件配置对象(通常是一个组件的选项对象或一个组件定义函数)。这个函数通常使用动态导入 import() 来实现。loadingComponent:当异步组件正在加载时显示的组件。默认情况下,如果没有提供,Vue 会显示一个默认的加载指示器。errorComponent:当异步组件加载失败时显示的组件。默认情况下,如果没有提供,Vue 会显示一个错误信息。delay:一个数字,表示在显示加载组件之前等待的时间(以毫秒为单位)。默认为 0,即立即显示加载组件。timeout:一个数字,表示异步组件加载的超时时间(以毫秒为单位)。如果超时,将触发错误处理。默认为 Infinity,即没有超时限制。onError:一个函数,当异步组件加载失败时调用。这个函数接收错误对象作为参数。三、高级用法动态加载组件:你可以根据条件动态地加载不同的异步组件。例如,根据用户的操作或路由的变化来加载不同的组件。const componentName = ref('AsyncComponent1'); const loadComponent = async () => { const component = await import(`./${componentName.value}.vue`); return defineAsyncComponent(() => component); }; const DynamicComponent = await loadComponent(); 使用 Suspense 组件:Vue 3 引入了 Suspense 组件,它可以用来在组件树中协调对异步依赖的处理。Suspense 允许定义一个等待异步组件加载的“占位符”,在异步组件加载完成之前,可以显示一个加载状态或者默认内容。<template> <Suspense> <template #default> <AsyncComponent /> </template> <template #fallback> <div>Loading...</div> </template> </Suspense> </template> <script setup> import { defineAsyncComponent } from 'vue'; const AsyncComponent = defineAsyncComponent(() => import('./AsyncComponent.vue')); </script> 四、应用场景按需加载:对于大型应用,可以通过异步组件实现按需加载,减少初始包的大小,提高加载速度。优化性能:通过异步加载组件,可以避免在应用启动时加载不必要的资源,从而优化应用的性能。处理依赖:在需要处理复杂的依赖关系时,可以使用异步组件来分离和延迟加载这些依赖。五、注意事项确保正确的依赖路径:在使用 import() 动态导入组件时,要确保提供的路径是正确的。处理加载和错误状态:提供合适的加载组件和错误组件,以提高用户体验。避免滥用:虽然异步组件可以提高性能,但也要避免滥用,否则可能会导致代码复杂性和维护成本的增加。综上所述,Vue 3 的异步组件功能为开发者提供了一种灵活而强大的方式来优化应用的性能和资源分配。通过合理使用异步组件,可以显著提升用户的使用体验。
-
在 Vue 3 中,依赖注入(Dependency Injection)是一种在组件树中传递数据的方式,它允许父组件或祖先组件向其后代组件提供数据或方法,而无需通过逐层传递 props。这种机制在大型应用中特别有用,因为它可以减少组件之间的直接依赖,提高代码的可维护性和复用性。以下是对 Vue 3 依赖注入的详细解析:一、关键方法Vue 3 提供了两个关键方法来实现依赖注入:provide 和 inject。provide:用于在父组件或祖先组件中提供数据。接受两个参数:key(注入名)和 value(提供的值)。key 可以是一个字符串或是一个 Symbol,用于后代组件查找期望注入的值。value 可以是任意类型,包括响应式的状态。inject:用于在后代组件中注入由父组件或祖先组件提供的数据。接受两个参数:key 和 defaultValue(可选)。key 是父组件提供值的 key。defaultValue 是当没有提供该依赖时使用的默认值,可以是具体的值,也可以是函数。二、使用示例基本的 provide 和 inject:<!-- 父组件 --> <template> <child-component></child-component> </template> <script setup> import { provide } from 'vue'; provide('message', 'Hello from Parent!'); </script> <!-- 子组件 --> <template> <div>{{ message }}</div> </template> <script setup> import { inject } from 'vue'; const message = inject('message'); </script> 在这个例子中,父组件通过 provide 提供了一个名为 message 的数据,子组件通过 inject 注入了这个数据,并在模板中显示。响应式数据的注入:<!-- 父组件 --> <template> <child-component></child-component> </template> <script setup> import { provide, ref } from 'vue'; const count = ref(0); provide('count', count); </script> <!-- 子组件 --> <template> <div>{{ count }}</div> <button @click="increment">Increment</button> </template> <script setup> import { inject } from 'vue'; const count = inject('count'); const increment = () => { count.value++; }; </script> 在这个例子中,父组件提供了一个响应式的 count 变量,子组件注入后可以访问并修改它,所有注入该响应式变量的组件都会自动更新。使用 Symbol 作为注入名:为了避免命名冲突,可以使用 Symbol 作为注入名。这通常在一个单独的文件中定义 Symbol,然后在父组件和子组件中导入它。// keys.js export const myInjectionKey = Symbol(); <!-- 父组件 --> <template> <child-component></child-component> </template> <script setup> import { provide } from 'vue'; import { myInjectionKey } from './keys.js'; provide(myInjectionKey, 'Secret Message'); </script> <!-- 子组件 --> <template> <div>{{ message }}</div> </template> <script setup> import { inject } from 'vue'; import { myInjectionKey } from './keys.js'; const message = inject(myInjectionKey); </script> 三、注意事项组件关系:依赖注入的组件必须是一棵组件树的前后代关系,兄弟组件之间不支持依赖注入。响应式数据修改:不建议后代组件中直接修改注入的响应式数据的值。如果需要修改,建议在提供依赖的组件中暴露修改数据的方法。全局注入:虽然支持全局注入,但要谨慎使用,避免引入不必要的全局状态。命名冲突:使用字符串作为注入名时,要注意命名冲突的问题。使用 Symbol 可以有效避免这个问题。通过依赖注入,Vue 3 提供了一种强大而灵活的方式来管理组件之间的依赖关系和数据传递。在大型项目中,合理使用依赖注入可以显著提高代码的可维护性和复用性。
-
在 Vue 3 中,插槽(Slots)是一种强大的机制,允许父组件向子组件传递内容。插槽的使用不仅提高了组件的复用性,还增强了组件的灵活性。以下是对 Vue 3 中插槽用法的详细解析:一、默认插槽(Default Slots)默认插槽是最基本的插槽类型,用于在组件中插入内容。在子组件中,使用 <slot> 标签定义插槽位置。父组件在使用子组件时,将需要插入的内容放在子组件标签内部即可。示例:<!-- 子组件 ChildComponent.vue --> <template> <div class="child-component"> <slot></slot> <!-- 默认插槽 --> </div> </template> <!-- 父组件 ParentComponent.vue --> <template> <div class="parent-component"> <ChildComponent> <p>这是插入到默认插槽的内容</p> </ChildComponent> </div> </template> 在上面的示例中,父组件的内容 <p>这是插入到默认插槽的内容</p> 会被渲染到子组件的 <slot> 位置。二、命名插槽(Named Slots)有时候,一个插槽不能满足业务需求,可以使用命名插槽定义多个插槽位置。在子组件中,使用 name 属性为 <slot> 标签命名。父组件在使用子组件时,需要使用 <template v-slot:slotName> 的形式向指定插槽位置投放内容。示例:<!-- 子组件 ChildComponent.vue --> <template> <div class="child-component"> <slot name="header"></slot> <slot></slot> <!-- 默认插槽 --> <slot name="footer"></slot> </div> </template> <!-- 父组件 ParentComponent.vue --> <template> <div class="parent-component"> <ChildComponent> <template v-slot:header> <h3>这是头部插槽的内容</h3> </template> <p>这是插入到默认插槽的内容</p> <template v-slot:footer> <p>这是底部插槽的内容</p> </template> </ChildComponent> </div> </template> 在上面的示例中,子组件定义了三个插槽:header、默认插槽和 footer。父组件分别向这三个插槽插入了对应的内容。三、作用域插槽(Scoped Slots)作用域插槽允许父组件访问子组件内部的数据。在子组件中,使用特殊的 v-slot 指令声明作用域插槽,并将需要传递给父组件的数据作为 v-slot 的参数。父组件在使用子组件时,通过 v-slot 指令接收这些数据,并在插槽内容中使用。示例:<!-- 子组件 ChildComponent.vue --> <template> <div class="child-component"> <slot name="header" :message="message"></slot> </div> </template> <script> export default { data() { return { message: 'Hello from ChildComponent!' }; } }; </script> <!-- 父组件 ParentComponent.vue --> <template> <div class="parent-component"> <ChildComponent> <template v-slot:header="{ message }"> <h3>{{ message }}</h3> </template> </ChildComponent> </div> </template> 在上面的示例中,子组件将 message 数据通过作用域插槽传递给父组件。父组件在插槽内容中使用 {{ message }} 来显示这些数据。四、动态插槽名称Vue 3 支持动态插槽名称。在父组件的 v-slot 指令中,可以使用表达式作为插槽的名称。示例:<!-- 子组件 ChildComponent.vue --> <template> <div class="child-component"> <slot :name="slotName"></slot> </div> </template> <script> export default { props: { slotName: { type: String, required: true } } }; </script> <!-- 父组件 ParentComponent.vue --> <template> <div class="parent-component"> <ChildComponent :slotName="'dynamicSlot'"> <template v-slot:[dynamicSlotName]> <p>这是动态插槽的内容</p> </template> </ChildComponent> </div> </template> <script> export default { data() { return { dynamicSlotName: 'dynamicSlot' }; } }; </script> 注意:在上面的动态插槽名称示例中,由于 Vue 的模板编译限制,直接在 ChildComponent 标签内部使用动态插槽名称可能不起作用。因此,该示例更多是为了说明动态插槽名称的概念,实际使用时可能需要采用其他方式来实现类似的功能。五、插槽的简写形式Vue 3 允许使用简写形式来定义和使用插槽。对于默认插槽,可以省略 <template> 标签和 v-slot 指令中的 default 关键字;对于命名插槽,可以使用 # 作为 v-slot 的简写。示例:<!-- 子组件 ChildComponent.vue --> <template> <div class="child-component"> <slot name="header"></slot> <slot></slot> <!-- 默认插槽 --> </div> </template> <!-- 父组件 ParentComponent.vue --> <template> <div class="parent-component"> <ChildComponent> <template #header> <h3>这是头部插槽的内容(简写形式)</h3> </template> <p>这是插入到默认插槽的内容(无需 <template> 和 v-slot)</p> </ChildComponent> </div> </template> 综上所述,Vue 3 中的插槽提供了丰富的功能,包括默认插槽、命名插槽、作用域插槽和动态插槽名称等。这些功能使得父组件能够灵活地向子组件传递内容,并访问子组件内部的数据。
-
Vue 3 引入了 Composition API,这允许开发者以一种更加模块化和可复用的方式组织和复用代码。尽管 Options API 仍然被支持,但 Composition API 提供了一些新的生命周期钩子,并且可以更灵活地管理组件的生命周期。以下是 Vue 3 中常用的生命周期钩子及其对应的 Options API 和 Composition API 表示方式:Options API 生命周期钩子beforeCreate在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。created在实例创建完成后被立即调用。在这一步,实例已完成数据观测、属性和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。beforeMount在挂载开始之前被调用:相关的 render 函数首次被调用。mountedel 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。如果根实例挂载到了文档内,当 mounted 被调用时,组件已经在其真实的 DOM 里。beforeUpdate数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。updated由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用这个钩子。当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态,因为这可能会导致无限更新循环。beforeUnmount在卸载组件实例之前调用。在这个阶段,实例仍然是完全可用的。unmounted卸载组件实例后调用。调用后,组件实例指示的所有东西都会解绑,所有的事件监听器会被移除,所有的子实例也会被销毁。Composition API 生命周期钩子Vue 3 的 Composition API 提供了与 Options API 相对应的生命周期钩子函数,这些函数需要在 setup 函数中调用。beforeCreate 和 created在 setup 函数中,由于 setup 是在 beforeCreate 和 created 之间执行的,所以这两个生命周期钩子在 setup 函数中无法直接使用。但是,setup 函数本身可以视为一个替代。beforeMount 和 mountedonBeforeMount 和 onMountedbeforeUpdate 和 updatedonBeforeUpdate 和 onUpdatedbeforeUnmount 和 unmountedonBeforeUnmount 和 onUnmounted示例代码Options API<template> <div>Hello, Vue 3!</div> </template> <script> export default { name: 'MyComponent', data() { return { message: 'Hello, Vue 3!' }; }, beforeCreate() { console.log('beforeCreate'); }, created() { console.log('created'); }, beforeMount() { console.log('beforeMount'); }, mounted() { console.log('mounted'); }, beforeUpdate() { console.log('beforeUpdate'); }, updated() { console.log('updated'); }, beforeUnmount() { console.log('beforeUnmount'); }, unmounted() { console.log('unmounted'); } }; </script> Composition API<template> <div>Hello, Vue 3!</div> </template> <script> import { onMounted, onUpdated, onBeforeUnmount, onUnmounted } from 'vue'; export default { name: 'MyComponent', setup() { onMounted(() => { console.log('mounted'); }); onUpdated(() => { console.log('updated'); }); onBeforeUnmount(() => { console.log('beforeUnmount'); }); onUnmounted(() => { console.log('unmounted'); }); // 其他 Composition API 代码 return {}; } }; </script> 使用 Composition API 时,生命周期钩子是通过导入和调用对应的函数来实现的,这使得在大型组件中更容易管理和复用逻辑。
-
在 Vue 3 中,组件间传递参数有多种方式,以下是几种常见的方法:1. Props(父传子)方式:父组件通过 v-bind 或简写 : 绑定变量,子组件通过 defineProps 接收参数。优点:简单直观,符合单向数据流原则,易于理解和维护。缺点:仅适用于父子组件之间的通信,跨级组件或兄弟组件通信较为繁琐。2. 自定义事件(子传父)方式:子组件通过 defineEmits 注册事件,并通过 $emit 触发事件,父组件通过 @ 或 v-on 监听事件。优点:适用于子组件向父组件发送数据。缺点:需要手动注册和触发事件,增加了代码的复杂性。3. $attrs(爷孙传参)方式:父组件传递的属性中,未在子组件 props 中定义的属性,可以通过 $attrs 接收,并传递给孙组件。优点:可以接收未在 props 中定义的属性,适用于多层组件间的属性传递。缺点:需要手动处理 $attrs,增加了代码的复杂性。4. refs(直接访问子组件实例)方式:父组件通过 ref 属性引用子组件实例,可以直接访问子组件的属性和方法。优点:可以直接操作子组件的属性和方法,适用于需要直接控制子组件的场景。缺点:破坏了组件的封装性,可能导致维护困难。5. v-model(双向绑定)方式:v-model 是一个语法糖,用于实现数据与视图的双向绑定。在组件中,可以通过 v-bind 和 v-on 的组合来实现类似的效果。优点:简化了双向绑定的实现,提高了代码的可读性。缺点:需要组件支持 v-model,且通常用于表单输入等场景。6. provide/inject(多层传参)方式:祖先组件通过 provide 提供依赖,后代组件通过 inject 注入依赖。优点:适用于跨越多个层级传递数据的场景,避免了层层传递 props 的繁琐。缺点:破坏了组件的封装性,使得组件间的依赖关系不明显,可能导致维护困难。7. 路由传参方式:通过 Vue Router 的 query、params 或 state 传递参数。优点:参数值持久存储,适用于页面间的参数传递。缺点:query 和 params 的参数会暴露在 URL 中,可能不安全;state 的参数不会暴露在 URL 中,但需要在路由配置中指定。8. 全局状态管理(Vuex/Pinia)方式:使用 Vuex 或 Pinia 等全局状态管理库,在组件间共享状态。优点:提供了集中式的状态管理方案,便于管理和维护全局状态。缺点:增加了项目的复杂性,需要学习全局状态管理库的使用。9. mitt(兄弟组件传参)方式:使用 mitt.js 插件实现兄弟组件间的通信,类似于 Vue 2 中的全局事件总线 $bus。优点:适用于所有组件间的通信,将事件统一管理。缺点:需要引入外部插件,增加了项目的依赖。10. 浏览器缓存/window 对象方式:通过浏览器缓存(如 localStorage、sessionStorage)或 window 对象全局挂载全局对象或属性来传递参数。优点:可以在不同页面或组件间共享数据。缺点:可能受到浏览器安全策略的限制,且数据持久化可能导致性能问题。综上所述,Vue 3 组件间传递参数的方式多种多样,每种方式都有其适用的场景和优缺点。在实际开发中,应根据具体需求选择合适的方式来实现组件间的参数传递。
-
在 Vue 3 中,组件是构建用户界面的基本单位。组件允许你将 UI 拆分成可复用的独立部分,每个部分都包含自己的逻辑、样式和模板。以下是 Vue 3 组件的基础用法:1. 定义一个组件你可以使用 defineComponent 函数(在 Vue 3 的 Composition API 中)或一个简单的对象字面量(在 Options API 中)来定义一个组件。使用 Composition APIimport { defineComponent, ref } from 'vue'; export default defineComponent({ name: 'MyComponent', setup() { const count = ref(0); const increment = () => { count.value++; }; return { count, increment, }; }, }); 使用 Options APIexport default { name: 'MyComponent', data() { return { count: 0, }; }, methods: { increment() { this.count++; }, }, }; 2. 注册组件在 Vue 3 中,你可以通过全局或局部方式注册组件。全局注册import { createApp } from 'vue'; import MyComponent from './MyComponent.vue'; import App from './App.vue'; const app = createApp(App); app.component('MyComponent', MyComponent); app.mount('#app'); 局部注册<template> <div> <MyComponent /> </div> </template> <script> import MyComponent from './MyComponent.vue'; export default { components: { MyComponent, }, }; </script> 3. 使用组件一旦组件被注册,你就可以在模板中使用它了。<template> <div> <MyComponent /> </div> </template> 4. 传递 Props组件之间可以通过 Props 传递数据。定义 Propsexport default { props: { title: { type: String, required: true, }, }, }; 使用 Props<template> <div> <h1>{{ title }}</h1> </div> </template> 传递 Props<template> <div> <MyComponent title="Hello, World!" /> </div> </template> 5. 事件处理组件可以通过 $emit 方法触发事件,父组件可以监听这些事件。触发事件export default { methods: { notify() { this.$emit('notify-event', 'Some message'); }, }, }; 监听事件<template> <div> <MyComponent @notify-event="handleNotify" /> </div> </template> <script>export default { methods: { handleNotify(message) { console.log(message); }, }, }; </script> 6. 插槽(Slots)插槽允许你定义组件的哪些部分可以被父组件的内容所替换。定义插槽<template> <div> <slot></slot> </div> </template> 使用插槽<template> <div> <MyComponent> <p>This content will be rendered inside the slot.</p> </MyComponent> </div> </template> 总结以上是 Vue 3 组件的基础用法,包括定义、注册、使用、传递 Props、事件处理和插槽。通过这些基础,你可以开始构建更复杂和可复用的 Vue 组件。随着你对 Vue 3 的深入了解,你还可以探索更多高级功能,如组合式 API、生命周期钩子、自定义指令等。
-
在 Vue 3 中,侦听器(watchers)是一种用于观察和响应 Vue 实例上数据变化的机制。与计算属性(computed properties)不同,侦听器允许你执行异步操作或更复杂的副作用处理。在 Vue 3 中,你可以使用 watch 函数来创建侦听器。watch 函数可以在组件的 setup 函数中使用,也可以在组合式 API 的其他部分使用。以下是一些关于如何在 Vue 3 中使用侦听器的基本示例和说明:基本用法<template> <div> <p>Number: {{ number }}</p> <button @click="increment">Increment</button> </div> </template> <script> import { ref, watch } from 'vue'; export default { setup() { const number = ref(0); const increment = () => { number.value++; }; // 侦听 number 的变化 watch(number, (newVal, oldVal) => { console.log(`Number changed from ${oldVal} to ${newVal}`); }); return { number, increment, }; }, }; </script> 在这个例子中,watch 函数用于侦听 number 的变化,并在变化时执行回调函数。侦听多个源你可以使用一个数组来同时侦听多个响应式引用或计算属性:<script> import { ref, watch } from 'vue'; export default { setup() { const foo = ref(''); const bar = ref(''); watch([foo, bar], ([newFoo, newBar], [oldFoo, oldBar]) => { console.log(`Foo changed from ${oldFoo} to ${newFoo}`); console.log(`Bar changed from ${oldBar} to ${newBar}`); }); return { foo, bar, }; }, }; </script> 深度侦听默认情况下,watch 只能侦听引用类型(对象或数组)的顶层属性的变化。如果你需要侦听嵌套属性的变化,可以使用 deep 选项:<script> import { reactive, watch } from 'vue'; export default { setup() { const user = reactive({ name: 'John', address: { city: 'New York', }, }); watch(user, (newVal, oldVal) => { console.log('User changed:', newVal, oldVal); }, { deep: true }); // 修改嵌套属性 setTimeout(() => { user.address.city = 'Los Angeles'; }, 2000); return { user, }; }, }; </script> 立即执行默认情况下,侦听器在第一次绑定时不会立即执行其回调函数。如果你希望在绑定时立即执行一次,可以使用 immediate 选项:<script> import { ref, watch } from 'vue'; export default { setup() { const count = ref(0); watch(count, (newVal, oldVal) => { console.log(`Count changed from ${oldVal} to ${newVal}`); }, { immediate: true }); return { count, }; }, }; </script> 停止侦听watch 函数返回一个停止侦听的函数。你可以调用这个函数来停止侦听某个响应式源:<script> import { ref, watch, onUnmounted } from 'vue'; export default { setup() { const count = ref(0); let stopWatch; stopWatch = watch(count, (newVal, oldVal) => { console.log(`Count changed from ${oldVal} to ${newVal}`); }); // 在组件卸载时停止侦听 onUnmounted(() => { stopWatch(); }); return { count, }; }, }; </script> 这些示例展示了 Vue 3 中 watch 函数的一些基本用法和选项。通过这些功能,你可以灵活地侦听和响应 Vue 实例上的数据变化。
-
在 Vue 3 中,表单输入绑定可以通过 v-model 指令来实现。v-model 提供了双向数据绑定,使得表单元素的值可以自动同步到组件的数据属性中,反之亦然。以下是一些关于 Vue 3 表单输入绑定的关键点:基本使用文本输入框:<template> <input v-model="message" placeholder="Enter your message" /> <p>Message is: {{ message }}</p> </template> <script> import { ref } from 'vue'; export default { setup() { const message = ref(''); return { message }; } } </script> 多行文本输入:<template> <textarea v-model="bio"></textarea> <p>Bio: {{ bio }}</p> </template> <script> import { ref } from 'vue'; export default { setup() { const bio = ref(''); return { bio }; } } </script> 单选按钮:<template> <div> <input type="radio" id="yes" value="Yes" v-model="choice" /> <label for="yes">Yes</label> <input type="radio" id="no" value="No" v-model="choice" /> <label for="no">No</label> </div> <p>Chosen: {{ choice }}</p> </template> <script> import { ref } from 'vue'; export default { setup() { const choice = ref(''); return { choice }; } } </script> 复选框:<template> <div> <input type="checkbox" id="subscribe" v-model="subscribe" /> <label for="subscribe">Subscribe</label> </div> <p>Subscribe: {{ subscribe }}</p> </template> <script> import { ref } from 'vue'; export default { setup() { const subscribe = ref(false); return { subscribe }; } } </script> 选择框:<template> <select v-model="selected"> <option disabled value="">Please select one</option> <option>Option 1</option> <option>Option 2</option> <option>Option 3</option> </select> <p>Selected: {{ selected }}</p> </template> <script> import { ref } from 'vue'; export default { setup() { const selected = ref(''); return { selected }; } } </script> 修饰符.lazy:默认情况下,v-model 会在 input 事件后同步输入框的值。使用 .lazy 修饰符,可以改为在 change 事件后同步。<template> <input v-model.lazy="message" /> </template> .number:如果想自动将用户输入值转换为数值类型,可以使用 .number 修饰符。<template> <input v-model.number="age" type="number" /> </template> <script> import { ref } from 'vue'; export default { setup() { const age = ref(0); return { age }; } } </script> .trim:自动过滤用户输入的首尾空白字符。<template> <input v-model.trim="username" /> </template> 组合式 API 与响应式数据在 Vue 3 的组合式 API 中,通常使用 ref 或 reactive 来管理响应式数据。ref 适用于简单数据类型(如字符串、数字、布尔值),而 reactive 适用于复杂数据结构(如对象、数组)。<template> <form @submit.prevent="handleSubmit"> <input v-model="formData.name" placeholder="Your name" /> <input v-model="formData.email" type="email" placeholder="Your email" /> <button type="submit">Submit</button> </form> </template> <script> import { reactive } from 'vue'; export default { setup() { const formData = reactive({ name: '', email: '' }); function handleSubmit() { console.log(formData); // 打印表单数据 } return { formData, handleSubmit }; } } </script> 通过这些方法,你可以在 Vue 3 中有效地处理表单输入绑定,实现与用户的交互和数据同步。
-
在 Vue 3 中,事件处理与 Vue 2 类似,但也有一些改进和变化。以下是一些关于 Vue 3 事件处理的关键点:基本语法绑定事件:使用 v-on 指令来绑定事件,简写为 @。<template> <button @click="handleClick">Click me</button> </template> <script> export default { methods: { handleClick() { console.log('Button clicked!'); } } } </script> 方法事件处理器:可以直接在组件的 methods 选项中定义方法,并在模板中使用这些方法作为事件处理器。内联语句处理器:可以直接在模板中使用 JavaScript 表达式。<template> <button @click="count++">Clicked {{ count }} times.</button> </template> <script> export default { data() { return { count: 0 } } } </script> 事件对象在事件处理器中,Vue 会自动注入原生的浏览器事件对象,可以通过参数接收:<template> <button @click="handleClick($event)">Click me</button> </template> <script> export default { methods: { handleClick(event) { console.log(event); // 打印事件对象 } } } </script> 修饰符Vue 提供了一些修饰符,可以用于调整事件处理器行为:.stop - 调用 event.stopPropagation()。<button @click.stop="handleClick">Click me</button> .prevent - 调用 event.preventDefault()。<form @submit.prevent="onSubmit">...</form> .capture - 使用事件捕获模式。<div @click.capture="onDivClick">...</div> .self - 只在事件是从自身元素触发时触发回调。<div @click.self="onDivSelfClick">...</div> .once - 事件处理器最多只会触发一次。<button @click.once="handleClickOnce">Click me once</button> .passive - 提高滚动性能,表示事件侦听器不会调用 preventDefault()。<div @scroll.passive="onScroll">...</div> 按键修饰符Vue 还提供了按键修饰符,用于监听特定按键事件:.enter, .tab, 等:<input @keyup.enter="submitForm" /> 自定义事件在子组件中触发事件:使用 this.$emit 在子组件中触发自定义事件。<template> <button @click="emitEvent">Emit Event</button> </template> <script> export default { methods: { emitEvent() { this.$emit('custom-event', { data: 'Hello' }); } } } </script> 在父组件中监听事件:使用 v-on 或 @ 来监听子组件的事件。<template> <ChildComponent @custom-event="handleCustomEvent" /> </template> <script> import ChildComponent from './ChildComponent.vue'; export default { components: { ChildComponent }, methods: { handleCustomEvent(payload) { console.log(payload); // { data: 'Hello' } } } } </script> 组合式 API 中的事件处理如果使用组合式 API,可以通过 ref 和 reactive 来管理状态,并在 setup 函数中定义事件处理逻辑:<template> <button @click="increment">Clicked {{ count }} times.</button> </template> <script> import { ref } from 'vue'; export default { setup() { const count = ref(0); function increment() { count.value++; } return { count, increment }; } } </script> 通过这些方式,你可以在 Vue 3 中有效地处理事件并与用户进行交互。
-
在 Vue 3 中,列表渲染是一种根据数组或对象的数据动态生成一组元素的技术。Vue 提供了 v-for 指令来实现列表渲染。以下是关于 Vue 3 中列表渲染的详细解释:1. 使用 v-for 渲染列表基本用法:v-for 指令用于遍历数组或对象,并生成一个元素列表。<template> <ul> <li v-for="item in items" :key="item.id">{{ item.name }}</li> </ul> </template> <script>export default { data() { return { items: [ { id: 1, name: 'Item 1' }, { id: 2, name: 'Item 2' }, { id: 3, name: 'Item 3' } ] }; } }; </script> key 属性:在使用 v-for 时,建议为每个生成的元素指定一个唯一的 key。key 用于帮助 Vue 识别哪些元素被改变、被添加或被移除,以优化渲染性能。2. 遍历对象对象遍历:可以使用 v-for 遍历对象的属性。<template> <ul> <li v-for="(value, key) in object" :key="key">{{ key }}: {{ value }}</li> </ul> </template> <script>export default { data() { return { object: { name: 'John', age: 30, occupation: 'Developer' } }; } }; </script> 3. 使用 v-for 的高级用法访问索引:在遍历数组时,可以通过第二个参数访问当前项的索引。<template> <ul> <li v-for="(item, index) in items" :key="item.id"> {{ index }}: {{ item.name }} </li> </ul> </template> 遍历范围:可以使用整数直接生成一个特定范围的列表。<template> <ul> <li v-for="n in 5" :key="n">Number {{ n }}</li> </ul> </template> 4. 列表的复杂用法嵌套循环:在需要渲染嵌套列表时,可以在一个 v-for 内嵌套另一个 v-for。<template> <div> <div v-for="category in categories" :key="category.id"> <h3>{{ category.name }}</h3> <ul> <li v-for="item in category.items" :key="item.id">{{ item.name }}</li> </ul> </div> </div> </template> <script>export default { data() { return { categories: [ { id: 1, name: 'Category 1', items: [{ id: 1, name: 'Item 1' }, { id: 2, name: 'Item 2' }] }, { id: 2, name: 'Category 2', items: [{ id: 3, name: 'Item 3' }] } ] }; } }; </script> 5. 使用组合 API 进行列表渲染结合 ref 和 computed:在组合 API 中,可以使用 ref 和 computed 来管理和计算列表数据。<template> <ul> <li v-for="item in items" :key="item.id">{{ item.name }}</li> </ul> </template> <script>import { ref, computed } from 'vue'; export default { setup() { const rawItems = ref([ { id: 1, name: 'Item 1' }, { id: 2, name: 'Item 2' }, { id: 3, name: 'Item 3' } ]); const items = computed(() => rawItems.value.filter(item => item.name.startsWith('Item'))); return { items }; } }; </script> 6. 维护和更新列表响应性:Vue 的响应式系统会自动检测数组的变化并更新 DOM。因此,直接修改数组(如添加、删除元素)会自动反映在视图上。methods: { addItem() { this.items.push({ id: this.items.length + 1, name: `Item ${this.items.length + 1}` }); }, removeItem(index) { this.items.splice(index, 1); } } 7. 列表渲染的注意事项key 的重要性:确保每个列表项都有一个唯一的 key,以便 Vue 能够高效地更新和渲染列表。避免直接使用索引作为 key:在列表项可能改变位置或顺序时,避免直接使用索引作为 key,因为这可能导致渲染错误。总结v-for 指令:用于遍历数组或对象,生成元素列表。key 属性:用于优化渲染性能,确保每个元素唯一。高级用法:支持访问索引、遍历范围以及嵌套循环。组合 API:结合 ref 和 computed,在 setup 函数中实现更灵活的列表渲染。响应性:Vue 的响应式系统会自动更新列表变化。通过这些功能,Vue 3 提供了强大且灵活的列表渲染功能,帮助开发者根据数据动态地生成和管理内容。
-
在 Vue 3 中,条件渲染是一种根据应用状态动态地显示或隐藏元素的技术。Vue 提供了多种指令和方法来实现条件渲染,包括 v-if、v-else-if、v-else、v-show 以及组合 API 中的条件逻辑。以下是对 Vue 3 中条件渲染的详细解释:1. v-if、v-else-if、v-elsev-if:用于根据表达式的真假来决定是否渲染元素。<template> <div v-if="isVisible">This is visible if isVisible is true</div> </template> <script>export default { data() { return { isVisible: true }; } }; </script> v-else-if:用于在 v-if 链中添加多个条件。<template> <div v-if="status === 'success'">Success!</div> <div v-else-if="status === 'pending'">Loading...</div> <div v-else-if="status === 'error'">Error occurred!</div> </template> <script>export default { data() { return { status: 'pending' }; } }; </script> v-else:用于在 v-if 或 v-else-if 链的末尾添加一个默认条件。<template> <div v-if="status === 'success'">Success!</div> <div v-else-if="status === 'pending'">Loading...</div> <div v-else>Something went wrong!</div> </template> 2. v-show用法:v-show 指令用于根据表达式的真假来决定是否显示元素,而不是渲染。元素始终存在于 DOM 中,只是通过 CSS 的 display 属性来控制显示。<template> <div v-show="isVisible">This is visible if isVisible is true</div> </template> <script>export default { data() { return { isVisible: true }; } }; </script> 区别:与 v-if 不同的是,v-show 不会移除元素,只是简单地切换元素的显示状态。这在需要频繁切换显示状态时性能更好。3. 组合 API 中的条件渲染使用 JavaScript 逻辑:在组合 API 中,可以使用 JavaScript 的条件逻辑来控制渲染。<template> <div v-if="shouldRender">This is rendered based on JavaScript logic</div> </template> <script>import { ref, computed } from 'vue'; export default { setup() { const isActive = ref(true); const shouldRender = computed(() => isActive.value && someOtherCondition()); function someOtherCondition() { // 自定义条件逻辑 return true; } return { shouldRender }; } }; </script> 4. 使用 <template> 进行条件渲染<template> 标签:<template> 标签本身不会渲染到 DOM 中,但可以用来包裹多个元素,结合条件渲染指令一起使用。<template> <div v-if="condition"> <template v-if="anotherCondition"> <p>Condition and anotherCondition are both true.</p> </template> <template v-else> <p>Condition is true, but anotherCondition is false.</p> </template> </div> </template> 5. v-if 与 v-for 优先级优先级:当 v-if 与 v-for 一起使用时,v-for 的优先级比 v-if 高。这意味着即使 v-if 返回 false,v-for 仍然会遍历整个列表。为了避免这种情况,通常建议在同一个元素上避免同时使用 v-if 和 v-for。<!-- 不推荐 --> <div v-for="item in items" v-if="item.isVisible" :key="item.id"> {{ item.name }} </div> <!-- 推荐 --> <template v-for="item in items" :key="item.id"> <div v-if="item.isVisible"> {{ item.name }} </div> </template> 总结v-if、v-else-if、v-else:用于根据条件动态地渲染元素。v-show:用于根据条件动态地显示或隐藏元素,而不移除它们。组合 API:利用 JavaScript 逻辑在 setup 函数中实现更复杂的条件渲染。<template> 标签:用于包裹多个元素,结合条件渲染指令使用。优先级:注意 v-if 和 v-for 的优先级问题,避免潜在的性能陷阱。通过这些工具和方法,Vue 3 提供了灵活且强大的条件渲染功能,帮助开发者根据应用状态动态地控制内容的显示和隐藏。
-
在 Vue 3 中,类与样式的绑定是动态地控制元素样式和类名的强大工具。Vue 提供了多种语法来实现这一功能,包括对象语法和数组语法。以下是对 Vue 3 中类与样式绑定的详细解释:类绑定1. 对象语法用法:通过对象语法,可以将一个对象传递给 :class 指令,对象的键是类名,值是布尔值。如果值为 true,则该类名会被添加到元素上。<template> <div :class="{ active: isActive, 'text-danger': hasError }">Hello Vue 3</div> </template> <script>export default { data() { return { isActive: true, hasError: false }; } }; </script> 在上述例子中,如果 isActive 为 true,则 active 类会被添加到 div 元素上;如果 hasError 为 true,则 text-danger 类会被添加。动态绑定对象:也可以直接绑定一个对象或计算属性到 :class。<template> <div :class="classObject">Hello Vue 3</div> </template> <script>export default { data() { return { isActive: true, hasError: false }; }, computed: { classObject() { return { active: this.isActive, 'text-danger': this.hasError }; } } }; </script> 2. 数组语法用法:通过数组语法,可以将一个类名数组传递给 :class 指令,Vue 会将数组中的每个类名都添加到元素上。<template> <div :class="[activeClass, errorClass]">Hello Vue 3</div> </template> <script>export default { data() { return { activeClass: 'active', errorClass: 'text-danger' }; } }; </script> 条件渲染:可以在数组中使用三元表达式来有条件地渲染类名。<template> <div :class="[isActive ? activeClass : '', errorClass]">Hello Vue 3</div> </template> <script>export default { data() { return { isActive: true, activeClass: 'active', errorClass: 'text-danger' }; } }; </script> 嵌套对象:也可以在数组中嵌套对象,以实现更复杂的条件渲染。<template> <div :class="[{ active: isActive }, errorClass]">Hello Vue 3</div> </template> <script>export default { data() { return { isActive: true, errorClass: 'text-danger' }; } }; </script> 样式绑定1. 对象语法用法:通过对象语法,可以将一个对象传递给 :style 指令,对象的键是 CSS 属性名(使用 camelCase 或 kebab-case),值是对应的样式值。<template> <div :style="{ color: activeColor, fontSize: fontSize + 'px' }">Hello Vue 3</div> </template> <script>export default { data() { return { activeColor: 'red', fontSize: 16 }; } }; </script> 动态绑定对象:也可以直接绑定一个对象或计算属性到 :style。<template> <div :style="styleObject">Hello Vue 3</div> </template> <script>export default { data() { return { activeColor: 'red', fontSize: 16 }; }, computed: { styleObject() { return { color: this.activeColor, fontSize: this.fontSize + 'px' }; } } }; </script> 2. 数组语法用法:通过数组语法,可以将多个样式对象传递给 :style 指令,Vue 会将这些样式对象合并后应用到元素上。<template> <div :style="[baseStyles, overridingStyles]">Hello Vue 3</div> </template> <script>export default { data() { return { baseStyles: { color: 'red', fontSize: '16px' }, overridingStyles: { backgroundColor: 'lightgray' } }; } }; </script> 优先级:如果多个样式对象有相同的属性,则后面的样式对象会覆盖前面的样式对象。总结类绑定:使用对象语法或数组语法动态地添加或移除类名。样式绑定:使用对象语法或数组语法动态地设置元素的样式。计算属性:在计算属性中返回对象或数组,以实现更复杂的逻辑和更好的代码组织。通过这些绑定方式,Vue 3 提供了灵活且强大的工具,帮助开发者根据应用状态动态地控制元素的样式和类名。
-
在 Vue 3 中,计算属性是一种基于其他属性值动态计算出的属性,其计算结果会被缓存,只有当依赖的属性发生变化时,相关计算才会重新执行。这使得计算属性非常适合处理复杂逻辑或是重复使用的逻辑,而无需在模板中编写过多的代码。定义计算属性在 Vue 3 组件中,计算属性是在 computed 选项中定义的。下面是一个简单的例子:<template> <div> <p>Original message: {{ message }}</p> <p>Reversed message: {{ reversedMessage }}</p> </div> </template> <script>export default { data() { return { message: 'Hello Vue 3' } }, computed: { // 计算属性 reversedMessage() { // 计算属性的值是基于 `message` 的 return this.message.split('').reverse().join(''); } } } </script> 计算属性的特点缓存:计算属性会基于其依赖的数据进行缓存,只有当依赖的数据发生变化时才会重新计算。这意味着,如果 message 没有变化,多次访问 reversedMessage 不会触发新的计算。声明式:计算属性的使用是声明式的,你只需要定义它们之间的关系,Vue 会负责管理和更新。可读:计算属性一般用于读取数据,但它们也可以是可写的(即可以设置 getter 和 setter)。可写计算属性如果你需要计算属性既可以读取又可以写入,你可以使用 getter 和 setter。如下例所示:<template> <div> <p>Full name: {{ fullName }}</p> <input v-model="fullName" placeholder="Enter full name"> </div> </template> <script>export default { data() { return { firstName: 'John', lastName: 'Doe' } }, computed: { fullName: { // getter get() { return `${this.firstName} ${this.lastName}`; }, // setter set(newValue) { const names = newValue.split(' '); this.firstName = names[0]; this.lastName = names[names.length - 1]; } } } } </script> 在这个例子中,fullName 是一个可写的计算属性。当 fullName 被修改时,setter 会被调用,并更新 firstName 和 lastName。计算属性 vs 方法计算属性:适用于基于其他数据计算数据的场景,有缓存机制,适合复杂计算。方法:用于执行操作或返回计算结果,但每次调用都会执行函数,没有缓存。选择使用计算属性还是方法,主要取决于你是否需要缓存结果。对于需要频繁访问且计算开销较大的数据,计算属性是更好的选择。
-
Vue 3 中的模板语法是用于将数据绑定到 DOM 的一种声明式语法。它允许你在 HTML 中嵌入 Vue 的特定指令和表达式,从而实现动态内容的展示。以下是一些常用的 Vue 3 模板语法示例和概念:插值文本插值:使用双大括号 {{ }} 来绑定数据。<template> <div>{{ message }}</div> </template> <script>export default { data() { return { message: 'Hello, Vue 3!' } } } </script> HTML 插值:使用 v-html 指令来插入 HTML 内容。<template> <div v-html="rawHtml"></div> </template> <script>export default { data() { return { rawHtml: '<span style="color: red;">This is red text.</span>' } } } </script> 指令Vue 提供了一组指令用于执行 DOM 操作。指令以 v- 开头。v-bind:绑定元素属性。<template> <img v-bind:src="imageSrc" alt="Image"> </template> <script>export default { data() { return { imageSrc: 'https://example.com/image.png' } } } </script> 简写::src="imageSrc"v-on:绑定事件监听器。<template> <button v-on:click="handleClick">Click me</button> </template> <script>export default { methods: { handleClick() { alert('Button clicked!'); } } } </script> 简写:@click="handleClick"v-model:双向绑定表单元素。<template> <input v-model="inputValue" placeholder="Type something..."> <p>You typed: {{ inputValue }}</p> </template> <script>export default { data() { return { inputValue: '' } } } </script> v-if / v-else-if / v-else:条件渲染。<template> <div v-if="status === 'success'">Success!</div> <div v-else-if="status === 'pending'">Loading...</div> <div v-else>Error!</div> </template> <script>export default { data() { return { status: 'success' } } } </script> v-for:列表渲染。<template> <ul> <li v-for="(item, index) in items" :key="index">{{ item }}</li> </ul> </template> <script>export default { data() { return { items: ['Apple', 'Banana', 'Cherry'] } } } </script> 缩写v-bind 缩写为 :<a :href="url">Link</a> v-on 缩写为 @<button @click="doSomething">Click me</button> 计算属性和侦听器计算属性:用于声明式地计算属性值。computed: { reversedMessage() { return this.message.split('').reverse().join(''); } } 侦听器(Watchers):用于对数据变化做出反应。watch: { message(newValue, oldValue) { console.log(`Message changed from ${oldValue} to ${newValue}`); } } 这些基本语法构成了 Vue 3 模板语言的基础,它们能够让开发者把 JavaScript 对象的状态直接映射为用户界面。这种方式大大简化了动态内容更新的逻辑。