vue2 基础过渡到 vue3
- 风格切换,更类似于原始风格 (SFC single file component), 倾向于单页面, 内包含(html, js, css)
vue
<html>
xxx
</html>
<script setup>
import xxx;
function a = ()=> {
console.log(123);
}
</script>
<style>
</style>
-
优化生命周期,简化API, 原本vue2中有很多生命周期,vue3中简化为一个 OnMounted, 其他旧的API也可以使用,但重要性下降
-
启用新的API,定义变量,变量使用
- ref()
- reactive()
- computed()
- watch()
-
js 与 html 深度融合,更加接近与 jsx 风格,使得js 在html 中直接编写,不需要定义函数然后再引用
- react框架 JSX 风格
-
保留 v 开头的指令
- v-if/v-else-if/v-else
- v-for
- v-show
-
新的参数与回调函数
- define
- vue文档(参数与回调)
- 通常,父组件 修改 子组件,通过参数
- 子组件修改父组件,通过回调
- define
-
依赖注入
- A -> B ->C, A 将参数给B, B 再给 C
- 现在通过依赖注入,A --> C, 直接将参数给 C,关键词 provide inject
更多API
vue3 的设计理念
- 扁平化(页面也是组件,逻辑也是组件,都可以复用)
- 向 React 学习(借鉴罢了)
- 快快快,还是快(效率至上)
- 站在巨人的肩膀(别人都写好了, 你还要再造一次轮子吗)
扁平化
javascript
// a.js
<template>
<div>父组件</div>
<A_children :count="count" @addCount="addCount"></A_children>
</template>
<script setup>
import {ref} from "vue";
import A_children from "./b.vue";
let count = ref(1);
const addCount = () => {
count.value++;
}
</script>
// b.js
<template>
<div>{{ count }}</div>
<div>
<button @click="$emit('addCount')">加1</button>
</div>
</template>
<script setup>
import {defineProps, defineEmits} from "vue";
// 参数
defineProps(["count"]);
// 回调函数
defineEmits(["addCount"])
</script>
- 通过 hooks(组合式API), 全局状态管理,来实现该功能
javascript
// hookDemo.vue
<template>
<div>父组件:
<div>{{ count }}</div>
</div>
<HookDemo2></HookDemo2>
</template>
<script setup>
import {useCount} from "./hooks";
import HookDemo2 from "./hookDemo2.vue";
const {count} = useCount();
</script>
// hooksDemo2.vue
<template>
<div>子组件: {{ count }}</div>
<div>
<button @click="addCount()">加1</button>
</div>
</template>
<script setup>
import {useCount} from "./hooks";
const {count, addCount} = useCount();
</script>
// hooks.js
import {ref} from "vue";
// 注意: 该变量声明需要在 组合式API 外面
const count = ref(1);
export const useCount = () => {
// 注意: count 写在这里,父组件将不会更新
// const count = ref(1);
const addCount = () => {
count.value++;
}
return {count, addCount}
}
比较说明
- 父子组件这种写法是 vue2 中比较常用的写法
- hooks 这种写法,避开了父子组件之间的关系,不仅可应用在相同组件,有显示count状态的地方,都可以通过引入的方式,快速同步
- 思考一个问题, 如果有多个页面都需要这个逻辑,或者 A 组件中有子组件 B, B 组件中有子组件C, 哪种方式更好
性能比较
- 通常,vue2 的父子组件需要遵循数据单向流动,在hooks 中,无需考虑这种写法,但开拓了一个额外的空间,保存该数据,并且在此之上包装了一些其他方法
- 组合式API 在数据共享上,做了一些优化,例如数据响应式逻辑,虚拟DOM更新逻辑
- 所以,性能上没有明显区别
组合式API VS 选项式API
- 组合式API 基于 react hooks 的理念, 将功能相近的逻辑写成一个独立文件(hook), 灵活组合成自己想要的功能,快速构建一个页面,但是需要前期铺垫,并且为该hook考虑到给未来页面使用的参数、方法等,保持一些通用性
- 选项式API,即页面用到的所有逻辑都放在一起,这样做的好处是一目了然,所有函数功能都在一起,缺点是如果其他页面也有一些共同的逻辑,需要重新写一遍
- 比较说明:两者并不是水火不容,有可能一个项目中两种风格并存,更多是一种理念和开发哲学的不同。
- 发展趋势: 从vue2 到 vue3,react早期版本到现在的版本来看,Hooks 组合式API开发的理念未来会越来越广泛地应用在项目中
图图图图图(这里缺少一个图)
网络请求 + 状态管理
- 假设有一个功能,用户点击 + 号,更新数量,点击一次发送网络请求给后端,并重新获取数量,显示在页面上
- vue2(伪代码)
less
{{count}}
button(@click="add")
func update();
func get();
func add(){
count = update().then(add());
};
- vue3 + vueQuery (伪代码)
kotlin
import {useMutation, useQuery, useQueryClient} from '@tanstack/vue-query'
import {get, update} from "@/demos/hookRemote/apis";
export const useCount = () => {
const queryClient = useQueryClient()
const {mutate,status}= useMutation({
mutationKey: ["addCount"],
mutationFn: () => update(),
onSuccess: () => {
queryClient.invalidateQueries({queryKey: ["get"]})
}
})
const { data, isFetching } = useQuery({
queryKey: ["get"],
queryFn: async() => {
const data = await get();
return data.data.count;
}
})
return {data, isFetching, status, mutate}
}
- 父组件
xml
<template>
<div>父组件:
<span>{{ data }}</span>
<div>{{isFetching ? "获取中" : "获取成功"}}</div>
<div>{{status}}</div>
<div @click="mutate"><button>父组件添加</button></div>
</div>
<hr/>
<HookDemo2></HookDemo2>
</template>
<script setup>
import HookDemo2 from "@/demos/hookRemote/hookDemo2.vue";
import {useCount} from "@/demos/hookRemote/hooks";
const {data, isFetching, status, mutate} = useCount();
</script>
- 子组件
xml
<template>
<div>子组件:
<span>{{ data }}</span>
<div>{{isFetching ? "获取中" : "获取成功"}}</div>
<div>{{status}}</div>
<div @click="mutate"><button>子组件添加</button></div>
</div>
</template>
<script setup>
import {useCount} from "@/demos/hookRemote/hooks";
const {data,isFetching,status,mutate} = useCount();
</script>
-
对比比较
-
vue3 通过状态管理 + axios, 将请求进行封装, 数据更新, 获取, 缓存, 统一被状态管理器进行管理
-
将数据对象进行抽象化, 页面的动作不再直接对服务器处理, 而是先改变状态, 状态管理自动的处理这些请求, 处理, 显示
-
优势在于,如果有多个页面依赖于这个数据对象(useXXX), 相同的逻辑直接调用, 数据直接展示即可,无需担心数据同步的问题
-
vue2 看起来比较直观,在页面功能比较简单时,文件依赖少,逻辑直观,只运用promise的概念处理,简单方便
-
service(API) --> JS --> 页面 (vue2)
-
service(API) --> 状态对象 --> 页面 (vue3)
-
-
总结
- 以前是 页面动作 触发 js 函数,函数调用 service 访问API
- 现在是 页面 修改了js 的状态,状态自动触发 service相关动作,并对相关动作进行延伸,可以再变更后,自动刷新数据,并记录其中的过程
- 以前主要是通过 promise 的then catch 进行动作,将loading 状态,数据赋值放在 promise 里边实现
- 现在 promise 的这个过程被弱化,程序员不需要关系相关的这些过程,只需要触发某个值的变化,query 对象会处理 成功或者失败,数据加载,请求状态记录的过程
全局状态管理(global state managers)
- 状态获取,更新,缓存,同步
hooks react 理念
React-query / Vue-Query (tanStack Query)
- 都出自TanStack大神,通俗来说,是服务器端的状态同步管理,能够实现页面更新后,后端也同步更新
- Query 官网
useQuery useMutation useQueryClient (Vue-Query) 使用
- 空白
pinia
- 空白
vuex
- 空白
组合式API VS 选项式API VS React Hooks
- cn.vuejs.org/guide/extra...
- 组合式函数(vue版本的hooks)约定用驼峰命名法命名,并以"use"作为开头。
- juejin.cn/post/706695...
状态、逻辑的复用(旧版本 mixin)
- 数据(状态)
- 函数(逻辑,功能)
墙裂推荐的功能、库、组件
- vueUse (组件社区,挑选满意的功能实现需求而不是自己写)
- lodash (对数据操作封装的库,免去数据处理中繁琐的js语法)