总结vue2-vue3发生的变化

186 阅读4分钟

特点

vue2 的特点

1. 易用 (容易上手)

2. 灵活 (可以在一个库或者一个框架中使用)

3. 高效 ( 20kB min+gzip 运行大小 超快虚拟 DOM 最省心的优化)

vue3的特点

1. 易用 (容易上手)

2. 灵活多变 (丰富的、可渐进式集成的生态系统,可以根据应用规模在库和框架间切换自如。)

3. 性能出色 (经过编译器优化、完全响应式的渲染系统,几乎不需要手动优化。)

特点上最大的区别是vue3增加了编译器优化

Vue3是一个编译时+运行时的框架,它在保持灵活性的基础上,还能够通过编译手段分析用户提供的内容,从而进一步提升更新性能

监听事件

父组件可以通过 v-on 或 @ 来选择性地监听子组件上抛的事件,

子组件可以通过调用内置的 $emit 方法,通过传入事件名称来抛出一个事件:

在vue3中新增了emits来声明需要抛出的事件
这个 emits 选项还支持对象语法,它允许我们对触发事件的参数进行验证:

export default {
  emits: {
    submit(payload) {
      // 通过返回值为 `true` 还是为 `false` 来判断
      // 验证是否通过
    }
  }
}

子组件
<template>
  <div class="blog-post">
    <h4>{{ title }}</h4>
    <button @click="$emit('enlarge-text')">Enlarge text</button>
  </div>
</template>
<script>
export default {
  props: ['title'],
  emits: ['enlarge-text']
}
</script>

父组件
<BlogPost
  ...
  @enlarge-text="postFontSize += 0.1"
 />

组件名

在vue3中使用 <script setup> 的单文件组件会自动根据文件名生成对应的 name 选项,无需再手动声明。

vue3新增显著的新功能

  • vue3 增加组合式 API
  • vue3增加新特性 (比如 Teleport、Suspense,以及多根元素模板)
  • emits用于声明由组件触发的自定义事件。
  • setup

中断性的改变

模版指令

1. v-mode(双向数据绑定)

v-bind 的sync修饰符被删除,并替换为v-model上的参数 在一个组件上创建多个 v-model 双向绑定

```
属性名可以任意,比如x,那么事件名必须是update:x,然后使用v-model

在3.x中,自定义组件上的v-model相当于传递modelValue属性并发出update:modelValue事件:
并且可以要更改模型名称,而不是模型组件选项,现在我们可以向v-model传递一个参数:
这也可以替代.sync修饰符,并允许我们在自定义组件上有多个v模型。
```

image.png 2.key

在v-if/v-else/v-else-if中不再需要key,因为Vue现在自动生成唯一键

3.v-if和v-for的优先级问题

vue2中 当处于同一节点`v-for`的优先级高于`v-if`

vu3中 当处于同一节点`v-if`的优先级高于`v-for`

4.v-bind 绑定行为

    <!--v-bind的绑定顺序会影响渲染结果-->
    
    <div id="red" v-bind="{ id: 'blue' }"></div>
     <!-- 2.xresult -->
     <div id="red"></div>
    <!-- 3.xresult -->
    <div id="blue"></div>

5.v-on.native (将原生事件绑定到组件)已删除

Vue现在将未在子组件中定义该事件,则会被作为本机事件添加到子级的根元素中(除非在子级的选项中设置了inheritAttrs:false)

<my-component
  v-on:close="handleComponentEvent"
  v-on:click="handleNativeClickEvent"
/>

<script>
  export default {
    emits: ['close']
  }
</script>

handleNativeClickEvent就会被作为本机事件添加到子组件的根元素中

Components(组件)

1. 只能使用普通函数创建功能组件

2. defineAsyncComponent异步组件

定义一个异步组件,它在运行时是懒加载的。参数可以是一个异步加载函数,或是对加载行为进行更具体定制的一个选项对象。返回一个Promise加载函数

例如:导入单个组件

import { defineAsyncComponent } from 'vue'

const AsyncComp = defineAsyncComponent(() =>
  import('./components/MyComponent.vue')
)

最后得到的 AsyncComp 是一个外层包装过的组件,仅在页面需要它渲染时才会调用加载内部实际组件的函数。它会将接收到的 props 和插槽传给内部组件,所以你可以使用这个异步的包装组件无缝地替换原始组件,同时实现延迟加载。

3.emits (用于声明由组件触发的自定义事件。)

渲染函数

1.渲染函数的API发生了改变

