为什么vue3中去掉了vue构造函数?

为什么

当在一些特殊的情况下Vue的的构造函数会遇到一些问题:例如一个页面有多个Vue应用,全局的混入和组件以及use(引用)就会出现问题

以vue2的方式在一个页面使用多个vue应用示例代码

  1. <!-- vue2 -->
  2. <div id="app1"></div>
  3. <div id="app2"></div>
  4. <script>
  5. Vue.use(...); // 此代码会影响所有的vue应用
  6. Vue.mixin(...); // 此代码会影响所有的vue应用
  7. Vue.component(...); // 此代码会影响所有的vue应用
  8. new Vue({
  9. // 配置
  10. }).$mount("#app1")
  11. new Vue({
  12. // 配置
  13. }).$mount("#app2")
  14. </script>

vue3中,去掉了Vue构造函数,转而使用createApp创建vue应用

  1. <!-- vue3 -->
  2. <div id="app1"></div>
  3. <div id="app2"></div>
  4. <script>
  5. // 创建一个vue应用,使用一些插件(只会对该应用有用,其它vue应用不会应用),混入一些配置,全局注册一些组件,挂载到该元素上,只会对该应用有效
  6. createApp(根组件).use(...).mixin(...).component(...).mount("#app1")
  7. // 创建一个vue应用,将其挂载到元素上
  8. createApp(根组件).mount("#app2")
  9. </script>

vue构造函数的api提到啦vue实例中去

更多vue应用的api:https://v3.vuejs.org/api/application-api.htm

**

标椎回答

vue2的全局构造函数带来了诸多问题:
1. 调用构造函数的静态方法会对所有vue应用生效,不利于隔离不同应用
2. vue2的构造函数集成了太多功能,不利于tree shaking,vue3把这些功能使用普通函数导出,能够充分利用tree shaking优化打包体积(vue3的导入是具名导入,会优化打包体积,将有用的打包进去,没有用的不会打包进去)
3. vue2没有把组件实例和vue应用两个概念区分开,在vue2中,通过new Vue创建的对象,既是一个vue应用,同时又是一个特殊的vue组件。vue3中,把两个概念区别开来,通过createApp创建的对象,是一个vue应用,它内部提供的方法是针对整个应用的,而不再是一个特殊的组件。

vue3数据响应式的理解

组件实例中的API

vue3中,组件实例是一个Proxy,它仅提供了下列成员,功能和vue2一样
属性:https://v3.vuejs.org/api/instance-properties.html
方法:https://v3.vuejs.org/api/instance-methods.html
vue3实例中的API跟vue2的差不多,比vue2少啦点,只不过带_ 看不到啦
_ 是vue要用的会禁止开发者使用,但在vue2依然可以使用,当在vue3由于this是一个代理,故禁止使用的api(例如带_ )不会显示且还无法使用

对比数据响应式

vue2和vue3均在相同的生命周期完成数据响应式,但做法不一样
为何去掉Vue构造函数,vue3的数据响应式的理解 - 图1
vue2会对所有属性使用递归遍历,对每一个属性使用Object.defineProperty重新定义,但是Object.defineProperty会使部分数据无法实现响应式,故使用$set 与 $delete 来实现
vue3使用es6的proxy 看下方的标椎答案

标椎答案

vue3不再使用Object.defineProperty的方式定义完成数据响应式,而是使用Proxy。
除了Proxy本身效率比Object.defineProperty更高之外,由于不必递归遍历所有属性,而是直接得到一个Proxy。所以在vue3中,对数据的访问是动态的,当访问某个属性的时候,再动态的获取和设置,这就极大的提升了在组件初始阶段的效率。
同时,由于Proxy可以监控到成员的新增和删除,因此,在vue3中新增成员、删除成员、索引访问等均可以触发重新渲染,而这些在vue2中是难以做到的。