likes
comments
collection
share

Vue2->Vue3 知识迁移指南(官方文档无废话版)持续更新...

作者站长头像
站长
· 阅读数 34

完整版请参考: v3-migration.vuejs.org/zh/

Vue 3 迁移指南

学习 Vue 3 的推荐方法是阅读新的文档谁说不是呢可那么长怎么弄?

值得注意的新特性

Vue 3 中需要关注的一些新特性包括:

新的框架级别推荐

Vue 3 的支持库进行了重大更新。以下是新的默认建议的摘要: 这个重要,都得使

  • 新版本的 Router, Devtools & test utils 来支持 Vue 3
  • 构建工具链: Vue CLI -> Vite
  • 状态管理: Vuex -> Pinia
  • IDE 支持: Vetur -> Volar
  • 新的 TypeScript 命令行工具: vue-tsc
  • 静态网站生成: VuePress -> VitePress
  • JSX: @vue/babel-preset-jsx -> @vue/babel-plugin-jsx

新特性

组合式API

组合式 API (Composition API) 使用函数写 Vue 组件。

组合式 API 并不是函数式编程,组合式 API 是以 Vue 中数据可变的、细粒度的响应性系统为基础的,而函数式编程通常强调数据不可变

基本上都会配合 <script setup> 语法在单文件组件中使用。

<script setup>
import { ref, onMounted } from 'vue'

// 响应式状态
const count = ref(0)

// 更改状态、触发更新的函数
function increment() {
  count.value++
}

// 生命周期钩子
onMounted(() => {
  console.log(`计数器初始值为 ${count.value}。`)
})
</script>

<template>
  <button @click="increment">点击了:{{ count }} 次</button>
</template>

API包括:

  • 响应式 API:例如 ref() 和 reactive(),使我们可以直接创建响应式状态、计算属性和侦听器。
  • 生命周期钩子:例如 onMounted() 和 onUnmounted(),使我们可以在组件各个生命周期阶段添加逻辑。
  • 依赖注入:例如 provide() 和 inject(),使我们可以在使用响应式 API 时,利用 Vue 的依赖注入系统。

生命周期

Vue2->Vue3 知识迁移指南(官方文档无废话版)持续更新...

生命周期的钩子(Hook)

这个是钩子不是生命周期

onMounted()

onUpdated()

onUnmounted()

onBeforeMount()

onBeforeUpdate()

onBeforeUnmount()

onErrorCaptured()

在捕获了后代组件传递的错误时调用。

错误可以从以下几个来源中捕获:

  • 组件渲染
  • 事件处理器
  • 生命周期钩子
  • setup() 函数
  • 侦听器
  • 自定义指令钩子
  • 过渡钩子

你可以在 errorCaptured() 中更改组件状态来为用户显示一个错误状态。注意不要让错误状态再次渲染导致本次错误的内容,否则组件会陷入无限循环。

onRenderTracked()

调试钩子,当组件渲染过程中追踪到响应式依赖时调用。

onRenderTriggered()

调试钩子,当响应式依赖的变更触发了组件渲染时调用。

onActivated() SSR 无效

若组件实例是 <KeepAlive> 缓存树的一部分,当组件被插入到 DOM 中时调用。

onDeactivated()SSR 无效

若组件实例是 <KeepAlive> 缓存树的一部分,当组件从 DOM 中被移除时调用。

onServerPrefetch()

异步函数,在组件实例在服务器上被渲染之前调用。SSR only

<script setup>

是在单文件组件 (SFC) 中使用组合式 API 的编译时语法糖。

将被预处理为组件的 setup() 函数,这意味着它将为每一个组件实例都执行。

defineProps() 和 defineEmits()

为了在声明 props 和 emits 选项时获得完整的类型推导支持,我们可以使用 defineProps 和 defineEmits

defineExpose()

使用 <script setup> 的组件是默认关闭的——即通过模板引用或者 $parent 链获取到的组件的公开实例,不会暴露任何在 <script setup> 中声明的绑定。

可以通过 defineExpose 编译器宏来显式指定在 <script setup> 组件中要暴露出去的属性

<script setup>
    import { ref } from 'vue'

    const a = 1
    const b = ref(2)

    defineExpose({
      a,
      b
    })
    //`{ a: number, b: number }` (ref 会和在普通实例中一样被自动解包)
</script>

defineOptions()

<script setup>
    defineOptions({
      inheritAttrs: false,
      customOptions: {
        /* ... */
      }
    })
</script>

defineSlots()

这个宏可以用于为 IDE 提供插槽名称和 props 类型检查的类型提示。

useSlots() 和 useAttrs()

在 <script setup> 使用 slots 和 attrs 的情况应该是相对来说较为罕见的,因为可以在模板中直接通过 $slots 和 $attrs 来访问它们。

顶层 await

<script setup> 中可以使用顶层 await。结果代码会被编译成 async setup()

<script setup>
const post = await fetch(`/api/post/1`).then((r) => r.json())
</script>

限制

