vue3升级概览

都来自于官网的的升级文档,官网文档点击我

异步组件

1, overview

2.x(before)

// simple
const asyncPage = () => import('./NextPage.vue')

//advanced
const asyncPage = {
  component: () => import('./NextPage.vue'),
  delay: 200,
  timeout: 3000,
  error: ErrorComponent,
  loading: LoadingComponent
}
3.x(after)

import { defineAsyncComponent } from 'vue'
import ErrorComponent from './components/ErrorComponent.vue'
import LoadingComponent from './components/LoadingComponent.vue'

// // simple  ---- Async component without options
const asyncPage = defineAsyncComponent(() => import('./NextPage.vue'))

// //advanced ---- Async component with options
const asyncPageWithOptions = defineAsyncComponent({
  loader: () => import('./NextPage.vue'), // 注意这里是loader,不是component关键字
  delay: 200,
  timeout: 3000,
  errorComponent: ErrorComponent,
  loadingComponent: LoadingComponent
})

2 loader function change

2.x(before)

const oldAsyncComponent = (resolve, reject) => {
  /* ... */
}
3.x(after)
const asyncComponent = defineAsyncComponent(
  () =>
    new Promise((resolve, reject) => {
      /* ... */
    })
)

指令的变化

指令的变化主要是API名字的变动,新的API指令名字类似于组件的生命周期

- 表示没有该API
2.x(before)3.x(after)
bindbeforeMount
insertedmounted
-beforeUpdate
update-
componentUpdatedupdated
unbindunmounted

最终的API长这样:


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

2.x(before)
<p v-highlight="yellow">Highlight this text bright yellow</p>
Vue.directive('highlight', {
  bind(el, binding, vnode) {
    el.style.background = binding.value
  }
})
3.x(after)
<p v-highlight="yellow">Highlight this text bright yellow</p>
const app = Vue.createApp({})

app.directive('highlight', {
  beforeMount(el, binding, vnode) {
    el.style.background = binding.value
  }
})

EVENT变化

在3.x版本中:移除了 $on, $off, $once这3个方法。保留了$emit,保留这个方法是为了触发父组件里面的event handler。

所以2.x中的非父子组件的数据交换以及事件触发,就不能通过$onor$off来实现了。实际上我们可以自己实现一个EventHub 【通过发布订阅模式】

不过已经有第三方库实现了mitttiny-emitter

Filter

3.x 不再支持filter,可以用method 或者 computed来代替。

Fragments

2.x 模板不支持多root节点,3.x支持多root节点

2.x(before)
<!-- Layout.vue -->
<template>
  <div> <!--有且只有一个root节点-->
    <header>...</header>
    <main>...</main>
    <footer>...</footer>
  </div>
</template>

3.x(after)
<!-- Layout.vue -->
<template>
  <!--template里面可以有多个root节点-->
  <header>...</header>
  <main v-bind="$attrs">...</main>
  <footer>...</footer>
</template>


Global API tree-shaking

前景: 2.x里面我们操作dom的时候,是这样操作的。

import Vue from 'vue'

Vue.nextTick(()=>{
  //Something Dom-related
})

由于2.x代码中nextTick的实现方式的原因,造成了诸如webpack等打包工具打包的时候,tree-shaking是不能移除这一块无用的代码的,比如我们是这样写的Vue.nextTick(),最后仍然会在build文件里面。

3.x 部分全局API被重写,已经能够支持tree-shaking。而且这些全局API只能通过ES module的具名引用形式获取到。 像这样:

import { nextTick } from 'vue'

nextTick(() => {
  // something DOM-related
})

2.x中被影响的全局API

- Vue.nextTick
- Vue.observable (replaced by Vue.reactive)
- Vue.version
- Vue.compile (only in full builds)
- Vue.set (only in compat builds)
- Vue.delete (only in compat builds)


除了一些全局的Global API,一些内部组件/帮助方法也能够以具名形式导出。 好处就是,只有被使用了,最后编译的时候才能够打包输出。有使用到才被打包。

v-model 的改变 [非常重要,在自定义组件的时候的逻辑修改]

1,自定义组件的时候,v-model的属性和时间的名字修改。

prop: value -> modelValue
event: input -> update:modelValue

2,v-binding.sync修饰器和组件的model选项被移除,现在作为v-model的参数。

3,可以给一个组件绑定多个v-model

4,除了默认的v-model,可以添加用户自定v-model修饰器

2.x(before)

在2.x下,v-model是一个语法糖,等同于value属性和一个input事件。

<ChildComponent v-model="pageTitle" />
<!-- 等同于 -->
<ChildComponent :value="pageTitle" @input="pageTitle = $event" />

如果我们想改变属性和事件的名字,不使用默认的 valueinput,那我们需要在ChildComponent里面添加model选项。

<!-- ParentComponent.vue -->
<ChildComponent v-model="pageTitle" />
// ChildComponent.vue

export default {
  model: {
    prop: 'title',
    event: 'change'
  },
  props: {
    // 让value属性发挥其他作用
    // this allows using the `value` prop for a different purpose
    value: String,
    // 用属性名title代替名字value
    // use `title` as the prop which take the place of `value`
    title: {
      type: String,
      default: 'Default title'
    }
  }
}

这样我们不仅能用v-model的形式,也能用语法糖来表示,但是可以用我们的命名来。

<ChildComponent v-model="pageTitle" />
<!-- 等同于 -->
<ChildComponent :title="pageTitle" @change="pageTitle = $event" />

关于.sync,在2.x中,有一定的情况下,需要属性值也双向绑定,子组件可以修改父组件传递下来的属性值。

父组件引用子组件的代码:

<ChildComponent :title.sync="pageTitle" />
<!--等同于-->
<ChildComponent :title="pageTitle" @update:title="pageTitle = $event" />

子组件修改属性值的代码:

this.$emit('update:title', newValue)
3.x(after)

在3.x下,在自定义组件上的v-model 等同于 modalValue属性和update:modalValue事件

prop:value -> modelValue

event: input -> update:modelValue

<ChildComponent v-model="pageTitle" />
<!-- would be shorthand for: -->
<ChildComponent
  :modelValue="pageTitle"
  @update:modelValue="pageTitle = $event"
/>

v-model参数(.sync的改进)

现在移除了组件里面的model option, 代替它的是在v-model上传递一个参数

<ChildComponent v-model:title="pageTitle" />
<!-- 等同于: -->
<ChildComponent :title="pageTitle" @update:title="pageTitle = $event" />

也就是说以前.sync的方式这样修改:

<!--2.x-->
<ChildComponent :title.sync="pageTitle" />
<!--3.x-->
<ChildComponent v-model:title="pageTitle" />

v-model可以自定义修饰器

2.x只有一些默认的修饰器,比如.trim, 3.x支持自定义修饰器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值