vue2和vue3区别

162 阅读3分钟
对比vue2vue3
脚手架命令式可视化脚手架
组件通信见下文见下文
数据监听watch, computedwatch, watchEffer, computed
双向绑定Object.definePropertyProxAPI
生命周期
api选项式组合式

一、双向绑定更新

vue2的双向绑定是利用 ES5 的一个API, Object.defineProperty()对数据进行劫持,结合发布订阅模式来实现

vue3中使用了 ES6 的ProxyAPI对数据代理,通过reactive()函数给每一个对象都包一层 Proxy 监听属性的变化,从而实现对数据的监控

使用 proxy的优势
1. defineProper只能监听某个属性,不能对全对象监听,
可以省去for in、闭包等内容来提升效率(直接绑定整个对象即可)
2.可以监听数组,不用再去单独的对数组进行异步操作,
通过 Proxy 可以直接拦截所有对象类型数据的操作,完美支持对数组的监听

二、实例化

Vue2.X中new出的实例对象,所有的东西都在这个vue对象上,这样无论用到还是没用到,都会跑一遍,不仅消耗性能,也增加了用户加载时间

vue3.0中可以用ES module imports按需引入,如:keep-alive内置组件、v-model指令,等等,不仅开发起来更加的便捷,减少了内存消耗,同时减少了用户加载时间,优化用户体验

三、 生命周期

vue2vue3描述
beforeCreatesetup实例创建前
createdsetup实例创建前
beforeMountonBeforeMountDOM挂载前调用
mountedonMountedDOM挂载完成调用
beforeUpdateonBeforeUpdate数据更新前调用
updatedonUpdate数据更新后调用
beforeDestoryonBeforeUnmount组件销毁前调用
destoryedonUnmounted组件销毁完调用

四、获取props vue2在script代码块可以直接获取props,vue3通过setup指令传递

vue2: console.log('props', this.xxx)
vue3:  setup(props, context){ console.log('props', props) }

五、数据的方法的定义

Vue2使用的是选项API (Options API),Vue3使用的合成型API(Composition API)

vue2:

data() { return {} }, methods: {}

vue3

数据和方法都定义在 setup 中,并统一进行 return{}

六、给父组件传值emit

vue2: this.$emint()
vue3: setup(props, context) { context.emit() }

七、watchEffect

Vue3中除了watch,还引入副作用监听函数watchEffect,它和 React 中的 useEffect 很像,只不过 watchEffect 不需要传入依赖

watchEffect会立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数

computed和watch所依赖的数据必须是响应式的。Vue3引入了 watchEffect,相当于 watch 的依赖源和回调函数合并,当任何你有用到的响应式依赖跟新时,该回调函数就会立刻执行,不同于 watch 的是 watchEffect 的回调函数会被立即执行,既({ immediate: true })

八、组件通信

方式Vue2Vue3
父传子propsprops
子传父$emitsemits
父传子$attrsattrs
子传父$listeners无(合并到attrs方式)
父传子provideprovide
子传父injectinject
子组件访问父组件$parent
父组件访问子组件$children
父组件访问子组件$refexpose&ref
兄弟传值EventBusmitt
注意
props中数据是单项的,既子组件不可改变父组件传来的值
在组合API中,如果想在子组件中用其他变量接收props的值时,需要使用toRef将props中的属性转为响应式

attrs和insteners
子组件使用 $attrs 可以获得父组件除了 props 专递的属性和特性绑定属性(class 和 style)之外的所有属性
子组件使用 $listeners 可以获得父组件(不含 .native修饰器的)所有v-on事件监听器,在Vue3中的attrs不仅可以获得父组件传来的属性,也可以获得父组件v-on事件监听器

九、路由

vue2和vue3路由常见功能只是在写法上有些区别:

vue3的 beforeRouteEnter 作为路由守卫的示例是因为他在 setup语法糖中是无法使用的;

setup中组件实例已经创建,时能够获得到组件实例的。而 beforeRouteEnter是再进入路由前触发的,此时组件还未创建,所以无法用在setup中的;

如果想在setup语法糖中使用则需要再写一个 script 如下

<script>
export default {
  beforeRouteEnter(to, from, next) {
    // 在渲染组件的对应路由被 confirm 前调用
    next()
  }
}
</script>

vue3路由写法

<script>
import { defineComponent } from 'vue'
import { useRoute, useRouter } from 'vue-router'
export default defineComponent({
  beforeRouteLeave((to, from, next)=>{
    // 离开当前组件 触发
    next()
  }),
  beforeRouteLeave((to, from, next)=>{
    // 离开当前组件 触发
    next()
  }),
  setup() {
    const router = useRouter()
    const route = useRoute()
    const toPage = () => {
      router.push(xxx)
    }
    
    // 获取params
    route.params
    // 获取query
    route.query
    return {
      toPage
    }
  }
})
</script>

vue2路由写法

<script>
export default {
  beforeRouteEnter(to, from, next) {
    // 在渲染该组件的对应路由 confirm 前调用
    netx()
  },
  beforeRouteEnter(to, from, next) {
    // 在渲染该组件的对应路由 confirm 前调用
    netx()
  },
  beforeRouteLeave((to, from, next) => {
    // 离开当前组件 触发
    netx()
  }),
  beforeRouteLeave((to, from, next) => {
    // 离开当前组件 触发
    netx()
  }),
  methods: {
    toPage() {
      this.$router.push(xxx)
    }
  },
  created() {
    // 获取params
    this.$route.params
    // 获取query
    this.$route.query
  }
}
</script>

十、总结

vue2和vue3比较还有很多不一样的地方,比如setup语法糖的形式最为便捷且更加符合开发者习惯

其他总结

1.因为改成组合式api所以没有this

2.生命周期没有creat,setup等同于create,卸载改成unmount

3.vue3中v-if的优先级高于v-for

4.根实例的创建从new app变成createApp方法

5.一些全局注册,比如minxin,注册全局组件,use改成了用app实例调用,而不是vue类调用

6.新增了传送门teleport组件

7.template模版可以不包在一个根div里