Vue3学习之路:写写小Demo,体验Vue3
小提示:本文章适合已了解VUE2的同学~
本章分为两个部分来写,第一部分基础知识,第二部分写小demo
Demo: 小demo是官方的例子,是个日常管理的TODO 虽然功能简单,但是用到的vue知识范围几乎覆盖的Vue3很早之前就有了,以前一直在学习Vue2和牢固前端基础,没有学习到Vue3,现在开始进步啦,记录学习Vue3~
文章包含Vue3官方文档的内容
Vue3基础知识
组合式API(Composition API)
我们学习组合式API之前,先回顾一下选项式API。 选项式API,多个选项的对象来描述组件的逻辑,比如:在data里面写数据 ,在methods里面写方法,等等。选项所定义的属性都会暴露在函数内部的 this 上,它会指向当前的组件实例。
这种写法确实入手门槛低,易学习这个框架,当时新学习的时候也是特别容易上手,在对应的选项里面写对应的东西即可,特别舒服。
js
<script>
export default {
// data() 返回的属性将会成为响应式的状态
// 并且暴露在 `this` 上
data() {
return {
count: 0
}
},
// methods 是一些用来更改状态与触发更新的函数
// 它们可以在模板中作为事件处理器绑定
methods: {
increment() {
this.count++
}
},
// 生命周期钩子会在组件生命周期的各个不同阶段被调用
// 例如这个函数就会在组件挂载完成后被调用
mounted() {
console.log(`The initial count is ${this.count}.`)
}
}
</script>
<template>
<button @click="increment">Count is: {{ count }}</button>
</template>
但这种好日子不长,小项目问题不大,很舒服哒。但是你一旦用VUE2的选项式API来开发中型项目那就不舒服啦,当时写比小项目大一点,比中型项目小一点的点餐小程序的时候,写一个复杂一点的功能的时候,我不停的滑动滚动条,把我搞的很难受,功能的代码片段东一个西一个,严重违背了高内聚,低耦合的原则
组合式API和选项式API的对比图(左边的是组合式API 右边的是选项式API):
看图片就一目了然啦~ 现在我们介绍在Vue3重大改变之一的:组合式API
ps:在Vue3也可以使用选项式API
组合式API:组合式 API (Composition API) 是一系列 API 的集合,使我们可以使用函数而不是声明选项的方式书写 Vue 组件。简单的说就是我们需要什么API那就导入对应的API函数,来描述组件的逻辑。
Vue
<template>
<button @click="increment">Count is: {{ count }}</button>
</template>
<script>
import { ref } from 'vue' // 导入ref响应式API
setup(){
const countRef = ref(0) // 用来修改状态、触发更新的函数
function increment() { count.value++ }
return {
count:countRef,
increment
}
}
</script>
看代码就一目了然,我们在setup函数里面描述组件的逻辑,当我们需要把普通变量变成响应式变量则会导入ref函数API(把数据变成响应式的API 后面会介绍),然后用ref函数,它会返回给我们一个响应式的数据,因此我们的countRef变成响应式了。
然后在这里要注意的是,我们在setup函数里面的函数或者变量在模板使用则需要返回这些函数和变量,才能在模板上直接使用,否则是不能使用的。
Vue官方为了方便使用组合式API,提供了 [<script setup>
] 。这个 setup
attribute 是一个标识,告诉 Vue 需要在编译时进行一些处理,让我们可以更简洁地使用组合式 API。比如,<script setup>
中的导入和顶层变量/函数都能够在模板中直接使用
我们把上面的示例,使用[<script setup>
]来重新编写一遍
Vue
<template>
<button @click="increment">Count is: {{ count }}</button>
</template>
<script setup>
import { ref } from 'vue'
// 响应式状态
const count = ref(0)
// 用来修改状态、触发更新的函数
function increment() {
count.value++
}
</script>
使用[<script setup>
]时,不需要返回的,里面的函数,变量都可以在模板直接使用的。
也推荐各位尽量使用组合式API开发,因为用组合式API,来抽离一些重复性的代码片段时候,超方便,简洁的。 使用选项式API的时候只能使用mixin,这个mixin 只能说依托答辩~
如何创建一个Vue 应用
在Vue3中创建一个Vue应用与Vue2是不同的,那我们看看到底是改变了什么?
我们首先看一下Vue2是如何创建一个Vue应用的
js
import Vue from 'vue'
import App from './App.vue'
new Vue({
render: h => h(App),
}).$mount('#app')
在Vue2的时候,导入Vue构造函数,使用new来创建一个Vue应用
Vue3是如何创建一个Vue应用的
js
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
在Vue3的时候,导入的是 createAPP 函数,然后使用createApp来创建Vue应用
Vue3为何改动创建一个应用的方式呢?有什么原因在?
在Vue2,当我们需要在一个页面中使用多个Vue应用的时候,我们需要使用插件,全局指令,全局混入的时候,一个插件会影响所有的Vue应用的,因为在Vue2的时候,我们使用插件什么的,直接在构造函数后面.use来使用的。 当我们把插件只想用在一个应用上,那是不可能的~ 看一下下面的示例:
js
<!-- vue2 -->
<div id="app1"></div>
<div id="app2"></div>
<script>
Vue.use(...); // 此代码会影响所有的vue应用
Vue.mixin(...); // 此代码会影响所有的vue应用
Vue.component(...); // 此代码会影响所有的vue应用
new Vue({
// 配置
}).$mount("#app1")
new Vue({
// 配置
}).$mount("#app2")
</script>
但是Vue3改变之后,这种情况就改善了,我们使用插件或者全局的时候,不会影响到所有的Vue应用。
js
<!-- vue3 -->
<div id="app1"></div>
<div id="app2"></div>
<script>
createApp(根组件).use(...).mixin(...).component(...).mount("#app1")
createApp(根组件).mount("#app2")
</script>
在Vue2的时候没有考虑到使用多个应用,但在Vue3弥补了这个Vue2上的缺陷。
响应式基础
我们现在到了,Vue框架的灵魂之一,响应式!
声明响应式状态
ref() 在上面的示例中也看到了,当我们把一个数据变成响应式的时候,使用ref()函数来变成的,现在我们详细的了解一下这个ref()函数吧~
在组合式 API 中,推荐使用 ref()
函数来声明响应式状态:
js
import { ref } from 'vue'
const count = ref(0)
ref()
接收参数,并将其包裹在一个带有 .value
属性的 ref 对象中返回:
Vue
<template>
<h1>Count is: {{ count }}</h1>
</template>
<script setup>
const count = ref(0)
console.log(count) // { value: 0 }
console.log(count.value) // 0
count.value++
console.log(count.value) // 1
</script>
在<script setup>
中使用的时候,需要.value
来使用,但是在模板中我们就可以直接使用,不需要.value
深层响应 Ref 可以持有任何类型的值,包括深层嵌套的对象、数组或者 JavaScript 内置的数据结构,比如 Map
Ref 会使它的值具有深层响应性。这意味着即使改变嵌套对象或数组时,变化也会被检测到:
js
import { ref } from 'vue'
const obj = ref({
nested: { count: 0 },
arr: ['foo', 'bar']
})
function mutateDeeply() {
// 以下都会按照期望工作
obj.value.nested.count++
obj.value.arr.push('baz')
}
也可以通过 shallow ref 来放弃深层响应性。对于浅层 ref,只有 .value
的访问会被追踪。浅层 ref 可以用于避免对大型数据的响应性开销来优化性能、或者有外部库管理其内部状态的情况。
在Vue3响应式的改变
在Vue2的时候,响应式是根据对象的getter和setter来实现的,但是Vue3中是使用Proxy代理来实现的
vue3不再使用Object.defineProperty的方式定义完成数据响应式,改成使用Proxy。 因为除了Proxy本身效率比Object.defineProperty更高之外,由于不必递归遍历所有属性,而是直接得到一个Proxy。所以在vue3中,对数据的访问是动态的,当访问某个属性的时候,再动态的获取和设置,这就极大的提升了在组件初始阶段的效率。 同时,由于Proxy可以监控到成员的新增和删除,因此,在vue3中新增成员、删除成员、索引访问等均可以触发重新渲染,而这些在vue2中是难以做到的。