由于模块执行语义的差异,<script setup> 中的代码依赖单文件组件的上下文。当将其移动到外部的 .js 或者 .ts 文件中的时候,对于开发者和工具来说都会感到混乱。因此, <script setup>  不能和 src attribute 一起使用。

全局API

createApp

解决了全局配置共享一个 Vue 副本

解决了污染其他测试用例

全局改变 Vue 行为的 API Vue3.x 移动到应用实例上

config.productionTip 移除

config.ignoredElements 替换为 config.isCustomElement

重点: Vue.prototype 替换为 config.globalProperties

// 之前 - Vue 2
Vue.prototype.$http = () => {}

// 之后 - Vue 3
const app = createApp({})
app.config.globalProperties.$http = () => {}

Vue.extend 移除

重点 使用 组合式 API 来替代继承与 mixin。

Vue.extend vue2用于创建基于 Vue 构造函数“子类”,其参数为包含组件选项的对象。Vue 3.x 中使用 createApp 挂载组件

// 之前 - Vue 2

// 创建构造器
const Profile = Vue.extend({
 template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
 data() {
   return {
     firstName: 'Walter',
     lastName: 'White',
     alias: 'Heisenberg'
   }
 }
})
// 创建一个 Profile 的实例,并将它挂载到一个元素上
new Profile().$mount('#mount-point')

// 之后 - Vue 3
const Profile = {
 template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
 data() {
   return {
     firstName: 'Walter',
     lastName: 'White',
     alias: 'Heisenberg'
   }
 }
}
Vue.createApp(Profile).mount('#mount-point')

使用Vue.use()会发出警告。必须在应用实例上显式指定插件如:

const app = createApp(MyApp)
app.use(VueRouter)

挂载 App 实例

const app = createApp(MyApp)

app.component('button-counter', {
  data: () => ({
    count: 0
  }),
  template: '<button @click="count++">Clicked {{ count }} times.</button>'
})

app.directive('focus', {
  mounted: (el) => el.focus()
})

// 现在,所有通过 app.mount() 挂载的应用实例及其组件树,
// 将具有相同的 “button-counter” 组件和 “focus” 指令,
// 而不会污染全局环境
app.mount('#app')

Provide / Inject

在应用之间共享配置

创建工厂函数的好处是不用给每个实例分别插入指令或配置

import { createApp } from 'vue'
import Foo from './Foo.vue'
import Bar from './Bar.vue'

const createMyApp = (options) => {
  const app = createApp(options)
  app.directive('focus' /* ... */)

  return app
}

createMyApp(Foo).mount('#foo')
createMyApp(Bar).mount('#bar')

全局 API具名导出与Treeshaking

Vue3 nextTick等全局API支持 tree-shaking 使用方式如

import { nextTick } from 'vue'

nextTick(() => {
  // 一些和 DOM 有关的东西
})

受此更改影响的API:

  • Vue.nextTick
  • Vue.observable (用 Vue.reactive 替换)
  • Vue.version
  • Vue.compile (仅完整构建版本)
  • Vue.set (仅兼容构建版本)
  • Vue.delete (仅兼容构建版本)

内部帮助器

内部组件/帮助器以具名方式导出。

编译器只在代码被使用到时才引入并输出它。 只有在应用实际使用了 Transition 组件它才会被导入。

<transition>
  <div v-show="ok">hello</div>
</transition>

//将编译为类似于以下的内容:
import { h, Transition, withDirectives, vShow } from 'vue'

export function render() {
  return h(Transition, [withDirectives(h('div', 'hello'), [[vShow, this.ok]])])
}

插件中的用法

如果使用了 webpack \rollup,可能会导致 Vue 的源代码输出打包到插件中。为了防止发生这种情况配置模块打包工具以将 Vue 从最终的打包产物中排除。

// webpack.config.js
module.exports = {
  /*...*/
  externals: {
    vue: 'Vue'
  }
}

// rollup.config.js
export default {
  /*...*/
  external: ['vue']
}


如果你的插件依赖到了受影响的 Vue 2.x 全局 API,在 Vue 3 中,必须显式导入例如:

import { nextTick } from 'vue'

const plugin = {
  install: app => {
    nextTick(() => {
      // ...
    })
  }
}

函数式组件

2.x 中函数式组件带来的性能提升在 3.x 中已经可以忽略不计

import { h } from 'vue'

const DynamicHeading = (props, context) => {
  return h(`h${props.level}`, context.attrs, context.slots)
}

DynamicHeading.props = ['level']

export default DynamicHeading

接收两个参数:props 和 contextcontext 参数是一个对象,包含组件的 attrsslots 和 emit property。

在 Vue 3 中,所有的函数式组件都是用普通函数创建的。换句话说,不需要定义 { functional: true } 组件选项。

单文件组件 (SFC)

在 3.x 中,有状态组件和函数式组件之间的性能差异已经大大减少,并且在大多数用例中是微不足道的。

<template>
  <component
    v-bind:is="`h${$props.level}`"
    v-bind="$attrs"
  />
</template>

<script>
export default {
  props: ['level']
}
</script>
转载自:https://juejin.cn/post/7277787934863048739
评论
请登录