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

Vue3学习总结

一、Vue 3 基础搭建与核心语法

1.创建 Vue 3 应用

在项目的入口文件 main.js 中,通过以下代码创建 Vue 3 应用实例:

import { createApp } from 'vue';
import App from './App.vue';const app = createApp(App);
app.mount('#app');

 这几行代码的作用是引入 createApp 函数,创建一个应用实例,并将 App.vue 挂载到页面上指定的 #app 元素。

2.组合式 API

Vue 3 引入了 组合式 API(Composition API),提供了更灵活的逻辑复用方式。

  • 组合逻辑:Composition API 提供了一种新的方式来组织和复用逻辑代码。它允许开发者以函数的形式定义组件的逻辑,而不是像 Options API 那样分散在 datamethodscomputed 等选项中。
  • 生命周期钩子:如 onMountedonUnmounted 等等,与 Options API 中的生命周期钩子相对应,但更灵活,可以自由组合。
  • setup:组件的入口函数,用于定义响应式数据、计算属性、方法等。

<script setup>
import { ref, onMounted } from 'vue';const message = ref('Hello World');onMounted(() => {console.log('Component is mounted!');
});
</script><template><p>{{ message }}</p>
</template>
import { ref, onMounted } from 'vue';export default {setup() {const count = ref(0);onMounted(() => {console.log('Component mounted');});return {count,};},
};

3.<script setup> 语法

<script setup> 是 Vue 3 提供的重要语法糖,极大地简化了组件的代码结构。在该语法下,模块顶层的代码会自动编译到 setup() 函数中,无需显式定义 setup 函数。

二、响应式原理与数据处理

Vue 3 使用 Proxy 实现响应式系统,Vue 3 使用 Proxy 替代了 Vue 的 Object.defineProperty,实现了更强大的响应式系统。

1.ref 和 reactive

  • ref 和 reactiveref 用于创建简单的响应式引用,而 reactive 则用来处理对象。对于数组和对象,建议使用 reactive
  • .value 访问器:当使用 ref 创建的响应式引用时,需要通过 .value 来读取或设置其内部值。
<script setup>
import { ref, reactive } from 'vue';// 使用 ref 创建基本类型响应式变量
const count = ref(0);// 使用 reactive 创建复杂类型的响应式对象
const state = reactive({name: 'Vue',version: 3,
});function increment() {count.value++;
}
</script><template><div><p>Count is {{ count }}</p><button @click="increment">Increment</button><p>Name is {{ state.name }}, Version is {{ state.version }}</p></div>
</template>

2.toRefs

toRefs 函数用于将一个响应式对象转换为普通对象,其中每个属性都转换为一个 ref,这样在解构响应式对象时能够保持其响应性。

<template><div><p>姓名: {{ name }}</p><p>年龄: {{ age }}</p></div>
</template><script setup>
import { reactive, toRefs } from 'vue';const person = reactive({name: '王五',age: 30
});const { name, age } = toRefs(person);
</script>

三、组件化开发

1.组件定义与使用

Vue 3 使用 .vue 文件来定义组件,包含 <template><script> 和 <style> 三个部分。

<template><div><p>{{ message }}</p><button @click="increment">Increment</button></div>
</template><script>
import { ref } from 'vue';export default {setup() {const message = ref('Hello, Vue 3!');const increment = () => {message.value += '!';};return {message,increment,};},
};
</script><style scoped>
p {color: blue;
}
</style>

使用 <script setup> 定义组件十分便捷,只需在 <script setup> 标签内编写逻辑代码,在 <template> 标签内编写模板内容。

// 子组件 Child.vue
<template><div><p>这是一个子组件</p></div>
</template><script setup>
// 这里可以定义子组件的逻辑
</script>

在父组件中使用子组件时,先导入子组件,然后在模板中直接使用子组件标签即可。

// 父组件 Parent.vue
<template><div><Child /></div>
</template><script setup>
import Child from './Child.vue';
</script>

2.组件通信

  • Props:父组件向子组件传递数据。

  • 事件:子组件向父组件传递数据。

父传子

通过 props 实现父组件向子组件传递数据。

// 父组件 Parent.vue
<template><div><ChildComponent :message="parentMessage" /></div>
</template><script setup>
import ChildComponent from './ChildComponent.vue';
const parentMessage = '父组件传递的信息';
</script>
// 子组件 ChildComponent.vue
<template><div><p>{{ message }}</p></div>
</template><script setup>
const props = defineProps(['message']);
</script>
子传父

