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` 的值 */
}




