vue3-从vue2迁移(1)

264 阅读3分钟

前言

在vue3、vue-router、vux相继next正式版本发布后,有的同学已经迫不及待的想要将自己项目去升级,今天就带大家看一下从vue2迁移需要主要哪些api的变化吧

api变化

1. children实例property已从Vue3.0中移除,不再支持,在3.0中访问子组件示例,需要使用children实例 property 已从 Vue 3.0 中移除,不再支持,在3.0中访问子组件示例,需要使用refs

2. 自定义指令

指令的挂钩函数已重命名,以更好地与组件生命周期保持一致

在 Vue 3 中,我们为自定义指令创建了一个更具凝聚力的 API。正如你所看到的,它们与我们的组件生命周期方法有很大的不同,

即使我们正与类似的事件钩子,我们现在把它们统一起来了:

  • created - 新的!在元素的 attribute 或事件侦听器应用之前调用。
  • bind → beforeMount
  • inserted → mounted
  • beforeUpdate:新的!这是在元素本身更新之前调用的,很像组件生命周期钩子。
  • update → 移除!有太多的相似之处要更新,所以这是多余的,请改用 updated。
  • componentUpdated → updated
  • beforeUnmount:新的!与组件生命周期钩子类似,它将在卸载元素之前调用。
  • unbind -> unmounted

最终 API 如下:

const MyDirective = {
 	beforeMount(el, binding, vnode, prevVnode) {},
  	mounted() {},
  	beforeUpdate() {}, // 新
  	updated() {},
  	beforeUnmount() {}, // 新
  	unmounted() {} 
 }

3. data选项

data组件选项声明不再接收纯 JavaScript object,而需要function 声明

当合并来自 mixin 或 extend 的多个 data 返回值时,现在是浅层次合并的而不是深层次合并的(只合并根级属性)。

2.x:

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

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

3.x:

在 3.x, data 选项已标准化为只接受返回 object 的 function.

<script>
  import { createApp } from 'vue'

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

Mixin合并行为变更

当来自组件的 data() 及其 mixin 或 extends 基类被合并时,现在将浅层次执行合并:

const Mixin = { data() { return { user: { name: 'Jack', id: 1 } } } } const CompA = { mixins: [Mixin], data() { return { user: { id: 2 } } } }

在vue 2.x中,生成的 $data 是:

{
  user: {
    id: 2,
    name: 'Jack'
  }
}

在vue 3.x中,生成的 $data 是:

{
  user: {
    id: 2
  }
}

对于依赖对象声明的,建议:

  • 将共享数据提取到外部对象并将其用作 data 中的 property
  • 重写对共享数据的引用以指向新的共享对象

对于依赖 mixin 的深度合并行为的用户,我们建议重构代码以完全避免这种依赖,因为 mixin 的深度合并非常隐式,这让代码逻辑更难理解和调试。

4. emits

Vue 3现在提供了一个emits选项,类似于现有的props选项。此选项可用于定义组件可以向其父对象发出的事件。

2.x:

在Vue 2中,可以定义组件可以接收到的props,但是不能声明它可以发出哪些事件

<template>
  <div>
    <p>{{ text }}</p>
    <button v-on:click="$emit('accepted')">OK</button>
  </div>
</template>
<script>
  export default {
    props: ['text']
  }
</script>

3.x:

与props类似,组件发出的事件现在可以使用发出选项定义

<template>
  <div>
    <p>{{ text }}</p>
    <button v-on:click="$emit('accepted')">OK</button>
  </div>
</template>
<script>
  export default {
    props: ['text'],
    emits: ['accepted']
  }
</script>

5. 事件api

onon,off 和 once实例方法已被移除,应用实例不再实现事件触发接口。once 实例方法已被移除,应用实例不再实现事件触发接口。emit还存在.

6. filters

从 Vue 3.0 开始,过滤器已删除,不再支持。

2.x:

<template>
  <h1>Bank Account Balance</h1>
  <p>{{ accountBalance | currencyUSD }}</p>
</template>

<script>
  export default {
    props: {
      accountBalance: {
        type: Number,
        required: true
      }
    },
    filters: {
      currencyUSD(value) {
        return '$' + value
      }
    }
  }
</script>

3.x:

在 3.x 中,过滤器已删除,不再支持。相反地,我们建议用方法调用或计算属性替换它们。

<template>
  <h1>Bank Account Balance</h1>
  <p>{{ accountInUSD }}</p>
</template>

<script>
  export default {
    props: {
      accountBalance: {
        type: Number,
        required: true
      }
    },
    computed: {
      accountInUSD() {
        return '$' + this.accountBalance
      }
    }
  }
</script>

迁移策略:

建议用计算属性或方法代替过滤器,而不是使用过滤器。

如果在应用中全局注册了过滤器,那么在每个组件中用计算属性或方法调用来替换它可能就没那么方便了。可以:

// main.js
const app = createApp(App)

app.config.globalProperties.$filters = {
  currencyUSD(value) {
    return '$' + value
  }
}

然后,你可以通过 $filters 对象修改所有的模板,像下面这样:

<template>
  <h1>Bank Account Balance</h1>
  <p>{{ $filters.currencyUSD(accountBalance) }}</p>
</template>

注意,这种方式只能用于方法中,不可以在计算属性中使用,因为后者只有在单个组件的上下文中定义时才有意义。