h() 是 hyperscript 的简称——意思是“能生成 HTML (超文本标记语言) 的 JavaScript”。准确的名称应该是 createVnode()

创建虚拟 DOM 节点 (vnode)
接收的参数
function h(
  type: string | Component,
  props?: object | null,
  children?: Children | Slot | Slots
): VNode


h()现在被全局导入,而不是作为参数传递给呈现函数

// 完整参数签名
function h(
  type: string | Component,
  props?: object | null,
  children?: Children | Slot | Slots
): VNode

声明渲染函数

我们可以使用 render 选项来声明渲染函数:

import { h } from 'vue'

export default {
  render() {
    return h('div')
  }
}

在 vue2中render函数将自动接收h函数(这是createElement的传统别名)作为参数:

// Vue 2 Render Function Example
export default {
  render(h) {
    return h('div')
  }
}

VNode属性格式

在vue2中domProps在VNode props中包含一个嵌套列表:
// 2.x
{
  staticClass: 'button',
  class: {'is-outlined': isOutlined },
  staticStyle: { color: '#34495E' },
  style: { backgroundColor: buttonColor },
  attrs: { id: 'submit' },
  domProps: { innerHTML: '' },
  on: { click: submitForm },
  key: 'submit-button'
}

//3.x中整个VNode支柱结构被展平

{
  class: ['button', { 'is-outlined': isOutlined }],
  style: [{ color: '#34495E' }, { backgroundColor: buttonColor }],
  id: 'submit',
  innerHTML: '',
  onClick: submitForm,
  key: 'submit-button'
}

2.scopedSlots(作用域插槽)属性被删除,所有插槽都通过scopedSlots(作用域插槽)属性被删除,所有插槽都通过slots作为函数公开

//2.x
h(LayoutComponent, [
  h('div', { slot: 'header' }, this.header),
  h('div', { slot: 'content' }, this.content)
])

this.$scopedSlots.header

//3.x

h(LayoutComponent, {}, {
  header: () => h('div', this.header),
  content: () => h('div', this.content)
})

this.$slots.header()

3.移除了listeners(事件侦听器)/合并到attr中

cn.vuejs.org/guide/compo…

listeners:(2.3.0+) 一个包含了所有父组件为当前组件注册的事件监听器的对象。这是 data.on 的一个别名。

事件侦听器现在是attr中的一部分

//2.x
<template>
  <label>
    <input type="text" v-bind="$attrs" v-on="$listeners" />
  </label>
</template>
<script>
  export default {
    inheritAttrs: false
  }
</script>

//3.x
<template>
  <label>
    <input type="text" v-bind="$attrs" />
  </label>
</template>
<script>
export default {
  inheritAttrs: false
}
</script>

其他细微的变化

  • 生命周期重命名

destroyed改为unmounted

beforeDestroy改为 beforeUnmount

  • data只能是一个返回对象的函数
//2.x data可以是一个对象,或者是函数

<!-- Object Declaration -->
<script>
  const app = new Vue({
    data: {
      apiKey: 'a1b2c3'
    }
  })
</script>

<!-- Function Declaration -->
<script>
  const app = new Vue({
    data() {
      return {
        apiKey: 'a1b2c3'
      }
    }
  })
</script>

//3.x

<script>
  import { createApp } from 'vue'

  createApp({
    data() {
      return {
        apiKey: 'a1b2c3'
      }
    }
  }).mount('#app')
</script>

  • Transition过渡样式名的修改

v-enter 改为v-enter-from v-leave改为v-leave-from

  • vue3 filter过滤器移除

内置组件

vue2

  • component

    渲染一个“元组件”为动态组件。依 is 的值,来决定哪个组件被渲染。

  • transition

    单个元素/组件的过渡效果

  • transition-group

    多个元素/组件的过渡效果

  • keep-alive

    缓存

  • slot

    插槽。

vue3

  • Transition
  • TransitionGroup
  • KeepAlive
  • Teleport

    它可以将一个组件内部的一部分模板“传送”到该组件的 DOM 结构外层的位置去。

  • Suspense

    异步组件

组合式API

vue3

  1. watchEffect()

立即运行一个函数,同时响应式地追踪其依赖,并在依赖更改时重新执行。

第一个参数就是要运行的副作用函数。

第二个参数是一个可选的选项,可以用来调整副作用的刷新时机或调试副作用的依赖。

兼容v2老版本的方式

对于更老的 Vue 2 版本,可以使用官方维护的插件 @vue/composition-api 来实现vue3的写法,后期如果升级只需要把@vue/composition-api替换成vue即可