做外贸收费的网站,关键词异地排名查询,合肥瑶海区有什么大学,网站挂百度推广一、Vue 3 概述
1. 为什么要学习Vue 3
Vue 3是Vue.js的最新主要版本#xff0c;它带来了许多改进和新特性#xff0c;包括但不限于#xff1a;
性能提升#xff1a;Vue 3提供了更快的渲染速度和更低的内存使用率。Composition API#xff1a;引入了一个新的API#xf…一、Vue 3 概述
1. 为什么要学习Vue 3
Vue 3是Vue.js的最新主要版本它带来了许多改进和新特性包括但不限于
性能提升Vue 3提供了更快的渲染速度和更低的内存使用率。Composition API引入了一个新的API允许更灵活的代码组织和复用特别适合构建大型应用。更好的TypeScript支持Vue 3从头开始就考虑了TypeScript的支持使得使用TypeScript开发Vue应用更加顺畅。更小的体积通过优化和树摇tree-shakingVue 3的体积更小使得加载时间更短。
学习Vue 3可以让你利用最新的Web开发技术构建高效、可维护的前端应用。
2. Vue 3的新变化
Vue 3带来了很多重要的新变化包括
Composition API提供了一种新的方式来组织组件的逻辑使得功能更容易被提取和复用。响应式系统的重写使用Proxy对象重写了响应性系统提高了性能并减少了内存占用。片段Fragments组件可以有多个根节点而不再限于单一根节点。Teleport组件允许将子节点渲染到DOM树的其他位置。Suspense组件提供了一种新的方式来处理异步组件的加载状态。
3. 破坏性语法的更新
Vue 3也引入了一些破坏性更新以提高性能和开发体验比如
废除了一些不再推荐使用的API如Vue.extend、Vue.mixin等。EventBus的使用方式发生了变化推荐使用提供/注入provide/inject模式或是Vuex来进行全局状态管理。
接下来让我们用一个简单的示例开始Vue 3的旅程
!DOCTYPE html
html langen
head
meta charsetUTF-8
titleVue 3 Hello World/title
/head
body
div idapp{{ message }}/divscript srchttps://unpkg.com/vue3.4.0/script
scriptconst { createApp } Vue;createApp({data() {return {message: Hello Vue 3!}}}).mount(#app);
/script
/body
/html这个示例创建了一个最基本的Vue 3应用展示了如何使用createApp方法创建一个新的Vue应用并将其挂载到页面上的指定元素。
二、Vue 3 开发环境搭建
搭建Vue 3开发环境是开始学习和开发Vue 3应用的第一步。这一部分将引导你如何创建Vue 3项目并简要介绍项目结构的变化。
1. 创建Vue 3项目
Vue 3项目可以通过Vue CLI或Vite这两种方式创建。Vue CLI是Vue的官方命令行工具而Vite是一个现代化的前端构建工具提供了更快的开发服务器启动和热重载。
使用Vue CLI创建项目
首先确保你安装了最新版的Vue CLI。如果尚未安装可以通过npm安装
npm install -g vue/cli然后创建一个新的Vue 3项目
vue create my-vue-app在创建过程中CLI会让你选择预设配置。为了使用Vue 3你可以选择“Manually select features”来自定义功能确保选择了“Vue 3”选项。
使用Vite创建项目
Vite是一个建立在现代Web标准之上的新一代前端构建工具。使用Vite创建Vue 3项目可以获得极速的服务启动和模块热更新。安装Vite并创建一个新项目
npm init vitelatest my-vue-app -- --template vue接下来进入项目目录并安装依赖
cd my-vue-app
npm install2. 创建Vue 2和Vue 3项目的文件变化
Vue 3项目的文件结构在大体上保持了与Vue 2类似的结构但也有一些关键的变化和改进
main.jsVue 3使用createApp函数来创建一个Vue应用实例而Vue 2使用new Vue()构造函数。单文件组件.vue文件在Vue 3中script setup语法糖允许更简洁的组合式API代码使得组件的编写更加高效。
3. Vue 3中的App单文件不再强制要求必须有根元素
在Vue 2中每个单文件组件.vue文件必须有一个单独的根元素。而在Vue 3中这一限制被取消允许组件有多个根元素这为组件的布局提供了更大的灵活性。
示例代码创建Vue 3项目
以下是一个简单的Vue 3项目的main.js示例演示了如何使用createApp来创建一个Vue应用
import { createApp } from vue;
import App from ./App.vue;createApp(App).mount(#app);这里App.vue是根组件它可以是这样的
templatedivHello Vue 3!/divdivThis is a multi-root component!/div
/templatescript
export default {name: App
}
/script三、组合式APIComposition API和选项式APIOptions API
Vue 3引入了一个新的API——组合式APIComposition API这是一个重大的创新旨在解决在使用Vue 2中的选项式APIOptions API时遇到的一些限制尤其是在处理大型和复杂组件时。我们来看看这两种API的主要差异和它们的应用场景。
选项式APIOptions API
在Vue 2中我们主要通过选项式API来组织组件的代码比如data, methods, props, computed, watch等选项。这种方式很直观因为它将不同类型的组件选项分门别类地组织起来。
templatediv{{ fullName }}/div
/templatescript
export default {data() {return {firstName: Jane,lastName: Doe}},computed: {fullName() {return this.firstName this.lastName;}}
}
/script组合式APIComposition API
Vue 3的组合式API提供了一种更灵活的组织组件逻辑的方式。它通过setup()函数允许你将相关功能组织在一起而不是基于选项类型分开。这使得代码重用和逻辑提取变得更加简单尤其是在构建复杂组件时。
templatediv{{ fullName }}/div
/templatescript
import { ref, computed } from vue;export default {setup() {const firstName ref(Jane);const lastName ref(Doe);const fullName computed(() firstName.value lastName.value);return { fullName };}
}
/scriptAPI比较
代码组织组合式API使得按逻辑组织代码变得更加容易特别是在处理复杂组件时可以将相关的逻辑放在一起而不是分散在不同的选项中。类型推断组合式API提供了更好的TypeScript集成因为它能够利用TypeScript的类型推断使得在使用TypeScript开发Vue应用时更加顺畅。代码复用通过组合式API可以更容易地将组件逻辑抽取到可复用的函数中这对于保持代码的干净和维护性是非常有帮助的。
示例代码使用Composition API
templatebutton clickincrementCount is: {{ count }}/button
/templatescript
import { ref } from vue;export default {setup() {const count ref(0);function increment() {count.value;}return { count, increment };}
}
/script这个例子展示了如何使用ref来创建一个响应式的计数器以及如何将逻辑如增加计数组织在setup函数中。
组合式API和选项式API各有优势Vue 3提供了这两种API以便开发者可以根据具体项目和个人偏好选择最适合的方式。
四、组合式APIComposition API
Vue 3的组合式API是一组基于函数的API让你能够更灵活地组织和重用组件逻辑。通过组合式API你可以更容易地将组件逻辑按功能组织而不是分散在不同的Vue选项中。下面我们来详细看看组合式API的核心特性。
1. setup函数
setup函数是组合式API的入口点它在组件创建之前执行此时组件的props已经解析完成。你可以在这个函数里定义响应式状态、计算属性和函数然后返回它们使其在模板中可用。
示例代码
templatediv{{ message }}/div
/templatescript
import { ref } from vue;export default {setup() {const message ref(Hello Vue 3!);// 返回的对象中的属性和函数在模板中可用return { message };}
}
/script在这个例子中我们使用ref函数创建了一个响应式的数据message并在模板中使用它。
2. 生命周期钩子
在组合式API中你可以使用特定的函数来访问组件的生命周期钩子这些函数名称以on开头例如onMounted、onUpdated、onUnmounted等。
示例代码
script
import { onMounted, ref } from vue;export default {setup() {const count ref(0);onMounted(() {console.log(Component is mounted!);});return { count };}
}
/script这个例子展示了如何在组件挂载完成后使用onMounted生命周期钩子。
组合式API的优势在于它提供了更大的灵活性和逻辑复用的能力。使用setup函数你可以按照逻辑而不是选项类型来组织代码这在管理大型或复杂组件时特别有用。同时通过直接使用生命周期钩子的函数你可以更直接地控制组件的行为。
接下来我们将探讨组合式API中的响应式引用(ref)和响应式对象(reactive)这两个是组合式API中最常用的响应式状态管理工具。
五、响应式Ref函数
在Vue 3的组合式API中ref函数用于创建一个响应式的引用对象。这个对象内部有一个.value属性通过这个属性可以获取或设置该引用的值。ref是处理基本数据类型如字符串、数字、布尔值的响应式状态时非常有用的工具。
1. 不使用ref函数
在不使用ref的情况下如果你尝试直接在setup函数内使用基本类型的数据那么这些数据不会是响应式的。这意味着当数据变化时视图不会自动更新。
let count 0; // 这不是响应式的2. 使用ref函数
使用ref可以让基本数据类型变成响应式的。这是因为ref返回的是一个响应式对象我们通过操作这个对象的.value属性来读写实际的值。
示例代码
templatebutton clickincrementCount is: {{ count }}/button
/templatescript
import { ref } from vue;export default {setup() {const count ref(0);function increment() {count.value;}return { count, increment };}
}
/script在这个示例中count是通过ref创建的响应式引用。我们在模板中直接使用count而不是count.valueVue内部会自动处理这些引用。但是在JavaScript逻辑中我们通过count.value来读写这个值。
3. ref引用
ref不仅可以用于基本数据类型也可以用于引用类型数据如对象或数组。当用于引用类型时Vue会递归地将这些数据转换为响应式数据。
示例代码
script
import { ref } from vue;export default {setup() {const state ref({count: 0,message: Hello});function increment() {state.value.count;}return { state, increment };}
}
/script在这个例子中state是一个包含多个属性的对象。通过ref创建的响应式引用我们可以保持对这个对象内部属性的响应式更新。
通过使用refVue 3的组合式API使状态管理变得简单而直接无论是基本数据类型还是引用类型数据。ref是构建响应式数据的基础是理解和使用Vue 3必须掌握的概念之一。
接下来我们将讨论reactive函数它是另一个在Vue 3中管理响应式状态的重要工具特别适用于复杂的对象。
六、Reactive函数
在Vue 3的组合式API中除了ref之外reactive函数是另一个核心功能用于创建响应式的复杂数据结构如对象或数组。reactive提供了一种更自然的方式来处理对象和数组使其成为响应式数据而无需使用.value属性进行访问。
使用reactive函数
reactive接收一个普通对象并返回该对象的响应式代理。与ref不同当你修改使用reactive创建的对象的属性时不需要使用.value。
示例代码
templatediv{{ state.count }}/divbutton clickincrementIncrement/button
/templatescript
import { reactive } from vue;export default {setup() {const state reactive({count: 0});function increment() {state.count;}return { state, increment };}
}
/script在这个例子中我们创建了一个响应式对象state并在模板中直接使用了它的属性。这比使用ref更加直接尤其是在处理复杂对象时。
对比ref和reactive
基本类型ref适用于基本数据类型可以通过.value进行读写。reactive不能直接用于基本数据类型。引用类型reactive直接作用于对象或数组使其成为响应式。对于复杂的数据结构reactive比ref更加适用。模板中的使用无论是ref还是reactive创建的响应式数据都可以直接在模板中使用Vue 会自动处理。
深度响应式和浅响应式
默认情况下reactive会递归地把一个对象内部的所有属性都转换为响应式数据。浅响应式如果你不希望对象内部的所有属性都是响应式的可以使用shallowReactive函数它只会使最外层的属性成为响应式而不会影响嵌套对象。
import { shallowReactive } from vue;const state shallowReactive({innerObject: { count: 0 }
});
// state是响应式的但state.innerObject不是响应式的。reactive和ref是Vue 3中组合式API的两大支柱理解它们之间的差异以及如何选择使用它们对于高效开发Vue 3应用至关重要。
接下来我们将讨论toRefs函数它允许我们从reactive对象中提取出多个响应式引用以保持结构分解赋值的响应性。
七、toRefs函数
在Vue 3的组合式API中toRefs函数用于将reactive对象转换为一个普通对象其中每个属性都是一个ref这对于保持响应式状态在结构分解赋值destructuring时特别有用。
为什么需要toRefs
当你从reactive对象中结构出属性时这些属性会失去响应性。这是因为结构赋值是基于值的拷贝所以拷贝出来的值不会和原始的reactive对象保持响应连接。toRefs可以解决这个问题它允许你在结构分解时保持属性的响应性。
示例代码
假设我们有一个reactive对象
import { reactive, toRefs } from vue;export default {setup() {const state reactive({count: 0,message: Hello Vue 3});// 尝试直接结构会导致失去响应性// let { count, message } state;// 使用toRefs来保持响应性let { count, message } toRefs(state);return { count, message };}
}如何使用toRefs
toRefs接收一个响应式对象并返回一个新的对象。返回的对象中的每个属性都是一个指向原始对象相应属性的ref。
templatediv{{ count }}/divdiv{{ message }}/div
/template在模板中你可以直接使用count和message就像它们是使用ref创建的响应式引用一样。这保证了即使在结构分解后你依然可以保持组件的响应性。
toRefs与ref
toRefs适用于将reactive对象转换成一个包含多个ref属性的普通对象每个ref都是响应式的。ref用于创建单个响应式数据。
使用toRefs可以非常方便地在保持响应性的同时使用JavaScript的结构分解功能这对于在多个地方使用或传递reactive对象的部分属性时非常有用。
到目前为止我们已经讨论了Vue 3的组合式API中的基本响应式API——ref、reactive和toRefs。这些工具为开发复杂组件提供了灵活性和强大的状态管理能力。
接下来我们将进一步探讨Vue 3中的计算属性computed和侦听器watch。这些功能使得我们可以更细致地控制响应式状态的变化和更新。
八、Computed计算属性
在Vue 3中计算属性(computed)是一种基于响应式依赖进行缓存的计算值。当计算属性依赖的响应式状态发生变化时计算属性会重新计算。这非常适合用于执行开销较大的计算操作或派生状态。
1. 基本用法
使用computed函数可以创建一个计算属性。computed接收一个函数作为参数这个函数的返回值就是计算属性的值。当依赖的响应式状态改变时这个函数会被重新执行。
示例代码
templatediv{{ fullName }}/div
/templatescript
import { reactive, computed } from vue;export default {setup() {const person reactive({firstName: John,lastName: Doe});const fullName computed(() {return ${person.firstName} ${person.lastName};});return { fullName };}
}
/script在这个例子中fullName是一个计算属性它依赖于reactive对象person的firstName和lastName。当person的属性改变时fullName会自动更新。
2. 高级用法
computed也支持一个带有get和set函数的对象允许你创建可写的计算属性。这在需要执行额外逻辑来处理更新操作时非常有用。
示例代码
templatediv{{ fullName }}/divbutton clickchangeNameChange Name/button
/templatescript
import { reactive, computed } from vue;export default {setup() {const person reactive({firstName: John,lastName: Doe});const fullName computed({get() {return ${person.firstName} ${person.lastName};},set(newValue) {const names newValue.split( );person.firstName names[0];person.lastName names[1] || ;}});function changeName() {fullName.value Jane Doe;}return { fullName, changeName };}
}
/script在这个高级用法中我们定义了一个可写的计算属性fullName。当尝试设置fullName.value时设置函数(setter)会被调用允许我们将一个新值分解并赋值给person.firstName和person.lastName。
计算属性是Vue响应系统的重要部分它使得管理复杂逻辑和依赖变得简单高效。
接下来我们将探讨Vue 3中的侦听器(watch和watchEffect)它们提供了一种方法来响应数据的变化。
九、Watch监听
Vue 3的组合式API提供了watch和watchEffect两种方式来侦听响应式数据的变化并执行相应的副作用。这两种API都非常强大可以用于执行数据变化时的异步操作、资源清理或复杂的业务逻辑。
1. 单个数据监听 - watch
watch函数用于侦听单个或多个响应式引用(ref)或响应式对象(reactive)的属性并在它们变化时执行回调函数。watch的回调函数接收新值和旧值作为参数。
示例代码
templatediv{{ count }}/divbutton clickincrementIncrement/button
/templatescript
import { ref, watch } from vue;export default {setup() {const count ref(0);watch(count, (newValue, oldValue) {console.log(count changed from ${oldValue} to ${newValue});});function increment() {count.value;}return { count, increment };}
}
/script在这个例子中每当count的值变化时我们都会在控制台打印出一条消息。
2. 多个数据监听
watch也可以同时侦听多个数据源。你需要将它们放在一个数组里并在回调函数中接收一个数组形式的新值和旧值。
watch([ref1, ref2], ([newVal1, newVal2], [oldVal1, oldVal2]) {// 响应变化
});3. 复杂数据类型监听
对于复杂数据类型如使用reactive创建的响应式对象你可能希望在嵌套属性变化时也能触发侦听器。这时可以直接将响应式对象传递给watchVue会进行深度监听。
4. 监听复杂数据类型中的属性
如果你只想监听响应式对象的某个属性可以使用一个函数来返回这个属性的值。
watch(() state.someNestedProperty,(newValue, oldValue) {// 响应变化}
);5. 开启深度监听
使用watch侦听响应式对象时默认情况下不会深度侦听。如果需要深度侦听可以通过传递一个配置对象将deep属性设置为true。
watch(state,(newValue, oldValue) {// 深度响应变化},{ deep: true }
);watchEffect的使用
watchEffect函数会立即执行传递给它的回调函数并响应式地追踪回调函数中使用的任何响应式状态的变化。当依赖的响应式状态发生变化时watchEffect会再次执行。
script
import { ref, watchEffect } from vue;export default {setup() {const count ref(0);watchEffect(() console.log(count.value));return { count };}
}
/scriptwatch和watchEffect提供了灵活且强大的方式来对响应式数据的变化作出反应它们是Vue组合式API中不可或缺的一部分。
接下来如果你准备好了我们可以讨论Vue 3中组件之间的通信包括父子通信和提供/注入机制。
十、父子通信
在Vue 3中组件之间的通信是构建应用时的关键部分。Vue 提供了多种方式来实现不同场景下的组件通信包括但不限于props、自定义事件、提供/注入机制等。我们首先讨论最常见的父子通信方式。
1. 父传子 - Props
Props是父组件向子组件传递数据的主要方式。子组件需要显式声明它期望接收的props。
子组件ChildComponent.vue:
!-- 子组件 --
templatediv{{ parentMessage }}/div
/templatescript setup
const props defineProps({parentMessage: String
});
/script!-- 父组件 --
templatedivChildComponent :parentMessagemessage //div
/templatescript setup
import { ref } from vue;
import ChildComponent from ./ChildComponent.vue;const message ref(Hello from parent);
/script
在这个例子中父组件通过messageprop向ChildComponent传递了一个字符串。
2. 子传父 - 自定义事件
子组件可以通过触发事件来向父组件传递信息。Vue 3中使用$emit方法触发事件已被废弃推荐使用defineEmits或context.emit。
子组件ChildComponent.vue:
templatebutton clicknotifyParentClick Me/button
/templatescript
import { defineEmits } from vue;export default {setup() {const emit defineEmits([custom-event]);function notifyParent() {emit(custom-event, Some data);}return { notifyParent };}
}
/script父组件:
templateChildComponent custom-eventhandleCustomEvent /
/templatescript
import ChildComponent from ./ChildComponent.vue;export default {components: {ChildComponent},methods: {handleCustomEvent(data) {console.log(data); // 输出: Some data}}
}
/script在这个例子中子组件通过触发custom-event事件并传递数据来与父组件通信。父组件监听这个事件并定义了一个处理函数handleCustomEvent来接收数据。
这两种方法是Vue中实现父子通信的基础。通过Props父组件可以向子组件传递数据而通过自定义事件子组件可以向父组件发送消息。
Vue还提供了更高级的通信方式如提供/注入机制它允许祖先组件向所有子孙组件传递数据而无需通过每一层的props来显式传递。
十一、Vue 3中的指令变化
Vue 3引入了一些新指令并更新了一些现有指令的用法以提高开发效率和应用性能。这里我们重点讨论v-model和v-if系列指令的变化。
1. v-model的变化
在Vue 2中v-model主要用于在表单控件和应用状态之间创建双向数据绑定。Vue 3扩展了v-model的用法允许在自定义组件上使用多个v-model绑定。
Vue 2用法:
input v-modelmessage /Vue 3用法:
Vue 3允许自定义组件上使用多个v-model
CustomComponent v-model:titlepageTitle v-model:contentpageContent /在自定义组件内部可以通过defineProps来接收这些属性
script setup
const props defineProps({title: String,content: String
});
/script并使用emit来更新这些属性
const emit defineEmits([update:title, update:content]);2. v-if、v-else-if、v-else的使用
这一系列的指令在Vue 3中保持不变用于条件渲染。v-if和v-else-if需要跟一个表达式v-else不需要。这三个指令必须紧跟在彼此后面使用。
templatediv v-iftype AA/divdiv v-else-iftype BB/divdiv v-elseC/div
/template这些更新和变化反映了Vue 3在灵活性和功能性方面的提升使得开发者能够更有效地构建复杂且高性能的应用。
Vue 3还引入了其他的新特性和API改进包括Teleport、Suspense以及对Composition API的进一步增强。
十二、Vue 3中的TypeScript支持
Vue 3从一开始就把TypeScript支持作为其核心特性之一。这意味着Vue 3不仅能够提供更好的类型推断和代码智能提示而且还能让开发者利用TypeScript的全部功能来构建应用。这种一流的TypeScript支持为开发大型应用和提高代码质量带来了巨大的好处。
类型增强
Vue 3利用Composition API提供了更好的类型推断。当你使用ref、reactive等API时Vue 3能够准确地推断出相应的类型这使得在使用TypeScript开发应用时能够获得更为准确的代码提示和类型检查。
示例代码
script langts
import { defineComponent, ref, Ref } from vue;export default defineComponent({setup() {const count: Refnumber ref(0); // count被推断为一个数字类型的响应式引用function increment() {count.value;}return { count, increment };}
});
/script在这个例子中我们明确声明了count是一个数字类型的响应式引用(Refnumber)。这种类型声明让TypeScript能够提供准确的类型检查和代码提示。
使用defineComponent进行类型推断
Vue 3推荐使用defineComponent函数来定义组件这不仅使得组件支持TypeScript而且还能提供更好的类型推断和组件选项的类型检查。
script langts
import { defineComponent } from vue;export default defineComponent({props: {message: String},setup(props) {console.log(props.message); // props.message被正确推断为string}
});
/script通过defineComponentVue 3可以准确地推断props、data、computed等选项的类型大大提高了开发体验。
十三 Suspense
Vue 3引入的Suspense组件是一个用于处理异步组件加载和异步数据的特殊内置组件。它提供了一种新的方式来处理在等待异步操作完成时的UI渲染特别适用于控制如数据获取、异步组件或其依赖加载等场景的用户体验。
工作原理
当一个组件需要进行异步操作比如数据请求或异步导入另一个组件时Suspense允许你定义一个“备用”内容例如加载指示器在异步操作完成之前显示。这意味着你可以提供一个平滑的用户体验避免在数据加载时显示一个空白或不完整的页面。
基本用法
Suspense通过两个插槽来工作
default 插槽包含异步加载的组件。fallback 插槽在等待异步操作完成时显示的内容。
templateSuspensetemplate #defaultAsyncComponent //templatetemplate #fallbackdivLoading.../div/template/Suspense
/templatescript
import { defineAsyncComponent } from vue;export default {components: {AsyncComponent: defineAsyncComponent(() import(./components/AsyncComponent.vue))}
}
/script在这个例子中AsyncComponent是通过defineAsyncComponent定义的一个异步组件。在AsyncComponent加载过程中用户会看到“Loading…”信息。一旦组件加载完成Suspense将渲染该组件替换掉加载提示。
高级场景
Suspense也支持更复杂的使用场景比如在组件内部进行异步数据获取。这通常通过组合式API中的async setup()函数实现。
templateSuspensetemplate #defaultdiv{{ data }}/div/templatetemplate #fallbackdivLoading.../div/template/Suspense
/templatescript
import { defineComponent } from vue;
import { fetchData } from ./api; // 假设的API请求函数export default defineComponent({async setup() {const data await fetchData();return { data };}
});
/script在这个场景中组件利用async setup()函数来获取数据。在数据未到达之前用户将看到“Loading…”提示。
虽然Suspense和骨架屏都是提升加载体验的手段但Suspense更多的是从组件和逻辑层面提供支持而骨架屏更侧重于视觉和用户感知层面。在实际应用中二者可以结合使用即在Suspense的fallback插槽中使用骨架屏提供更加丰富和直观的加载状态反馈进一步提升用户体验。