1. Performance
vue3在性能方面比vue2快了2倍。
- 重写了虚拟DOM的实现
- 运行时编译
- update性能提高
- SSR速度提高
2. Tree-shaking support
vue3中的核心api都支持了tree-shaking,这些api都是通过包引入的方式而不是直接在实例化时就注入,只会对使用到的功能或特性进行打包(按需打包),这意味着更多的功能和更小的体积。
3. Composition API
vue2中,我们一般会采用mixin来复用逻辑代码,用倒是挺好用的,不过也存在一些问题:例如代码来源不清晰、方法属性等冲突。基于此在vue3中引入了Composition API(组合API),使用纯函数分隔复用代码。和React中的hooks的概念很相似。
- 更好的逻辑复用和代码组织
- 更好的类型推导
一个简单的例子
<template>
<div>X: {{ x }}</div>
<div>Y: {{ y }}</div>
</template>
<script>
import { defineComponent, onMounted, onUnmounted, ref } from "vue";
const useMouseMove = () => {
const x = ref(0);
const y = ref(0);
function move(e) {
x.value = e.clientX;
y.value = e.clientY;
}
onMounted(() => {
window.addEventListener("mousemove", move);
});
onUnmounted(() => {
window.removeEventListener("mousemove", move);
});
return { x, y };
};
export default defineComponent({
setup() {
const { x, y } = useMouseMove();
return { x, y };
}
});
</script>
4. Fragment、Teleport、Suspense
新增的三个组件。
Fragment
在书写vue2时,由于组件必须只有一个根节点,很多时候会添加一些没有意义的节点用于包裹。Fragment组件就是用于解决这个问题的(这和React中的Fragment组件是一样的
)。
这意味着现在可以这样写组件了。
/* App.vue */
<template>
<header>...</header>
<main v-bind="$attrs">...</main>
<footer>...</footer>
</template>
<script>
export default {};
</script>
或者这样
// app.js
import { defineComponent, h, Fragment } from 'vue';
export default defineComponent({
render() {
return h(Fragment, {}, [
h('header', {}, ['...']),
h('main', {}, ['...']),
h('footer', {}, ['...']),
]);
}
});
Teleport
Teleport其实就是React中的Portal。Portal 提供了一种将子节点渲染到存在于父组件以外的 DOM 节点的优秀的方案。
一个 portal 的典型用例是当父组件有 overflow: hidden 或 z-index 样式时,但你需要子组件能够在视觉上“跳出”其容器。例如,对话框、悬浮卡以及提示框。
/* App.vue */
<template>
<div>123</div>
<Teleport to="#container">
Teleport
</Teleport>
</template>
<script>
import { defineComponent } from "vue";
export default defineComponent({
setup() {}
});
</script>
/* index.html */
<div id="app"></div>
<div id="container"></div>
Suspense
同样的,这和React中的Supense是一样的。
Suspense 让你的组件在渲染之前进行“等待”,并在等待时显示 fallback 的内容。
// App.vue
<template>
<Suspense>
<template #default>
<AsyncComponent />
</template>
<template #fallback>
Loading...
</template>
</Suspense>
</template>
<script lang="ts">
import { defineComponent } from "vue";
import AsyncComponent from './AsyncComponent.vue';
export default defineComponent({
name: "App",
components: {
AsyncComponent
}
});
</script>
// AsyncComponent.vue
<template>
<div>Async Component</div>
</template>
<script lang="ts">
import { defineComponent } from "vue";
const sleep = () => {
return new Promise(resolve => setTimeout(resolve, 1000));
};
export default defineComponent({
async setup() {
await sleep();
}
});
</script>
5. Better TypeScript support
在vue2中使用过TypesScript的童鞋应该有过体会,写起来实在是有点难受。vue3则是使用ts进行了重写,开发者使用vue3时拥有更好的类型支持和更好的编写体验。
6. Custom Renderer API
这个api定义了虚拟DOM的渲染规则,这意味着使用自定义API可以达到跨平台的目的。下面是一个简单的例子。
// App.js
import { defineComponent, h } from 'vue';
export default defineComponent({
render() {
return h('Article', {
onClick() {
console.log('点击文章');
}
}, [
h('Title', { align: 'center' }, '这是文章标题')
]);
}
});
// main.js
import { createRenderer } from 'vue';
import App from './App.js';
import './assets/index.css';
const { createApp } = createRenderer({
createElement(type) {
let nodeType = 'div';
switch(type) {
case 'Article': nodeType = 'article'; break;
case 'Title': nodeType = 'h1'; break;
case 'Content': nodeType = 'p'; break;
}
return document.createElement(nodeType);
},
insert(child, parent, anchor) {
parent.insertBefore(child, anchor || null);
},
setElementText(node, text) {
node.textContent = text;
},
patchProp(el, key, prevValue, nextValue) {
console.log(el, key, prevValue, nextValue);
switch(key) {
case 'onClick':
el.addEventListener('click', nextValue);
break;
default:
el.setAttribute(key, nextValue);
}
}
});
createApp(App).mount(document.querySelector('#app'));
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。