子组件通过 emit 触发事件向父组件传递数据。

// 子组件 Child.vue
<template><div><button @click="sendDataToParent">传递数据给父组件</button></div>
</template><script setup>
import { defineEmits } from 'vue';const emits = defineEmits(['dataFromChild']);
const sendDataToParent = () => {emits('dataFromChild', '子组件的数据');
};
</script>
// 父组件 Parent.vue
<template><div><Child @dataFromChild="handleDataFromChild" /></div>
</template><script setup>
import Child from './Child.vue';const handleDataFromChild = (data) => {console.log('接收到子组件的数据:', data);
};
</script>
兄弟组件通信

兄弟组件通信通常借助事件总线或状态管理库(如 Pinia)来实现。事件总线可以通过创建一个空的 Vue 实例来作为事件中心,兄弟组件通过这个实例来触发和监听事件。使用 Pinia 时,将共享的数据存储在 Pinia 的 store 中,兄弟组件都可以访问和修改这个 store 中的数据。

 3.插槽

匿名插槽

父组件可以在子组件标签内插入内容,子组件通过 <slot> 标签渲染这些内容。

// 父组件 Parent.vue
<template><div><ChildComponent><p>这是插入到子组件的匿名插槽内容</p></ChildComponent></div>
</template><script setup>
import ChildComponent from './ChildComponent.vue';
</script>
// 子组件 ChildComponent.vue
<template><div><slot></slot></div>
</template><script setup>
</script>
具名插槽

父组件可以通过 template 标签和 #name 语法指定插槽名称,子组件通过 <slot name="xxx"> 渲染对应的内容。

// 父组件 Parent.vue
<template><div><ChildComponent><template #header><h1>这是头部插槽内容</h1></template><template #content><p>这是内容插槽内容</p></template></ChildComponent></div>
</template><script setup>
import ChildComponent from './ChildComponent.vue';
</script>
// 子组件 ChildComponent.vue
<template><div><slot name="header"></slot><slot name="content"></slot></div>
</template><script setup>
</script>

四、生命周期管理

 在 <script setup> 中,可以方便地使用各种生命周期钩子函数,这些钩子函数在组件的不同阶段被调用。

<template><div><p>组件内容</p></div>
</template><script setup>
import { onMounted, onUpdated, onUnmounted } from 'vue';onMounted(() => {console.log('组件已挂载');
});onUpdated(() => {console.log('组件已更新');
});onUnmounted(() => {console.log('组件已卸载');
});
</script>

onMounted 在组件挂载完成后调用,可用于初始化数据、获取 DOM 元素等操作;onUpdated 在组件更新后调用,可用于在数据更新后执行一些额外的逻辑;onUnmounted 在组件卸载时调用,可用于清理定时器、解绑事件等操作。

五、计算属性与监听器

1.计算属性

计算属性是基于响应式数据的缓存值,只有当它所依赖的响应式数据发生变化时才会重新计算。

<template><div><p>原始数字: {{ number }}</p><p>加倍后的数字: {{ doubleNumber }}</p></div>
</template><script setup>
import { ref, computed } from 'vue';const number = ref(10);
const doubleNumber = computed(() => number.value * 2);
</script>

在这个例子中,doubleNumber 是一个计算属性,依赖于 number 的值。当 number 变化时,doubleNumber 会自动重新计算。

2.监听器

监听器用于监听响应式数据的变化,并在数据变化时执行相应的操作。

<template><div><input v-model="inputValue" /></div>
</template><script setup>
import { ref, watch } from 'vue';const inputValue = ref('');
watch(inputValue, (newValue, oldValue) => {console.log('新值:', newValue, '旧值:', oldValue);
});
</script>

上述代码中,通过 watch 监听 inputValue 的变化,当 inputValue 改变时,会在控制台打印出新值和旧值。

六、指令系统

1.内置指令

v-model

v-model 用于表单元素的双向数据绑定,使得表单元素的值与响应式数据保持同步。

<template><div><input v-model="inputText" /><p>输入的内容: {{ inputText }}</p></div>
</template><script setup>
import { ref } from 'vue';const inputText = ref('');
</script>
v-if、v-else、v-else-if

这些指令用于条件渲染,根据表达式的真假来决定是否渲染相应的内容。

<template><div><p v-if="isShow">显示的内容</p><p v-else>不显示的内容</p></div>
</template><script setup>
import { ref } from 'vue';const isShow = ref(true);
</script>
v-for

