Vue知识点总结(一)基础认识
该系列文章主要基于官方Vue教程,对Vue使用及特性等方面做一个较为系统的总结
官方文档链接Vue.js
Vue概述
框架的作用
vue是一套构建用户界面的javascript框架,基于html,css,javascript构建,提供一套声明式的,组件化的编程模型。
前端开发框架的本质作用是简化开发,其优势是提供了一系列模块化语法,只需遵守这些语法就可以涵盖大量日常开发的需求,使用开发框架具有如下特点:
- 组件化开发:将代码拆分为独立的、可复用的组件,总而便于管理
- 状态管理:提供强大的数据管理流,从而帮助开发者管理数据状态
- 虚拟
DOM
:使用虚拟DOM
构建DOM
树,能够减少实际对DOM
的操作次数,从而提高开发效率 - 响应式数据绑定:提供一系列响应式数据绑定
api
,实现数据与视图的同步 - 单页应用(
SPA
):使用框架非常适合构建单页应用,可以在不刷新页面的前提下实现页面更新
vue是一个框架,也是一个生态,符合大部分前端开发需求。
渐进式框架
什么是渐进式框架?
渐进式框架即在开发过程中可以被渐进集成的框架,这意味着Vue
项目将不需要在开始就规划好所有功能,而是可以慢慢根据需求进行集成,这对于逐渐膨胀的前端开发而言是非常有利的
渐进式框架的特点
- 无需构建步骤,渐进式增强静态html
- 在任何页面中作为
web components
嵌入- 单页应用(
SPA
)- 全栈、服务端渲染(
SSR
)jamestack
、静态站点生成(SSG
)- 开发桌面端、移动端、WebGL,甚至是命令行终端中的界面
使用Vue
可以渐进式地集成上述功能
Vue代码风格
选项式api
与组合式api
两种风格的api
可以实现相同的功能,但是语言风格不同
选项式api
适合解决需要不断拓展的需求
组合式api
更适合解决完整的单页开发
两种api
底层系统相同,都能解决大部分问题。
但两种api
都有一个共性,即Vue
项目不关注dom
是怎么变化的,而是关注数据,并将数据同步到视图中
Vue实例创建
创建一个vue应用
主流有两种脚手架工具,分别是vue-cli
与vite
,相对来说vite
的构建效率要大于vue-cli
,不过开发中两者都很常见
- 构建
Vue
项目
使用vue-cli
构建使用
1 vue create my-new-vue-projectVite
构建
1 npm create/init vue@latest- 安装依赖,启动服务器
1
2 npm install
npm run serve/dev- 发布到生产环境
1 npm run build
构建一个vue实例
如果直接使用CDN
而不是npm
创建vue
实例,可以直接通过url
引入createApp
,这种方式一般用于对html
做静态提升
在早期也有通过new Vue
创建Vue
实例的,但引入了createApp
后更倾向于这种方式
- 准备一个根模板容器
1
2
3 <div id="app">
<button @click="count++">{{ count }}</button>
</div>- 创建导入构造对象
1
2
3
4
5
6
7
8
9
10 import { createApp } from 'vue'
const app = createApp({
data() {
return {
count: 0
}
}
})- 挂载构造对象
1 app.mount('#app')
一个页面可以创建多个vue
实例,如果你正在使用Vue
来增强服务端渲HTML
,并且只想要Vue
去控制一个大型页面中特殊的一小部分,应避免将一个单独Vue
应用实例挂载到整个页面上,而是应该创建多个小的应用实例,将它们分别挂载到所需的元素上去。
Vue核心概念
Vue
构建网页的具体流程如下:
- 实例创建:通过
createApp
创建一个Vue
实例- 选项注入:使用选项或组合式api注入数据和方法
- 创建虚拟
DOM
:模板编译生成虚拟DOM
树- 挂载:将虚拟
DOM
树挂载到真实DOM
树上- 渲染:数据变化时,通过
DOM diff
算法更新真实DOM
树
选项注入
创建Vue
实例后,下一步便是对选项进行注入,Vue2
的选项式api
即将数据抽象为具体的如data
,computed
,method
等选项或方法进行注入Vue
实例中
在Vue3
中则是将数据封装进setup
方法中,通过ref
,reactive
等来定义响应式状态
虚拟DOM
vue
模板并不是真实的DOM
,而是虚拟DOM
,虚拟DOM
本质上是一个字符串,vue
内部会根据虚拟DOM
生成真实DOM
(vnode
树),这个过程被称为vue
渲染,通过虚拟DOM
节点的对比修改数据,从而提高效率,vue
渲染使用render()
函数的返回值生成vnode
,从而创建真实DOM
虽然Vue2
和Vue3
整体构建方法类似,但Vue3
中通过算法的优化大大提升了构建效率
Vue特性
插值表达式
最基本的数据绑定形式,响应式双大括号中的值1
<span>Message: {{ msg }} </span>
样式作用域 scoped
通过hash
映射对组件样式进行约束1
<style scoped>
样式作用域不仅影响当前组件,还会影响子组件的根元素
深层选择器 :deep()
处于scoped
样式中的选择器如果想要做更“深度”的选择,也即:影响到子组件,可以使用:deep()
这个伪类:1
2
3
4
5<style scoped>
.a :deep(.b) {
/* ... */
}
</style>
组件递归
一个单文件组件可以通过它的文件名被其自己所引用。例如:名为 FooBar.vue
的组件可以在其模板中用 <FooBar/>
引用它自己1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21<!-- Comment.vue -->
<template>
<div>
<p>{{ comment.text }}</p>
<div v-if="comment.replies">
<Comment v-for="reply in comment.replies" :key="reply.id" :comment="reply" />
</div>
</div>
</template>
<script>
export default {
name: 'Comment',
props: {
comment: {
type: Object,
required: true
}
}
};
</script>
动态参数
动态参数允许你在模板中动态绑定事件或者方法,使用动态参数可以做到动态修改属性名!(不是属性的值),具体实现方式是使用[]
来绑定属性名1
2
3
4
5
6
7
8<!--
注意,参数表达式有一些约束,
参见下面“动态参数值的限制”与“动态参数语法的限制”章节的解释
-->
<a v-bind:[attributeName]="url"> ... </a>
<!-- 简写 -->
<a :[attributeName]="url"> ... </a>
还可以绑定方法名1
2
3
4<a v-on:[eventName]="doSomething"> ... </a>
<!-- 简写 -->
<a @[eventName]="doSomething"> ... </a>
使用动态参数时,需保证表达式的值为一个字符串且不支持null
,此外,空格可引号都是不被允许的
Vue基本指令
v-html/v-text
v-text
用以动态设置元素文本内容v-html
用以动态设置元素innerhtml
,包括DOM
元素
1 | <span v-text="msg"></span> |
1 | <div v-html="html"></div> |
v-show/v-if
- 两者都用来控制元素的显示与隐藏
v-if
是真实地按条件渲染,即”真实地”控制元素的重建与销毁v-show
则只是相当于控制元素的display
属性为none
,相当于从页面中移除,在DOM
树中仍保有一席之地- 因此,
v-show
用来控制需要经常变动的元素,而v-if
处理变动较少的元素
1 | <div v-if="type === 'A'"> |
1 | <h1 v-show="ok">Hello!</h1> |
还有一个老生常谈的问题了,就是v-if
不能和v-for
在一起使用,由于v-if
比v-for
的优先级更高。这意味着v-if
的条件将无法访问到v-for
作用域内遍历的值
v-on
- 我们可以使用
v-on
指令 (简写为 @) 来监听DOM
事件,并在事件触发时执行对应的JavaScript
v-on
可以处理内联事件或方法事件
1 | const count = ref(0) |
1 | const name = ref('Vue.js') |
.stop
:单击事件时停止传递.prevent
:提交表单时不会刷新页面,相当于event.preventDefault()
.capture
:当事件涉及子组件穿透时优先处理父组件.self
:当事件的event.target
指向自身(不来自子元素)时才触发.once
:点击事件最多触发一次.passive
:保证滚动事件的默认行为立即发生
修饰符遵从链式调用原则
vue
为一些系统按键提供了别名,如.enter
,.delete
,.space
,.esc
,.space
,.up
,.down
,.left
,.right
,.ctrl
,.alt
,.shift
等1
2
3
4
5<!-- Alt + Enter -->
<input @keyup.alt.enter="clear" />
<!-- Ctrl + 点击 -->
<div @click.ctrl="doSomething">Do something</div>.exact
修饰符:可使用.exact
修饰符来指定当单独按键被按下时才触发事件1
2
3
4
5
6
7
8<!-- 当按下 Ctrl 时,即使同时按下 Alt 或 Shift 也会触发 -->
<button @click.ctrl="onClick">A</button>
<!-- 仅当按下 Ctrl 且未按任何其他键时才会触发 -->
<button @click.ctrl.exact="onCtrlClick">A</button>
<!-- 仅当没有按下任何系统按键时触发 -->
<button @click.exact="onClick">A</button>- 鼠标按键修饰符
.left
,.right
,.middle
v-bind
v-bind
,简写为:
,在vue
中用作数据绑定- 常用作绑定类和内联样式或者对
vue
内置参数进行绑定,如key
和props
v-bind
可以绑定数组,对象,支持一次绑定多个参数
1 | const isActive = ref(true) |
1 | <div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div> |
v-for
v-for
用于基于数组来渲染一个列表- 模板语法:
v-for = "(value,key?,index) in items"
- 参数示意:
value
表示数组的值,key
(可选)表示数组的键,index
(可选)表示数组的索引 - 为
v-for
绑定一个唯一的:key
来确保跟踪每个项
1 | const myObject = reactive({ |
v-model
v-model
本质是一个语法糖,用于简化将表单内容同步到Javascript
中的相应变量这一步骤v-model
会绑定文本类型,如<input>
,<textarea>
的value
属性,并监听input
事件v-model
会根据文本类型自动调整绑定方式,例如,对ckeckbox
可以绑定一个数组,用以存储所有多选的值
1 | <input |
1 | const checkedNames = ref([]) |
.lazy
:v-model
会在每次change
事件触发后(文本框失去焦点,多选框选择等)更新数据.number
:把输入自动转化为数字,会在输入框有type=number
时自动启用.trim
:自动去除用户输入两端的空格
自定义指令
- 除了
Vue
内置的一系列指令外,Vue
还允许你注册自定义的指令 - 在
<script setup>
语法糖中,任何以v
开头的驼峰式命名的变量都可以被用作一个自定义指令,如vFocus
即可以在模板中以v-focus
的形式使用 - 在没有
<script setup>
中,可以配置derective
配置项定义自定义指令 - 可以使用
app.derective()
全局定义指令 - 自定义指令由一个包含生命周期钩子对象组成,预定义的钩子函数触发,根据内含的参数创建方法
方法一(script setup)
1 | <script setup> |
方法二(配置项)
1 | export default { |
方法三(全局注册)
1 | const app = createApp({}) |
在vue2
中会使用insert()
表示绑定,用update()
表示更新,这些在vue3
中被替换成了生命周期钩子,便于记忆
1 | const myDirective = { |
为简化自定义指令,由于大部分情况下自定义指令由mounted
和updated
触发,故简化形式可直接传入一个函数表示这两种情况
1 | app.directive('color', (el, binding) => { |
el
:指令绑定到的元素。这可以用于直接操作DOM
。binding
:一个对象,包含以下属性。value
:传递给指令的值。例如在v-my-directive
=”1 + 1” 中,值是 2。oldValue
:之前的值,仅在beforeUpdate
和updated
中可用。无论值是否更改,它都可用。arg
:传递给指令的参数 (如果有的话)。例如在v-my-directive:foo
中,参数是"foo"
。modifiers
:一个包含修饰符的对象 (如果有的话)。例如在v-my-directive.foo.bar
中,修饰符对象是{ foo: true, bar: true }
。instance
:使用该指令的组件实例。dir
:指令的定义对象。
vnode
:代表绑定元素的底层 VNode。prevVnode
:代表之前的渲染中指令所绑定元素的VNode
。仅在beforeUpdate
和updated
钩子中可用。1
2
3
4
5
6
7
8<div v-example:foo.bar="baz">
//对于上述指令,binding参数为如下对象
{
arg: 'foo',
modifiers: { bar: true },
value: /* `baz` 的值 */,
oldValue: /* 上一次更新时 `baz` 的值 */
}