vue3.0来临,这些必须得会啦!
新特性
Performance
- 重写了虚拟DOM的实现(跳过静态节点,只处理动态节点)
- update性能提供1.3~2倍
- SSR速度提供了2~3倍
Tree shaking
- 可以将无用模块“剪辑”, 仅打包需要的
Fragment
- 不再限于模板中的单个节点
- 类似于react里的空节点<></>
<template>
<p> Count: {{ count }} </p>
<button @click="increment"> Increment </button>
<button @click="decrement"> Decrement </button>
</template>
<teleport>
- 将组件中渲染到页面任意一个 DOM 节点中
- 以前称为, 传送门, Alpha版本暂不能使用
- vue2是利用第三方插件完成的
<Teleport to="#modal-layer">
<div class="modal">hello</div>
</Teleport>
<Suspense>
-
可在嵌套层级中等待嵌套的异步依赖项
-
通常前后端交互是一个异步的过程: 默认我们提供一个加载中的动画,2.x版本我们通常用 v-if 来控制数据显示
-
这个还是比较实用的
<template> <Suspense> <template #default> 异步返回的数据 </template> <template #fallback> loading... </template> </Suspense>
TypeScript
- 更好的TypeScript支持
Custom Renderer API
- 自定义渲染器API
- 用户可以尝试WebGL自定义渲染器
Composition API
- 成为组合式API,替换原有的Options API
- 根据逻辑相关性组织代码,提供可读性和可维护性
- 更好的重用逻辑代码(避免mixins混入时命名冲突的问题)
- 但是依然可以延用Options API
- 这个对于使用是最大的变动
在2.0时代我们要把代码写到指定位置,我们理解为配置到指定的options ,称为Options API, 我们发现在项目代码少的情况下代码很清晰,如果代码量比较多就不太利于我们可读性维护性了,尤大大收到了这样的吐糟,预算3.0提供了componsition Api 称之为组合式API, 提供了一个setup, 是整个api的入口。 把特定功能的模块导入到setup里面,统一暴露出去来使用。
Proxy
- 响应式原理不再基于Object.defineProperty
基于vue/cli 配置3.0
github.com/vuejs/vue-n… vue-cli-plugin-vue-next vue-cli 版本需要> 4.3.1
npm install -g @cli/cli
vue --version
vue create xxx
vue add vue-next
基于vite配置3.0 -个人推荐
由作者you雨溪开发的web开发工具 github.com/vitejs/vite
- 基于浏览器原生ES imports的开发服务器(利用浏览器去解析imports, 在服务器端按需编译返回,完全跳过了打包这个概念,服务器随起随用) 同事不仅有Vue文件支持,还搞定了热更新,而且热更新的速度不会随着模块而变慢
npm init vite-app xxx
cd xxx
npm install
npm run dev
npm run build
掌握setup和响应式系统API
setup
setup 函数是一个新的组件选项,作为在组件内使用Composition API的入口点
- 初始化props和beforeCreate之间调用
- 可以接收props和context
- this在setup()中不可用
props是响应式的,可以基于watchEffect、watch监听,解构赋值后则无效
import { watchEffect } from 'vue';
export default {
props: {
title: String
},
// 初始化props和beforeCreate之间
setup(props) {
// props: 基于Proxy响应式数据
console.log(props);
watchEffect(() => {
console.log('title is:' + props.title)
})
}
}
ref
接收一个参数值并返回一个响应式且可改变的ref对象
- ref对象拥有一个指向内部值的单一属性.value
- 当ref在模板中使用的时候,它会自动解套,无需在模板内部额外书写value
- 一般处理
import { ref } from 'vue';
export default {
props: {
title: String
},
setup(props) {
// 构建响应式数据 一版处理简单值得响应式 原理:defineProperty
let supNum = ref(0),
oppNum = ref(0);
console.log(supNum);
console.log(supNum.value)
function change(lx) {
lx == 0? supNum.value++: oppNum.value++;
}
return {
supNum,
oppNum,
change
}
}
}
控制台输出:
reactive
接受一个普通对象然后返回该普通对象的响应式数据 等同于2.x Vue.observable()
- 响应式转换是“深层的”, 会影响对象内所有嵌套的属性
export default {
setup(props) {
// 响应式构建方案 reactive 基于Proxy数据深度的监听,以此构建响应式
let state = reactive({
supNum: 0,
oppNum: 0,
arr: [10, 20]
});
function change() {
state.arr[2] = 30; // 直接修改值
state.sum = 40; // 新增属性
}
return {
state,
change,
}
}
}
unref/toRef/toRefs/isRef/isProxy/isReactive/isReadonly
toRef/toRefs
把reactive 种每一项变为ref响应式数据 template 下可以直接使用
setup() {
let state = reactive({
supNum: 0,
oppNum: 0
});
console.log('toRef:', toRef(state, 'supNum')); // 转单一属性
console.log('toRefs:', toRefs(state)); // 转所有属性
return {
state
}
}
readonly
传入一个对象(响应式数据)或ref, 返回一个原始对象的只读代理 一个只读的代理是“深层的”,对象内任何嵌套的属性也都只是只读的
setup(props) {
let xxxObj = reactive({
x: 10,
y: {
z: 20
}
})
let xxxObj2 = readonly(xxxObj);
console.log(xxxObj2.y.z); // 修改会触发xxxObj2上的监听
xxxObj2.y.z = 100; // 无法修改会被警告
return {
xxxObj
}
警告如图:
computed
传入一个getter函数,返回一个默认不可手动修改的ref对象
let count = ref(1);
let plusOne = computed(() => count.value+1)
console.log(plusOne.value) // 2
plusOne.value++; // 错误
或者传入一个拥有get 和 set 函数的对象,创建一个可手动修改的计算属性
const count = ref(1);
let plusOne = computed({
get: () => count.value + 1,
set: val => {
count.value = val -1;
}
})
plugOne.value = 1;
console.log(count.value); //0
watchEffect
立即执行传入一个函数,并响应式追踪其依赖,并在其依赖变更时重新运行该函数 类似于2.x的watch 下的immediate: true
import { watchEffect } from 'vue';
export default {
props: {
title: String
},
setup(props) {
watchEffect(() => {
console.log('title is:' + props.title)
})
}
}
watch
watch Api完全等效于2.x this.$watch
- watch 需要监听特定的数据源, 并在回调函数中执行副作用
- 默认情况下是懒执行的,也就是说仅在监听的源变更时才执行回调
...
setup(props) {
let state = reactive({
supNum: 0,
oppNum: 0
})
// 写法1:
watch(state, () => {
console.log(state.supNum);
})
// 写法2: 只监听state下的supNum, 需要这样写
watch(
() => state.supNum,
() => {
console.log(state.supNum);
}
)
let x = ref(0),
y = ref(0);
// 写法3:监听多个
watch([x, y], ([x, y], [prevX, prevY]) => {
console.log(x, prevX);
console.log(y, prevY);
})
...
}
模板refs
当使用组合式API时,reactive refs 和 template refs 的概念是一样的 和2.x 那个一样, 就是取dom节点的
<template>
<div ref="root"></div>
</template>
<script>
import { ref, onMounted } from 'vue';
export default {
props: {
title: String
},
setup(props) {
const root = ref(null);
onMounted(() => {
console.log(root.value);
})
return {
root
}
}
}
</script>
声明周期函数
可以直接导入onXXX 一族的函数来注册生命周期钩子
- 这些生命周期钩子注册函数只能在sestUp()期间同步使用
- 在卸载组件时,生命周期钩子内部同步创建的监听器和计算状态也将删除 2.x版本 -> 3.0版本对照
beforeCreated-> 使用setup()created-> 使用setup()- beforeMount -> 使用setup()
- mounted -> onMounted
- beforeUpdate -> onBeforeUpdate
- update -> onUpdated
- beforeDestory -> onBeforeUnmount
- destoryed -> onUnmounted
- errorCaptured -> onErrorCaptured
v3.0使用哪个api,就引入哪个,打包时也将只打包使用过的api. 更轻便
-
如果想在2.x中体验vue3.0 ,可以通过@vue/omposition这个库。
与 React Hooks 相比
基于函数的组合式 API 提供了与 React Hooks 同等级别的逻辑组合能力,但是与它还是有很大不同:组合式 API 的 setup() 函数只会被调用一次,这意味着使用 Vue 组合式 API 的代码会是:
-
一般来说更符合惯用的 JavaScript 代码的直觉;
-
不需要顾虑调用顺序,也可以用在条件语句中;
-
不会在每次渲染时重复执行,以降低垃圾回收的压力;
-
不存在内联处理函数导致子组件永远更新的问题,也不需要 useCallback;
-
不存在忘记记录依赖的问题,也不需要“useEffect”和“useMemo”并传入依赖数组以捕获过时的变量。Vue 的自动依赖跟踪可以确保侦听器和计算值总是准确无误。