vue2与vue3的差异
- 响应式系统的差异:
- Vue 2 使用
Object.defineProperty
实现响应式系统,而 Vue 3 使用了 Proxy。 - 在 Vue 2 中,对于数组的响应式处理有一些限制,比如不能检测数组索引和长度的变化,而 Vue 3 中这些问题得到了解决。
- Vue 2 使用
- 组件和API的变化:
- Vue 2 中的组件选项(如
data
,methods
,computed
等)与 Vue 3 中可能有所不同,特别是在组合式 API(Composition API)的引入上。 - Vue 3 引入了
setup
函数和响应式引用(ref
,reactive
),这在 Vue 2 中是没有的。
- Vue 2 中的组件选项(如
- 生命周期钩子的变化:
- Vue 3 中引入了一些新的生命周期钩子,如
beforeUnmount
和unmounted
,它们在 Vue 2 中分别对应beforeDestroy
和destroyed
。
- Vue 3 中引入了一些新的生命周期钩子,如
- 模板和JSX的变更:
- Vue 3 支持更多编译时优化,模板的写法也更加灵活,例如
v-model
可以用在多个参数上。 - Vue 3 的 JSX 写法也有所不同,特别是在使用
setup
函数时。
- Vue 3 支持更多编译时优化,模板的写法也更加灵活,例如
- 全局API和配置:
- Vue 2 中的一些全局 API 和配置(如
Vue.filter
,Vue.mixin
)在 Vue 3 中被移除或改为使用应用实例上的 API。
- Vue 2 中的一些全局 API 和配置(如
在学习 Vue 2 时可以重点掌握的内容:
- Vue 2 的响应式原理:理解
Object.defineProperty
如何工作,以及如何追踪依赖和触发更新。 - Vue 2 的选项式 API:深入理解
data
,props
,computed
,methods
,watch
,lifecycle hooks
等组件选项的使用。 - Vue 2 的指令:熟悉
v-if
,v-for
,v-bind
,v-model
,v-on
等指令的用法和原理。 - Vue 2 的组件系统:学习组件的注册、组件间的通信(props, events, slots, provide/inject)。
- Vue 2 的路由和状态管理:了解 Vue Router 和 Vuex 在 Vue 2 中的使用方式。
- Vue 2 的性能优化:学习如何优化 Vue 2 应用的性能,比如使用
v-once
,v-memo
,Object.freeze
等。 - Vue 2 的构建工具:熟悉 Vue CLI 和其插件系统,以及如何配置 Vue 2 项目。
创建项目
- 通过npm安装Vue CLI(基于webpack):
npm install -g @vue/cli
。 - 创建一个新项目:
vue create project-name
。
通过cdn引入vue2的方法:
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
声明式渲染
<div id="app">
{{ message }}
</div>
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
})
响应式系统
// 数据对象
var data = { a: 1 }
// 该对象被加入到一个 Vue 实例中
var vm = new Vue({
data: data
})
// 获得这个实例上的 property
// 返回源数据中对应的字段
vm.a == data.a // => true
// 设置 property 也会影响到原始数据
vm.a = 2
data.a // => 2
// ……反之亦然
data.a = 3
vm.a // => 3
// 添加一个新的 property, 不会触发任何视图的更新
vm.b = 'hi'
// 阻止修改现有的 property
Object.freeze(obj)
模板语法
插值与绑定指令
- 原始HTML
双大括号会将数据解释为普通文本,而非 HTML 代码。
为了输出真正的 HTML,需要使用v-html
指令:
// rawHtml: "<span style="color: red;">This should be red.</span>"
// 动态渲染的任意 HTML 可能会非常危险,因为它很容易导致 XSS 攻击
<p>Using mustaches: {{ rawHtml }}</p>
<p>Using v-html directive: <span v-html="rawHtml"></span></p>
-
布尔类型属性绑定
只要存在就意味着值为
true
, 如果isButtonDisabled
的值是null
、undefined
或false
,则disabled
attribute 不会被包含在渲染出来的<button>
元素中。
<button v-bind:disabled="isButtonDisabled">Button</button>
-
模板表达式
模板表达式都被放在沙盒中,只能访问全局变量的一个白名单,如Math
和Date
。不应该在模板表达式中试图访问用户定义的全局变量。 -
动态参数绑定属性
动态参数预期会求出一个字符串,异常情况下值为null
。
这个特殊的null
值可以被显性地用于移除绑定。任何其它非字符串类型的值都将会触发一个警告。
<a v-bind:[attributeName]="url"> ... </a>
// data property attributeName,其值为 "href"
// 那么这个绑定将等价于 v-bind:href
<a v-on:[eventName]="doSomething"> ... </a>
// 当 eventName 的值为 "focus" 时
// 等价于 v-on:focus
<!--
在 DOM 中使用模板时这段代码会被转换为 `v-bind:[someattr]`。 (直接在一个 HTML 文件里撰写模板)
除非在实例中有一个名为“someattr”的 property,否则代码不会工作。
-->
<a v-bind:[someAttr]="value"> ... </a>
- 绑定元素的类
// 传给v-bind:class一个对象, 也可以在data中定义对象
<div
class="static"
v-bind:class="{ active: isActive, 'text-danger': hasError }"
></div>
data: {
isActive: true,
hasError: false
}
计算属性
- 缓存
计算属性是基于它们的响应式依赖进行缓存的
// 只在相关响应式依赖发生改变时它们才会重新求值
// Date.now() 不是响应式依赖, 计算属性将不再更新
computed: {
now: function () {
return Date.now()
}
}
- setter
computed: {
fullName: {
get: function () {
return this.firstName + ' ' + this.lastName
},
set: function (newValue) {
var names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}
key属性
// Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。
// 切换 loginType 将不会清除用户已经输入的内容, 仅仅是替换了它的 placeholder
<template v-if="loginType === 'username'">
<label>Username</label>
<input placeholder="Enter your username">
</template>
<template v-else>
<label>Email</label>
<input placeholder="Enter your email address">
</template>
// 添加一个具有唯一值的 key 属性
// 以示这两个元素是完全独立的,不要复用它们
<template v-if="loginType === 'username'">
<label>Username</label>
<input placeholder="Enter your username" key="username-input">
</template>
<template v-else>
<label>Email</label>
<input placeholder="Enter your email address" key="email-input">
</template>
条件渲染
v-show
不支持 <template>
元素,也不支持 v-else
。
v-if
有更高的切换开销,而 v-show
有更高的初始渲染开销。
列表渲染
-
数组更新: 包裹(变异方法)能够触发视图的更新
push()
/pop()
/shift()
/unshift()
/splice()
/sort()
/reverse()
-
对象更新:
this.$set(this.obj, 'newProp', 'New Value');
this.obj = { ...this.obj, newProp: 'New Value' };
-
数组替换: 不会变更原始数组,而总是返回一个新数组
filter()
、concat()
和slice()
example1.items = example1.items.filter(function (item) {
return item.message.match(/Foo/)
})
事件处理
<div id="example-1">
<button v-on:click="counter += 1">Add 1</button>
<p>The button above has been clicked {{ counter }} times.</p>
</div>
表单输入绑定
修饰符:
.lazy
: 在“change”时而非“input”时更新
<input v-model.lazy="msg">
.number
: 自动将用户的输入值转为数值类型
<input v-model.number="age" type="number">
.trim
: 自动过滤用户输入的首尾空白字符
<input v-model.trim="msg">