参考答案:
1. performance: 性能比vue2.x块1.2~2倍;
2. Tree shaking support: 按需编译,体积比vue2.x更小;
3. Composition API: 组合API(类似React Hooks);
4. Fragment, Teleport, Suspense: 更先进的组件;
5. Better TypeScript support: 更好的 ts 支持;
6. Custom Render API: 暴露了自定义渲染的API;
解析:
一,performance: 性能比vue2.x块1.2~2倍;
diff算法的优化
render阶段的静态提升(render阶段指生成虚拟dom树的阶段)
事件侦听缓存
二,Tree shaking support: 按需编译,体积比vue2.x更小;
在vue3中,可以如下面这样引用vue的功能函数,如果你的项目没有用到watch,那编译时就会把tree shaking掉。
import { computed, watch, nextTick } from "vue";
利用的就是 ES6 模块系统import/export。
三,Composition API: 组合API(类似React Hooks);
composition-api 是一个 Vue3 中新增的功能,它的灵感来自于 React Hooks ,是比 mixin 更强大的存在。 composition-api 可以提高代码逻辑的可复用性,从而实现与模板的无关性;同时使代码的可压缩性更强。另外,把 Reactivity 模块独立开来,意味着 Vue3.0 的响应式模块可以与其他框架相组合。
如上图,composition-api
把复杂组件的逻辑抽地更紧凑,而且可以将公共逻辑进行抽取。
四,Fragment, Teleport, Suspense: 更先进的组件;
在书写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>
同样的,这和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>
五,Better TypeScript support: 更好的 ts 支持;
import { defineComponent, ref, PropType, reactive } from 'vue'
import { Student } from '../store'
export default defineComponent({
props: {
success: { type: String },
student: {
type: Object as PropType<Student>,
required: true
}
},
setup() {
const year = ref(2020)
const state = reactive({ count: 3 });
function handleClick() {
state.count++;
}
return { year, state, handleClick };
}
})
六,Custom Render API: 暴露了自定义渲染的API;
下面我们可以看到vue2和vue3的入口写法有所不同
// vue2
import Vue from 'vue'
import App from './App.vue'
new Vue({ => h(App)}).$mount('#app')
// vue3
const { createApp } from 'vue'
import App from "./src/App"
createApp(App).mount(('#app')
vue官方实现的 createApp 会给我们的 template 映射生成 html 代码,但是要是你不想渲染生成到 html ,而是要渲染生成到 canvas 之类的不是html的代码的时候,那就需要用到 Custom Renderer API 来定义自己的 render 渲染生成函数了。
// 你自己实现一个createApp,比如是渲染到canvas的。
import { createApp } from "./runtime-render";
import App from "./src/App"; // 根组件
createApp(App).mount('#app');
在使用webpack作为开发构建工具时,npm run dev都要等一会,项目越大等的时间越长。热重载页有几秒的延迟,但是如果用vite来做vue3的开发构建工具,npm run dev 秒开,热重载也很快。这种开发体验真是很爽,拒绝等待。
vite的原理还是用了浏览器支持import关键字了,启动项目不用webpack构建工具先构建了,浏览器直接请求路由对应的代码文件,代理服务器针对单个文件进行编译并返回。如果请求的文件里还import了其他文件,同理浏览器继续发请求,代理服务器返回。就这样实现了npm run dev时无需编译,实时请求实时编译。
其他的,数据监听方式变成了Proxy,消除了Object.defineProperty现有的限制(例如无法检测新的属性添加),并提供更好的性能。
vue3解决了vue2的一些问题,大型应用的性能问题、ts支持不友好问题,自定义渲染API解决体系架构存在的问题,如果在vue3的基础上实现weex框架会好很多。也做出了很多优化,Compostion API让代码的组织形式更好。vite开发构建工具让开发体验更好,Tree shaking让包更小、性能更优。
总的来说vue3还是非常棒的,带来了很多非常好的新特性。