Vue.js (一) 项目创建与基本概念
Vue 是一个渐进式现代 JavaScript 框架,用于构建用户界面( UI )。它的目标是通过尽可能简单的 Api 实现响应式数据绑定和组合的视图集合( 组件 )
Vue 的核心只关注视图层,如果需要其它高级功能可以逐步引入( 如 路由、状态管理 等 )
Vue 起源于开源项目,由前 Google 员工尤雨溪开发并维护,它在开源社区中极具人气,尤其在亚洲地区广泛流行
MVVM 架构
MVVM 是一种软件架构模式,它将应用程序分成三层:模型(Model)、视图(View)、视图模型(ViewModel)
Vue.js 参照了 MVVM 架构的思想设计
模型(Model)
- 代表应用程序的数据和业务逻辑
- 它是应用的核心部分,包含了所有的数据处理、验证以及对数据的操作
视图(View)
- 代表应用程序的用户界面( UI )。它呈现模型中的数据给用户,并通过用户交互反馈数据的变化
- 在 Web前端中,通常由 HTML、CSS 组成,用于表示界面的结构和样式
视图模型(ViewModel)
- 连接模型( Model )和视图( View )。它是一个中间层,负责处理视图和模型之间的双向数据绑定
- 将模型中的数据转换成视图可识别的格式( HTML DOM ),并将视图的操作反馈给模型
创建 Vue 工程项目
确保你的机器上安装了 Node.js,之后我们使用 Vite 脚手架来创建项目,它会帮我们生成项目所需的依赖,以及构建工具相关的配置等…
1 | npm create vite |
npm create
命令:
npm create
命令是用来运行远程的项目生成器( 脚手架 )的命令
它会自动下载并执行远程的 create-<package-name>
命名的包来创建一个项目
Vue 项目结构:
1 | my-vue-app/ |
Vue 的基本概念
响应式
响应式是 Vue 中的一种机制,指的是当数据发生变化时,Vue 会自动检测到这个变化并更新相关的视图。这种自动的同步更新被称为“响应式系统”。Vue 的响应式系统主要依赖于“依赖追踪”和“数据劫持”技术
组件化
组件化指的是将应用程序拆分为多个独立的、可复用的模块(组件),每个模块负责特定的功能或界面部分。组件化开发能够提升代码的组织性、复用性和可维护性,尤其适合开发大型的前端应用
在 Vue 中组件可以用 .vue
文件( 单文件组件SFC )表示,每个组件都封装了自己独立的模板、逻辑(如数据和方法)、以及样式。它包含以下三个部分:
- template:定义了组件的 HTML 结构
- script:定义了组件的逻辑,包括数据、方法、生命周期钩子等
- style:定义了组件的样式
例:
1 | <!-- src/components/CountBtn.vue 计数器按钮组件 --> |
1 | <!-- src/App.vue 根组件 --> |
1 | /* src/main.js 应用程序的入口文件 */ |
组件命名:
kebab-case命名: school / my-school
CamelCase命名: School / MySchool
组件名不能用 HTML 已有元素的名称
注册组件:
局部注册
局部注册的组件只在指定的 Vue 实例或组件中可用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17<!-- Header组件 -->
<template>
<div class="header">Header组件</div>
</template>
<!-- scoped 局部CSS样式 -->
<style scoped>
.header {
width: 100%;
height: 75px;
box-sizing: border-box;
border: 10px solid black;
font-size: 23px;
text-align: center;
line-height: 55px;
}
</style>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16<template>
<!-- 使用Header组件 -->
<Header />
</template>
<script>
// 导入Header组件(注册前需先导入对应组件)
import Header from './components/Header.vue';
export default {
components: {
// 注册Header组件, 只能在当前组件中使用
Header
}
}
</script>全局注册
全局注册的组件可以在任何地方使用,通常在
main.js
( 程序入口文件 ) 中进行全局注册1
2
3
4
5
6
7
8
9
10/* src/main.js */
import { createApp } from 'vue'
// 导入Header组件
import Header from './components/Header.vue';
const app = createApp(App)
// 注册全局组件
app.component('Header', Header)
app.mount('#app')
在 Vue 中全局注册使用相对较少,主要原因如下:
- 命名冲突:全局注册的组件在整个应用中可见,容易与其它组件名称冲突
- 难以维护:如果大量组件都全局注册,可能会造成组件引用混乱,管理维护变得复杂
- 性能开销:全局注册的组件在应用加载时就被解析( 不管是否使用 ),可能会增加应用的初始加载时间
Vue.createApp
方法
描述:用来创建 Vue 应用实例的方法,它接收一个对象作为参数,该对象是当前 Vue 应用实例的根组件( Root Component )
组件中包含很多配置选项,常见的包括:
template
:用于定义组件的模板data
:用于定义组件的数据,可以在模板中使用methods
:用于定义组件的方法,可以在模板中调用……
在实际开发中我们会在单个 Vue 应用实例中使用组件来构建复杂的单页面应用
app.mount
方法
描述:将 Vue 应用实例挂载到指定的 DOM 元素上以使 Vue 应用实例在页面中生效。Vue 应用实例挂在后,它会响应式地去渲染页面
语法:app.mount(挂载点)
挂载点可以是一个 DOM元素 或是一个 CSS 选择器,它会返回根组件的实例
模板 template
Vue 模板是一种描述视图的语法结构。它允许你将 HTML 和 Vue 的特殊语法结合在一起,创建动态的、响应式的用户界面
Vue 模板主要增加了以下几种语法:
插值( Mustache ):
语法:
{{ expression }}
| 只能在元素内容中使用,不能在元素属性中使用双大括号(
{{ }}
)中的内容是 Vue 表达式,它可以访问组件实例中的数据作用:用于在模板中插入组件实例中的数据,实现数据的动态渲染,即数据发生变化时,视图自动更新变化
指令( Directive ):
- 指令是带有特殊功能的 Vue 模板属性,它通常以
v-
开头,用于在 DOM 元素中添加特定行为和功能
Vue 表达式:
- Vue表达式可以使用 JavaScript 表达式和一些常用 JavaScript 内置对象( 如 Date, Object 等 ),最重要的是它能访问组件实例上的属性
例:
1 | <!-- 通过 cdn 链接来使用 Vue --> |
style scoped(局部样式)
局部样式是指组件内的 CSS样式只在该组件内有效,而不会影响到其他组件的样式
要使用局部样式只需要在 <style>
标签上添加 scoped
属性即可:
例:
1 | <!-- 局部样式, 如果去除 scoped, 则样式会对所有组件有效(全局样式) --> |
style scoped 的原理:
Vue 会在组件的每个元素上添加一个自动生成的属性(如 data-v-xxxx
),并将 style scoped
样式中的选择器转换为只匹配带有该属性的元素。例如,上面的 .box
样式会被编译为类似以下的代码:
1 | /* data-v-xxxx 相当于一个身份标识, 每个组件生成的都不相同, 这样确保了组件中的样式只在该组件中有效 */ |
Composition API(组合式 API)
Vue3 引入了组合式 API(Composition API),以便更灵活地组织和复用组件逻辑
Vue2 中使用 data
、methods
等选项来定义组件状态和方法。Vue3 的组合式 API 则不再强制划分这些选项,可以自由组合和组织逻辑,使代码结构更清晰、复用性更强
setup
函数
在组合式 API 中,setup
函数是组件的入口。它在组件实例创建前调用。setup
函数返回的内容会暴露给模板使用
例:
1 | <template> |
ref
函数
ref
函数用于创建响应式数据的工具- 它会将数据包裹在一个名为 RefImpl 类型的代理( Proxy )对象中返回。在
setup
函数中要访问响应式数据必须通过对象中的value
属性来访问,但在模版中无需通过value
来访问,Vue 会自动解包( 在模板编译时, Vue 会自动将RefImpl
类型对象转换为ref.value
)访问 value
属性的操作会被 Vue 拦截(get
&set
),当修改value
属性的值为基本数据类型时,Vue 会响应式的更新,如果将其值修改为复杂数据类型(如 数组、对象)时,Vue 会调用reactive
函数来创建复杂数据类型的响应式数据
reactive
函数:
reactive
函数用于创建复杂数据类型(如 数组、对象)的响应式数据,它会通过创建代理(new Proxy
)的方式来实现响应式,这种方式可以实现数组或对象的深层响应式,但不能实现基本数据类型的响应式
toRefs
函数
toRefs
是 Vue3 中提供的一个工具函数,用于将一个响应式对象中的每个属性转换为单独的 ref
对象( RefImpl
)。它的主要用途是解决直接解构响应式对象丢失响应性的问题
例:
1 | <template> |
script setup(组合式 API 语法糖)
script setup
是 Vue3 提供的一个开发编译时的语法糖,用来代替传统的 setup
函数。它直接把 setup
的逻辑写在 <script setup>
标签内,无需显式定义 setup
函数
例:
1 | <!-- setup 启用组合式 API 语法糖 --> |
特点:
- 无需显示的将变量或函数通过 return 暴露给模板,Vue 会在开发编译时自动将顶层( 全局作用域 )的变量或函数暴露给模板(
setupState
) - 导入的组件无需注册,Vue 会自动注册
props 组件间通信
props
是 Vue 中的一种机制,用于在父组件中向子组件传递数据。父组件可以在模板中给子组件添加属性将数据传递给子组件,而子组件则通过 props
接收这些数据,从而实现父子组件之间的通信
例:
1 | <!-- 父组件: src/components/Parent.vue --> |
1 | <!-- 子组件: src/components/Child.vue --> |
1 | <!-- 父组件: src/components/Parent.vue --> |
1 | <!-- 子组件: src/components/Child.vue --> |
props
可以通过 :指令(v-bind) 动态的传递数据,这意味着当父组件传递的 props
数据变化时,子组件会立即响应式的更新
props
在子组件中是只读的,不能直接修改,否则会提示警告
单向数据流:
单向数据流是指数据在组件之间的传递方向:从父组件流向子组件,但子组件不能直接修改从父组件传递过来的数据( props 只读 )。单向数据流确保了数据流向的单一性和可预测性,避免了数据状态的混乱导致状态管理变得复杂。如果需要更新 props
( 修改 props ) 时,可以使用事件通知父组件
例:
1 | <!-- 父组件: src/components/Parent.vue --> |
1 | <!-- 子组件: src/components/Child.vue --> |
1 | <!-- 父组件: src/components/Parent.vue --> |
1 | <!-- 子组件: src/components/Child.vue --> |
events 组件间通信
events 即组件事件,它是指组件之间通过自定义事件实现的通信方式。组件事件允许子组件向父组件发送消息,使父组件能够响应子组件中的操作。这种机制在 Vue 中主要是通过 $emit
、v-on
(缩写 @
)来实现
通过自定义事件实现子组件向父组件传递数据:
在 Vue 中,子组件可以使用组件实例上的 $emit
方法触发一个自定义事件,并可将数据传递给父组件。父组件通过 v-on
(或 @
)监听该事件,并在事件发生时接收数据和执行回调函数
例:
1 | <!-- src/components/Child.vue --> |
1 | <!-- src/components/Parent.vue --> |
1 | <!-- src/components/Child.vue --> |
1 | <!-- src/components/Parent.vue --> |
Vue 推荐事件及 props 的名称都使用 “kebab-case
” 的命名方式,比如 child-click
、submit-form
。这样格式更统一,可读性也更强