v-for 用于列表渲染,通过遍历数组或对象来渲染多个元素。

<template><div><ul><li v-for="(item, index) in list" :key="index">{{ item }}</li></ul></div>
</template><script setup>
import { ref } from 'vue';const list = ref(['苹果', '香蕉', '橙子']);
</script>
v-bind

v-bind 可以缩写为 :,用于动态绑定 HTML 属性,使属性值根据响应式数据的变化而变化。

<template><div><img :src="imageUrl" :alt="imageAlt" /></div>
</template><script setup>
import { ref } from 'vue';const imageUrl = ref('path/to/image.jpg');
const imageAlt = ref('描述图片');
</script>
v-on

v-on 可以缩写为 @,用于绑定事件监听器,当事件触发时执行相应的函数。

<template><div><button @click="handleClick">点击我</button></div>
</template><script setup>
const handleClick = () => {console.log('按钮被点击了');
};
</script>

2.自定义指令

自定义指令可以扩展 Vue 的功能,通过 directive 函数来定义。

<template><div><input v-focus /></div>
</template><script setup>
import { directive } from 'vue';const vFocus = directive('focus', {mounted(el) {el.focus();}
});
</script>

上述代码定义了一个自定义指令 v-focus,当组件挂载时,会自动将焦点设置在使用该指令的输入框上。

七、状态管理(Pinia)

Vue 3 推荐使用 Pinia 作为状态管理库。

1.安装与引入

首先通过 npm install pinia 安装 Pinia,然后在 main.js 中引入并使用:

import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';const pinia = createPinia();
const app = createApp(App);
app.use(pinia);
app.mount('#app');

2.创建 Store

使用 defineStore 函数定义一个 store,用于存储和管理应用的状态。

// store/counter.js
import { defineStore } from 'pinia';export const useCounterStore = defineStore('counter', {state: () => ({count: 0}),actions: {increment() {this.count++;}}
});

3.在组件中使用 Store

在组件中通过 useCounterStore 函数来访问和使用 store 中的状态和方法。

<template><div><p>计数器: {{ counterStore.count }}</p><button @click="counterStore.increment">增加</button></div>
</template><script setup>
import { useCounterStore } from './store/counter.js';const counterStore = useCounterStore();
</script>

八、路由管理(Vue Router)

1.安装与配置

通过 npm install vue-router 安装 Vue Router,然后在 router/index.js 中配置路由:

import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'const router = createRouter({// 配置使用history模式history: createWebHistory(import.meta.env.BASE_URL),// 定义路由规则routes: [{path: '/', // 路由名称name: 'home',component: HomeView // 同步组件},{path: '/about',name: 'about',// route level code-splitting// this generates a separate chunk (About.[hash].js) for this route// which is lazy-loaded when the route is visited.component: () => import('../views/AboutView.vue') // 异步组件}]
})export default router

2.动态路由和嵌套路由

  • 动态路由:通过 :id 定义动态路径参数。

  • 嵌套路由:通过 children 定义嵌套路由。

const routes = [{path: '/user/:id',component: User,children: [{ path: 'profile', component: Profile },{ path: 'posts', component: Posts },],},
];

3.在 main.js 中引入路由

在 main.js 中引入配置好的路由:

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'const app = createApp(App)app.use(router)app.mount('#app')

3.在组件中使用路由

在组件中可以使用 router-link 来创建导航链接,使用 router-view 来显示当前路由对应的组件。

<script setup>
// RouterLink是一个组件
// RouterView也是一个组件
import { RouterLink, RouterView } from 'vue-router'
</script><template><!-- 配置路由出口 --><nav><router-link to="/">Home</router-link><router-link to="/about">About</router-link></nav><main><router-view></router-view></main>
</template><style scoped>
nav {display: flex;width: 200px;
}
nav a {flex: 1;
}
main {width: 400px;height: 200px;border: 1px solid #ccc;
}
</style>

九、性能优化

1 懒加载

  • 组件懒加载:使用 defineAsyncComponent 或 import() 动态加载组件。

  • 路由懒加载:使用 import() 动态加载路由组件。

const Home = defineAsyncComponent(() => import('./views/Home.vue'));

2 代码拆分 

  • 使用 Webpack 或 Vite 的代码拆分功能,将代码分割成多个 chunk。

3 缓存组件

  • 使用 <keep-alive> 缓存组件状态,避免重复渲染。

<keep-alive><router-view />
</keep-alive>

