Vue2是一个非常优秀的框架, 好上手, 学习曲线也比较平滑. 也是目前使用最广泛的框架之一
为什么尤大要重构, 推出Vue3呢?
大家有兴趣可以看一下这篇专访
总结起来就是
更适应当下的技术环境
要知道, 每个技术都是有局限性的. 某一方面的提升往往意味着另一方面的牺牲.
使用TS重构
应用了JS的新特性Proxy重写响应式
性能的提升
Composition API
如果一定要选出一个最大的区别, 应该是Composition API
使用Options API实现一个功能, 需要在不同的地方编写代码
状态(数据)在data中定义
方法在methods中定义
计算属性
...
当新添加一个功能时, 代码的组织会比较零散
引入vue.js
创建页面容器
实例化对象
Document
{{msg}}
data必须是一个函数
之前Vue2中的配置项依然可以使用
练习
在Vue3中, 为了向前兼容, 不影响之前的配置项
创造了一个新的配置项setup, 所有的Composition API都可以在setup中使用
:::info
setup是一个函数
返回一个对象, 对象中定义的属性, 方法在模板中直接使用
返回渲染函数(不常用)
:::
示例
Document
{{uname}} -- {{age}}
{{ sayHi() }}
这样写的代码会丢失响应式
:::warning
** 注意**
不要将vue2的语法和vue3的语法混用!!
:::
这里我们安装最新的vue devtools工具, 可以同时支持vue2和vue3
通过调试工具, 我们发现定义的数据并不是响应式的.
在setup函数中, 如果要实现响应式, 需要借助
ref函数: 实现普通类型数据的响应式
reactive函数: 实现引用类型数据的响应式
使用步骤
导入ref函数
使用ref函数定义数据
示例
Document
{{msg}}
通过devtools修改
:::info
需求
点击按钮修改姓名
:::
如何使用代码实现修改数据呢?
示例
Document
姓名:{{uname}}
练习
使用setup语法(Composition API)实现计数器
对于引用类型数据. 如对象, 数组
使用ref函数比较麻烦, 在访问时, 每次都需要.value
示例
Document
姓名:{{stu.name}}
区别
从定义的角度
ref: 主要用于基本数据类型
reactive: 主要用于引用数据类型
从实现的角度
ref: 通过Object.defineProperty的get和set来实现响应式
reactive: 通过Proxy来实现数据劫持, 通过reflect操作内部属性
从使用的角度
ref: 需要通过.value操作数据
reactive: 不需要.value, 直接操作数据
使用步骤
导入computed函数
在setup中使用
示例
Document
姓:
名:
全名: {{fullName}}
优化
Document
姓:
名:
全名: {{person.fullName}}
在Vue3中, 将watch也定义成一个组合式API
使用步骤
导入watch函数
使用watch函数监听
由于定义数据有两种方式. 监听时也分两种情况
监视ref定义的数据
监视reactive定义的数据
示例
Document
当前计数为: {{count}}
Document
姓名: {{stu.name}}
年龄: {{stu.age}}
对于引用类型, watch不能监视到oldValue
Document
姓名: {{stu.name}}
年龄: {{stu.age}}
Vue3的生命周期在调用mount('#app')后开始
setup在所有生命周期函数执行前调用, 因此, 在setup()中this指向window, 没有批向当前实例
setup主要完成composition API的初始化. created完成OptionsAPI的初始化
在setup中最常用的生命周期有两个: onMounted和onBeforeUnmount
示例
Document
我是vm根实例
创建Vue3.0项目有这样两种方式
使用vue-cli
使用vite
vue create vue3-project
npm create vite
使用vite初始化项目
hooks本质上还是一种函数, 将多个Composition API封装, 实现某个特定功能
解耦
复用
示例
将特定功能封装到一个单独的文件usePoint.js
import { reactive, onMounted, onBeforeUnmount } from 'vue'
export default function usePoint() {
const point = reactive({
x: 0,
y: 0,
})
function onClick(event) {
point.x = event.pageX
point.y = event.pageY
console.log(point.x, point.y)
}
onMounted(() => {
window.addEventListener('click', onClick)
})
onBeforeUnmount(() => {
window.removeEventListener('click', onClick)
})
return point
}
在需要时引入hooks函数
子组件
x的坐标: {{ point.x }}--y的坐标: {{ point.y }}