目录
3.1. 【OptionsAPI 与 CompositionAPI】
7.1.【shallowRef 与 shallowReactive 】
7.2.【readonly 与 shallowReadonly】
1. Vue3简介
-
2020年9月18日,
Vue.js
发布版3.0
版本,代号:One Piece
(n -
截止2023年10月,最新的公开版本为:
3.3.4
1.1. 【性能的提升】
-
打包大小减少
41%
。 -
初次渲染快
55%
, 更新渲染快133%
。 -
内存减少
54%
。
1.2.【 源码的升级】
-
使用
Proxy
代替defineProperty
实现响应式。 -
重写虚拟
DOM
的实现和Tree-Shaking
。
1.3. 【拥抱TypeScript】
-
Vue3
可以更好的支持TypeScript
。
1.4. 【新的特性】
-
Composition API
(组合API
):-
setup
-
ref
与reactive
-
computed
与watch
......
-
-
新的内置组件:
-
Fragment
-
Teleport
-
Suspense
......
-
-
其他改变:
-
新的生命周期钩子
-
data
选项应始终被声明为一个函数 -
移除
keyCode
支持作为v-on
的修饰符......
-
2. 创建Vue3工程
2.1. 【基于 vue-cli 创建】
点击查看官方文档
备注:目前
vue-cli
已处于维护模式,官方推荐基于Vite
创建项目。
## 查看@vue/cli版本,确保@vue/cli版本在4.5.0以上 vue --version ## 安装或者升级你的@vue/cli npm install -g @vue/cli ## 执行创建命令 vue create vue_test ## 随后选择3.x ## Choose a version of Vue.js that you want to start the project with (Use arrow keys) ## > 3.x ## 2.x ## 启动 cd vue_test npm run serve
2.2. 【基于 vite 创建】(推荐)
vite
是新一代前端构建工具,官网地址:https://vitejs.cn,vite
的优势如下:
-
轻量快速的热重载(
HMR
),能实现极速的服务启动。 -
对
TypeScript
、JSX
、CSS
等支持开箱即用。 -
真正的按需编译,不再等待整个应用编译完成。
-
webpack
构建 与vite
构建对比图如下:
-
具体操作如下(点击查看官方文档)
## 1.创建命令 npm create vue@latest ## 2.具体配置 ## 配置项目名称 √ Project name: vue3_test ## 是否添加TypeScript支持 √ Add TypeScript? Yes ## 是否添加JSX支持 √ Add JSX Support? No ## 是否添加路由环境 √ Add Vue Router for Single Page Application development? No ## 是否添加pinia环境 √ Add Pinia for state management? No ## 是否添加单元测试 √ Add Vitest for Unit Testing? No ## 是否添加端到端测试方案 √ Add an End-to-End Testing Solution? » No ## 是否添加ESLint语法检查 √ Add ESLint for code quality? Yes ## 是否添加Prettiert代码格式化 √ Add Prettier for code formatting? No
自己动手编写一个App组件
<template> <div class="app"> <h1>你好啊!</h1> </div> </template> <script lang="ts"> export default { name:'App' //组件名 } </script> <style> .app { background-color: #ddd; box-shadow: 0 0 10px; border-radius: 10px; padding: 20px; } </style>
安装官方推荐的vscode
插件:
总结:
-
Vite
项目中,index.html
是项目的入口文件,在项目最外层。 -
加载
index.html
后,Vite
解析<script type="module" src="xxx">
指向的JavaScript
。 -
Vue3
中是通过createApp
函数创建一个应用实例。
2.3. 【一个简单的效果】
Vue3
向下兼容Vue2
语法,且Vue3
中的模板中可以没有根标签
<template> <div class="person"> <h2>姓名:{ {name}}</h2> <h2>年龄:{ {age}}</h2> <button @click="changeName">修改名字</button> <button @click="changeAge">年龄+1</button> <button @click="showTel">点我查看联系方式</button> </div> </template> <script lang="ts"> export default { name:'App', data() { return { name:'张三', age:18, tel:'13888888888' } }, methods:{ changeName(){ this.name = 'zhang-san' }, changeAge(){ this.age += 1 }, showTel(){ alert(this.tel) } }, } </script>
3. Vue3核心语法
3.1. 【OptionsAPI 与 CompositionAPI】
-
Vue2
的API
设计是Options
(配置)风格的。 -
Vue3
的API
设计是Composition
(组合)风格的。
Options API 的弊端
Options
类型的 API
,数据、方法、计算属性等,是分散在:data
、methods
、computed
中的,若想新增或者修改一个需求,就需要分别修改:data
、methods
、computed
,不便于维护和复用。
Composition API 的优势
可以用函数的方式,更加优雅的组织代码,让相关功能的代码更加有序的组织在一起。
3.2. 【拉开序幕的 setup】
setup 概述
setup
是Vue3
中一个新的配置项,值是一个函数,它是 Composition API
“表演的舞台”,组件中所用到的:数据、方法、计算属性、监视......等等,均配置在setup
中。
特点如下:
-
setup
函数返回的对象中的内容,可直接在模板中使用。 -
setup
中访问this
是undefined
。 -
setup
函数会在beforeCreate
之前调用,它是“领先”所有钩子执行的。
<template> <div class="person"> <h2>姓名:{ {name}}</h2> <h2>年龄:{ {age}}</h2> <button @click="changeName">修改名字</button> <button @click="changeAge">年龄+1</button> <button @click="showTel">点我查看联系方式</button> </div> </template> <script lang="ts"> export default { name:'Person', setup(){ // 数据,原来写在data中(注意:此时的name、age、tel数据都不是响应式数据) let name = '张三' let age = 18 let tel = '13888888888' // 方法,原来写在methods中 function changeName(){ name = 'zhang-san' //注意:此时这么修改name页面是不变化的 console.log(name) } function changeAge(){ age += 1 //注意:此时这么修改age页面是不变化的 console.log(age) } function showTel(){ alert(tel) } // 返回一个对象,对象中的内容,模板中可以直接使用 return {name,age,tel,changeName,changeAge,showTel} } } </script>
setup 的返回值
-
若返回一个对象:则对象中的:属性、方法等,在模板中均可以直接使用(重点关注)。
-
若返回一个函数:则可以自定义渲染内容,代码如下:
setup(){ return ()=> '你好啊!' }
setup 与 Options API 的关系
-
Vue2
的配置(data
、methos
......)中可以访问到setup
中的属性、方法。 -
但在
setup
中不能访问到Vue2
的配置(data
、methos
......)。 -
如果与
Vue2
冲突,则setup
优先。
setup 语法糖
setup
函数有一个语法糖,这个语法糖,可以让我们把setup
独立出去,代码如下:
<template> <div class="person"> <h2>姓名:{ {name}}</h2> <h2>年龄:{ {age}}</h2> <button @click="changName">修改名字</button> <button @click="changAge">年龄+1</button> <button @click="showTel">点我查看联系方式</button> </div> </template> <script lang="ts"> export default { name:'Person', } </script> <!-- 下面的写法是setup语法糖 --> <script setup lang="ts" name="123"> //name自定义组件名字需要安装插件 console.log(this) //undefined // 数据(注意:此时的name、age、tel都不是响应式数据) let name = '张三' let age = 18 let tel = '13888888888' // 方法 function changName(){ name = '李四'//注意:此时这么修改name页面是不变化的 } function changAge(){ console.log(age) age += 1 //注意:此时这么修改age页面是不变化的 } function showTel(){ alert(tel) } </script>
扩展:上述代码,还需要编写一个不写setup
的script
标签,去指定组件名字,比较麻烦,我们可以借助vite
中的插件简化
-
第一步:
npm i vite-plugin-vue-setup-extend -D
-
第二步:
vite.config.ts
import { defineConfig } from 'vite' import VueSetupExtend from 'vite-plugin-vue-setup-extend' export default defineConfig({ plugins: [ VueSetupExtend() ] })
-
第三步:
<script setup lang="ts" name="Person">
3.3. 【ref 创建:基本类型的响应式数据】
-
作用:定义响应式变量。
-
语法:
let xxx = ref(初始值)
。 -
返回值:一个
RefImpl
的实例对象,简称ref对象
或ref
,ref
对象的value
属性是响应式的。 -
注意点:
-
JS
中操作数据需要:xxx.value
,但模板中不需要.value
,直接使用即可。 -
对于
let name = ref('张三')
来说,name
不是响应式的,name.value
是响应式的。
-
<template> <div class="person"> <h2>姓名:{ {name}}</h2> <h2>年龄:{ {age}}</h2> <button @click="changeName">修改名字</button> <button @click="changeAge">年龄+1</button> <button @click="showTel">点我查看联系方式</button> </div> </template> <script setup lang="ts" name="Person"> import {ref} from 'vue' // name和age是一个RefImpl的实例对象,简称ref对象,它们的value属性是响应式的。 let name = ref('张三') let age = ref(18) // tel就是一个普通的字符串,不是响应式的 let tel = '13888888888' function changeName(){ // JS中操作ref对象时候需要.value name.value = '李四' console.log(name.value) // 注意:name不是响应式的,name.value是响应式的,所以如下代码并不会引起页面的更新。 // name = ref('zhang-san') } function changeAge(){ // JS中操作ref对象时候需要.value age.value += 1 console.log(age.value) } function showTel(){ alert(tel) } </script>
3.4. 【reactive 创建:对象类型的响应式数据】
-
作用:定义一个响应式对象(基本类型不要用它,要用
ref
,否则报错) -
语法:
let 响应式对象= reactive(源对象)
。 -
返回值:一个
Proxy
的实例对象,简称:响应式对象。 -
注意点:
reactive
定义的响应式数据是“深层次”的。
<template> <div class="person"> <h2>汽车信息:一台{ { car.brand }}汽车,价值{ { car.price }}万</h2> <h2>游戏列表:</h2> <ul> <li v-for="g in games" :key="g.id">{ { g.name }}</li> </ul> <h2>测试:{ {obj.a.b.c.d}}</h2> <button @click="changeCarPrice">修改汽车价格</button> <button @click="changeFirstGame">修改第一游戏</button> <button @click="test">测试</button> </div> </template> <script lang="ts" setup name="Person"> import { reactive } from 'vue' // 数据 let car = reactive({ brand: '奔驰', price: 100 }) let games = reactive([ { id: 'ahsgdyfa01', name: '英雄联盟' }, { id: 'ahsgdyfa02', name: '王者荣耀' }, { id: 'ahsgdyfa03', name: '原神' } ]) let obj = reactive({ a:{ b:{ c:{ d:666 } } } }) function changeCarPrice() { car.price += 10 } function changeFirstGame() { games[0].name = '流星蝴蝶剑' } function test(){ obj.a.b.c.d = 999 } </script>
3.5. 【ref 创建:对象类型的响应式数据】
-
其实
ref
接收的数据可以是:基本类型、对象类型。 -
若
ref
接收的是对象类型,内部其实也是调用了reactive
函数。
<template> <div class="person"> <h2>汽车信息:一台{ { car.brand }}汽车,价值{ { car.price }}万</h2> <h2>游戏列表:</h2> <ul> <li v-for="g in games" :key="g.id">{ { g.name }}</li> </ul> <h2>测试:{ {obj.a.b.c.d}}</h2> <button @click="changeCarPrice">修改汽车价格</button> <button @click="changeFirstGame">修改第一游戏</button> <button @click="tes