4.Teleport

  • 传送内容到DOM的不同位置:允许你把组件的内容“传送”到应用程序中的任意位置,而不受组件层级结构的限制。这对于模态框、提示信息等场景特别有用。
<teleport to="body"><!-- 这里的内容会被插入到 body 元素中 --><div id="modal">...</div>
</teleport>

5.Transition 组件增强

TransitionGroup 和 Transition:提供了更强大的过渡效果控制,包括列表动画等功能。

6. Suspense

  • 异步组件加载:允许你在等待异步依赖(如从服务器获取数据)时展示占位符内容,直到所需资源准备好为止。
<suspense><template #default><AsyncComponent /></template><template #fallback>Loading...</template>
</suspense>

十、最佳实践

1 组件设计

  • 单一职责:每个组件只负责一个功能。

  • Props 验证:使用 props 的 type 和 validator 进行数据验证。

export default {props: {message: {type: String,required: true,validator: (value) => value.length > 0,},},
};

2 代码风格

  • 使用组合式 API 组织逻辑。

  • 使用 ref 和 reactive 定义响应式数据。

  • 使用 computed 和 watch 处理复杂逻辑。

3 错误处理

  • 使用 try...catch 捕获异步错误。

  • 使用全局错误处理函数捕获未处理的异常。

app.config.errorHandler = (err, vm, info) => {console.error('Global error:', err);
};

十一、 工具链

1 Vite

Vite 是 Vue 3 的推荐构建工具,支持快速开发和热更新。

2 Vue DevTools

Vue DevTools 是浏览器扩展,用于调试 Vue 应用。

十二、测试

1 单元测试

使用 Jest 或 Vitest 进行单元测试。

import { mount } from '@vue/test-utils';
import MyComponent from './MyComponent.vue';test('renders correctly', () => {const wrapper = mount(MyComponent);expect(wrapper.text()).toContain('Hello, Vue 3!');
});

2 端到端测试

使用 Cypress 进行端到端测试。

describe('MyComponent', () => {it('renders correctly', () => {cy.visit('/');cy.contains('Hello, Vue 3!');});
});

十三、TypeScript 支持

  • 内置对 TypeScript 的友好支持:包括类型推断、类型检查以及更好的开发体验。Composition API 特别适合 TypeScript,因为它提供了更明确的类型定义。
<template><p>{{ message }}</p>
</template><script setup lang="ts">
import { ref } from 'vue';const message = ref<string>('Hello, Vue 3 with TypeScript!');
</script>


http://www.mrgr.cn/news/83474.html

相关文章:

  • 线程与互斥锁
  • 【HarmonyOS Next NAPI 深度探索1】Node.js 和 CC++ 原生扩展简介
  • 不同音频振幅dBFS计算方法
  • PyTorch 装饰器 @torch.jit.ignore 介绍
  • Leetcode 967 Numbers With Same Consecutive Differences
  • 记一次sealos部署k8s集群之delete了第一台master如何恢复
  • Liunx-搭建安装VSOMEIP环境教程 执行 运行VSOMEIP示例demo
  • 李宏毅机器学习课程笔记02 | 机器学习任务攻略General Guide
  • week06_预训练语言模型—BERT
  • Android车机DIY开发之软件篇(八)单独编译
  • 全面教程:Nacos 2.3.2 启用鉴权与 MySQL 数据存储配置
  • Tkinter组件-Button按键
  • 《ROS2 机器人开发 从入门道实践》 鱼香ROS2——第6章内容
  • Windows 下Mamba2 / Vim / Vmamba 环境安装问题记录及解决方法终极版(无需绕过triton)
  • 攻防靶场(34):隐蔽的计划任务提权 Funbox1
  • 【云计算】OpenStack云计算平台
  • Qt 5.14.2 学习记录 —— 십일 QLCDNumber、ProgressBar、QCalendarWidget
  • 前端开发:Web前端和HTML
  • C++之函数提高
  • 国产编辑器EverEdit - 扩展脚本:新建同类型文件(避免编程学习者反复新建保存练习文件)
  • C语言 操作符_位操作符、赋值操作符、单目操作符
  • 仓颉笔记——写一个简易的web服务并用浏览器打开
  • 代码随想录算法训练营第3天(链表1)| 203.移除链表元素 707.设计链表 206.反转链表
  • 卷积神经02-CUDA+Pytorch环境安装
  • 初识 Git——《Pro Git》
  • 哈希表及模拟实现