目录
一、关于Vue3
1、认识Vue3
2、性能提升
3、新增特性
二、如何创建一个Vue3项目
1.使用 vue-cli 创建
2、使用 vite 创建
三、Composition API
1、setup
2、 ref
3、 reactive
4、 比较Vue2与Vue3的响应式
5、 setup细节
6、 reactive与ref细节
7、计算属性与监视
8、生命周期
9、自定义hook函数
10、 toRefs
11、 ref获取元素
●Vue.js 3.0 "One Piece" 正式版在今年9月份发布
●2年多开发, 100+位贡献者, 2600+次提交, 600+次PR
●Vue3支持vue2的大多数特性
●更好的支持Typescript
●打包大小减少41%
●初次渲染快55%, 更新渲染快133%
●内存减少54%
●使用Proxy代替defineProperty实现数据响应式
●重写虚拟DOM的实现和Tree-Shaking
● Composition (组合) API
● setup
○ ref 和 reactive
○ computed 和 watch
○ 新的生命周期函数
○ provide与inject
○ ...●新组件
○ Fragment - 文档碎片
○ Teleport - 瞬移组件的位置
○ Suspense - 异步加载组件的loading界面
●其它API更新
○ 全局API的修改
○ 将原来的全局API转移到应用对象
○ 模板语法变化
安装或者升级
npm install -g @vue/cli
保证 vue cli 版本在 4.5.0 以上
vue --version
创建项目
vue create my-project
然后的步骤
Please pick a preset - 选择 Manually select features Check the features needed for your project - 选择上 TypeScript ,特别注意点空格是选择,点回车是下一步 Choose a version of Vue.js that you want to start the project with - 选择 3.x (Preview) Use class-style component syntax - 直接回车 Use Babel alongside TypeScript - 直接回车 Pick a linter / formatter config - 直接回车 Use history mode for router? - 直接回车 Pick a linter / formatter config - 直接回车 Pick additional lint features - 直接回车 Where do you prefer placing config for Babel, ESLint, etc.? - 直接回车 Save this as a preset for future projects? - 直接回车
官方文档
vite 是一个由原生 ESM 驱动的 Web 开发构建工具。在开发环境下基于浏览器原生 ES imports 开发,它做到了本地快速开发启动, 在生产环境下基于 Rollup 打包。快速的冷启动,不需要等待打包操作; 即时的热模块更新,替换性能和模块数量的解耦让更新飞起; 真正的按需编译,不再等待整个应用编译完成,这是一个巨大的改变。
官网地址
代码如下:
npm init vite-app
cd
npm install
npm run dev
新的option, 所有的组合API函数都在此使用, 只在初始化时执行一次
函数如果返回对象, 对象中的属性或方法, 模板中可以直接使用
- 作用: 定义一个数据的响应式
- 语法: const xxx = ref(initValue):
- 创建一个包含响应式数据的引用(reference)对象
- js中操作数据: xxx.value
- 模板中操作数据: 不需要.value
- 一般用来定义一个基本类型的响应式数据
{{count}}
- 作用: 定义多个数据的响应式
- const proxy = reactive(obj): 接收一个普通对象然后返回该普通对象的响应式代理器对象
- 响应式转换是“深层的”:会影响对象内部所有嵌套的属性
- 内部基于 ES6 的 Proxy 实现,通过代理对象操作源对象内部数据都是响应式的
name: {{state.name}}
age: {{state.age}}
wife: {{state.wife}}
vue2的响应式
核心:
- 对象: 通过defineProperty对对象的已有属性值的读取和修改进行劫持(监视/拦截)
- 数组: 通过重写数组更新数组一系列更新元素的方法来实现元素修改的劫持
问题:
- 对象直接新添加的属性或删除已有属性, 界面不会自动更新
- 直接通过下标替换元素或更新length, 界面不会自动更新 arr[1] = {}
//核心方法 -
Object.defineProperty(obj, prop, descriptor)
// obj:要在其上定义属性的对象。
// prop:要定义或修改的属性的名称。
// descriptor:将被定义或修改的属性描述符。
Object.defineProperty(对象, 属性, {
get () {},
set () {}
})
Vue3的响应式
核心:
- 通过Proxy(代理): 拦截对data任意属性的任意(13种)操作, 包括属性值的读写, 属性的添加, 属性的删除等...
- 通过 Reflect(反射): 动态对被代理对象的相应属性进行特定的操作
new Proxy(data, {
// 拦截读取属性值
get (target, prop) {
return Reflect.get(target, prop)
},
// 拦截设置属性值或添加新属性
set (target, prop, value) {
return Reflect.set(target, prop, value)
},
// 拦截删除属性
deleteProperty (target, prop) {
return Reflect.deleteProperty(target, prop)
}
})
proxy.name = 'tom'
Proxy 与 Reflect
setup执行的时机
- 在beforeCreate之前执行(一次), 此时组件对象还没有创建
- this是undefined, 不能通过this来访问data/computed/methods / props
- 其实所有的composition API相关回调函数中也都不可以
setup的返回值
- 一般都返回一个对象: 为模板提供数据, 也就是模板中可以直接使用此对象中的所有属性/方法
- 返回对象中的属性会与data函数返回对象的属性合并成为组件对象的属性
- 返回对象中的方法会与methods中的方法合并成功组件对象的方法
- 如果有重名, setup优先
- 注意:
- 一般不要混合使用: methods中可以访问setup提供的属性和方法, 但在setup方法中不能访问data和methods
- setup不能是一个async函数: 因为返回值不再是return的对象, 而是promise, 模板看不到return对象中的属性数据
setup的参数
- setup(props, context) / setup(props, {attrs, slots, emit})
- props: 包含props配置声明且传入了的所有属性的对象
- attrs: 包含没有在props配置中声明的属性的对象, 相当于 this.$attrs
- slots: 包含所有传入的插槽内容的对象, 相当于 this.$slots
- emit: 用来分发自定义事件的函数, 相当于 this.$emit
{{n}}
{{m}}
msg: {{msg}}
msg2: {{$attrs.msg2}}
是Vue3的 composition API中2个最重要的响应式API
ref用来处理基本类型数据, reactive用来处理对象(递归深度响应式)
如果用ref对象/数组, 内部会自动将对象/数组转换为reactive的代理对象
ref内部: 通过给value属性添加getter/setter来实现对数据的劫持
reactive内部: 通过使用Proxy来实现对对象内部所有数据的劫持, 并通过Reflect操作对象内部数据
ref的数据操作: 在js中要.value, 在模板中不需要(内部解析模板时会自动添加.value)
App
m1: {{m1}}
m2: {{m2}}
m3: {{m3}}
computed函数:
- 与computed配置功能一致
- 只有getter
- 有getter和setter
watch函数
- 与watch配置功能一致
- 监视指定的一个或多个响应式数据, 一旦数据变化, 就自动执行监视回调
- 默认初始时不执行回调, 但可以通过配置immediate为true, 来指定初始时立即执行第一次
- 通过配置deep为true, 来指定深度监视
watchEffect函数
- 不用直接指定要监视的数据, 回调函数中使用的哪些响应式数据就监视哪些响应式数据
- 默认初始时就会执行第一次, 从而可以收集需要监视的数据
- 监视数据发生变化时回调
App
fistName:
lastName:
fullName1:
fullName2:
fullName3:
vue2的生命周期
与 2 版本生命周期相对应的组合式 API
新增的钩子函数
组合式 API 还提供了以下调试钩子函数:
msg: {{msg}}
App
import { ref, onMounted, onUnmounted } from 'vue'
/*
收集用户鼠标点击的页面坐标
*/
export default function useMousePosition () {
// 初始化坐标数据
const x = ref(-1)
const y = ref(-1)
// 用于收集点击事件坐标的函数
const updatePosition = (e: MouseEvent) => {
x.value = e.pageX
y.value = e.pageY
}
// 挂载后绑定点击监听
onMounted(() => {
document.addEventListener('click', updatePosition)
})
// 卸载前解绑点击监听
onUnmounted(() => {
document.removeEventListener('click', updatePosition)
})
return {x, y}
}
把一个响应式对象转换成普通对象,该普通对象的每个 property 都是一个 ref
App
foo: {{foo}}
bar: {{bar}}
foo2: {{foo2}}
bar2: {{bar2}}
举例:利用ref函数获取组件中的标签元素
App
---