Vue3较Vue2的更新内容(二)

由于内容较多,我将其分为了里两部分:
Vue3较Vue2的更新内容(一)>>>

18、按键修饰符变更

vue3将不再支持使用数字 (即键码) 作为 v-on 修饰符,不再支持 config.keyCodes
在 Vue 2 中,keyCodes 可以作为修改 v-on 方法的一种方式。

<!-- 键码版本 -->
<input v-on:keyup.13="submit" />

此外,也可以通过全局的 config.keyCodes 选项定义自己的别名。

Vue.config.keyCodes = {
  f1: 112
}
<!-- 键码版本 -->
<input v-on:keyup.112="showHelpText" />

<!-- 自定义别名版本 -->
<input v-on:keyup.f1="showHelpText" />

在 Vue 3 使用keycode修饰词将会报错:’KeyboardEvent.keyCode’ modifier on ‘v-on’ directive is deprecated. Using ‘KeyboardEvent.key’ instead‘
替代方案使用:KeyboardEvent.key

<!-- 别名版本 -->
<input v-on:keyup.enter="submit" />

19、移除$listeners

在vue3,事件监听器现在是 $attrs 对象的一部分,所以 $listeners 对象在 Vue 3 中已被移除。
在 Vue 2 中,你可以通过 this. $attrs 访问传递给组件的 attribute,以及通过 this. $listeners 访问传递给组件的事件监听器
在 Vue 3 的虚拟 DOM 中,事件监听器现在只是以 on 为前缀的 attribute,这样它就成为了 $attrs 对象的一部分,因此 $listeners 被移除了。

如果这个组件接收一个 id attribute 和一个 v-on:close 监听器,那么 $attrs 对象现在将如下所示:
v2:

{
  id: 'my-input',
}

v3:

{
  id: 'my-input',
  onClose: () => console.log('close 事件被触发')
}

20、被挂载的应用不会替换元素

在 Vue 2.x 中,当挂载一个具有 template 的应用时,被渲染的内容会替换我们要挂载的目标元素。在 Vue 3.x 中,被渲染的应用会作为子元素插入,从而替换目标元素的 innerHTML。

挂载一个应用template:

<div id="rendered">{{ message }}</div>

原页面:

<body>
  <div id="app">
    Some app content
  div>
body>

v2渲染结果:

<body>
  <div id="rendered">Hello Vue!div>
body>

v3渲染结果:

<body>
  <div id="app" data-v-app="">
    <div id="rendered">Hello Vue!div>
  div>
body>

21、移除propsData选项

propsData 选项之前用于在创建 Vue 实例的过程中传入 prop,现在它被移除了。如果想为 Vue 3 应用的根组件传入 prop,请使用 createApp 的第二个参数。
v2:

const Comp = Vue.extend({
  props: ['username'],
  template: '
{{ username }}
'
}) new Comp({ propsData: { username: 'Evan' } })

v3:

const app = createApp(
  {
    props: ['username'],
    template: '
{{ username }}
'
}, { username: 'Evan' } )

22、在 prop 的默认函数中访问this

现在 Vue 3 生成 prop 默认值的工厂函数不再能访问 this。

取而代之的是:
组件接收到的原始 prop 将作为参数传递给默认函数;
inject API 可以在默认函数中使用。

import { inject } from 'vue'
export default {
  props: {
    theme: {
      default (props) {
        // `props` 是传递给组件的、
        // 在任何类型/默认强制转换之前的原始值,
        // 也可以使用 `inject` 来访问注入的 property
        return inject('theme', 'default-theme')
      }
    }
  }
}

23、渲染函数 API(更改)

渲染函数参数

在 2.x 中,render 函数会自动接收 h 函数 (它是 createElement 的惯用别名) 作为参数:

// Vue 2 渲染函数示例
export default {
  render(h) {
    return h('div')
  }
}

在 3.x 中,h 函数现在是全局导入的,而不是作为参数自动传递。

// Vue 3 渲染函数示例
import { h } from 'vue'

export default {
  render() {
    return h('div')
  }
}
渲染函数签名更改

在 2.x 中,render 函数自动接收参数,如 h 函数。

// Vue 2 渲染函数示例
export default {
  render(h) {
    return h('div')
  }
}

在 3.x 中,由于 render 函数不再接收任何参数,它将主要在 setup() 函数内部使用。这还有一个好处:可以访问在作用域中声明的响应式状态和函数,以及传递给 setup() 的参数。

import { h, reactive } from 'vue'
export default {
  setup(props, { slots, attrs, emit }) {
    const state = reactive({
      count: 0
    })
    function increment() {
      state.count++
    }
    // 返回渲染函数
    return () =>
      h(
        'div',
        {
          onClick: increment
        },
        state.count
      )
  }
}
VNode Prop 格式化

在 2.x 中,domProps 包含 VNode prop 中的嵌套列表:

// 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 prop 的结构都是扁平的。使用上面的例子,来看看它现在的样子。

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

24、插槽统一

在vue3,this. $slots 现在将插槽作为函数公开、且移除了 this. $scopedSlots

v2:
当使用渲染函数,即 h 时,2.x 曾经在内容节点上定义 slot 数据 property。

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

此外,可以使用以下语法引用作用域插槽:

// 2.x 语法
this.$scopedSlots.header

v3:

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

当你需要以编程方式引用作用域插槽时,它们现在被统一到 $slots 选项中了。

// 2.x 语法
this.$scopedSlots.header

// 3.x 语法
this.$slots.header()

25、新增Suspense

Suspense 是一个试验性的新特性,其 API 可能随时会发生变动。
官方也提醒到:生产环境请勿使用
所以这个就简单了解下就行了

该 组件提供了另一个方案,允许将等待过程提升到组件树中处理,而不是在单个组件中。 组件有两个插槽。它们都只接收一个直接子节点。default 插槽里的节点会尽可能展示出来。如果不能,则展示 fallback 插槽里的节点。

26、过渡的 class 名更改

在vue3, 过渡类名 v-enter 修改为 v-enter-from、过渡类名 v-leave 修改为 v-leave-from。
组件的相关 prop 名称也发生了变化:
leave-class 已经被重命名为 leave-from-class (在渲染函数或 JSX 中可以写为:leaveFromClass)
enter-class 已经被重命名为 enter-from-class (在渲染函数或 JSX 中可以写为:enterFromClass)

v2过渡类:

.v-enter,
.v-leave-to {
  opacity: 0;
}
.v-leave,
.v-enter-to {
  opacity: 1;
}

v3过渡类:

.v-enter-from,
.v-leave-to {
  opacity: 0;
}

.v-leave-from,
.v-enter-to {
  opacity: 1;
}

27、Transition作为根节点将不再触发过渡效果

在 Vue 2 中,通过使用 作为一个组件的根节点,过渡效果存在从组件外部触发的可能性:


<template>
  <transition>
    <div class="modal"><slot/>div>
  transition>
template>

<modal v-if="showModal">hellomodal>

切换 showModal 的值将会在模态组件内部触发一个过渡效果。

但在 Vue 3 ,当使用 作为根结点的组件从外部被切换时将不再触发过渡效果。取而代之,你可以向组件传递一个 prop 来触发组件内过渡效果。

28、Transition Group 根元素不再默认渲染根元素

现在 Vue 3 中 不再默认渲染根元素,但仍然可以用 tag attribute 创建根元素。
在 Vue 2 中, 像其它自定义组件一样,需要一个根元素。默认的根元素是一个 ,但可以通过 tag attribute 定制。

<transition-group tag="ul">
  <li v-for="item in items" :key="item">
    {{ item }}
  li>
transition-group>

在 Vue 3 中,我们有了片段的支持,因此组件不再需要根节点。所以, 不再默认渲染根节点。
如果像上面的示例一样,已经在 Vue 2 代码中定义了 tag attribute,那么一切都会和之前一样

29、移除v-on.native修饰符

v-on 的 .native 修饰符已被移除。同时,新增的 emits 选项允许子组件定义真正会被触发的事件。
因此,对于子组件中未被定义为组件触发的所有事件监听器,Vue 现在将把它们作为原生事件监听器添加到子组件的根元素中 (除非在子组件的选项中设置了 inheritAttrs: false)。

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

MyComponent.vue:

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

30、v-model

在vue3用于自定义组件时,v-model prop 和事件默认名称已更改:
prop:value -> modelValue;
事件:input -> update:modelValue;
v-bind 的 .sync 修饰符和组件的 model 选项已移除

v2:
如果想要更改 prop 或事件名称,则需要在 ChildComponent 组件中添加 model 选项:

<ChildComponent v-model="pageTitle" />
// ChildComponent.vue
export default {
  model: {
    prop: 'title',
    event: 'change'
  },
  props: {
    // 这将允许 `value` 属性用于其他用途
    value: String,
    // 使用 `title` 代替 `value` 作为 model 的 prop
    title: {
      type: String,
      default: 'Default title'
    }
  }
}

所以,在这个例子中 v-model 是以下的简写:

<ChildComponent :title="pageTitle" @change="pageTitle = $event" />

v3:
在 3.x 中,自定义组件上的 v-model 相当于传递了 modelValue prop 并接收抛出的 update:modelValue 事件。若需要更改 model 的名称,现在我们可以为 v-model 传递一个参数,以作为组件内 model 选项的替代:

<ChildComponent v-model:title="pageTitle" />



<ChildComponent :title="pageTitle" @update:title="pageTitle = $event" />

31、v-if 与 v-for 的优先级对比

v2:
2.x 版本中在一个元素上同时使用 v-if 和 v-for 时,v-for 会优先作用。
v3:
3.x 版本中 v-if 总是优先于 v-for 生效。

32、v-bind 合并行为

v2:
在 2.x 中,如果一个元素同时定义了 v-bind=“object” 和一个相同的独立 attribute,那么这个独立 attribute 总是会覆盖 object 中的绑定。

<!-- 模板 -->
<div id="red" v-bind="{ id: 'blue' }"></div>
<!-- 结果 -->
<div id="red"></div>

v3:
在 3.x 中,如果一个元素同时定义了 v-bind=“object” 和一个相同的独立 attribute,那么绑定的声明顺序将决定它们如何被合并。后定义的属性会覆盖前定义的结果。

<!-- 模板 -->
<div id="red" v-bind="{ id: 'blue' }"></div>
<!-- 结果 -->
<div id="blue"></div>

<!-- 模板 -->
<div v-bind="{ id: 'blue' }" id="red"></div>
<!-- 结果 -->
<div id="red"></div>

33、VNode 生命周期事件

在 Vue 2 中,我们可以通过事件来监听组件生命周期中的关键阶段。这些事件名都是以 hook: 前缀开头,并跟随相应的生命周期钩子的名字。
在 Vue 3 中,这个前缀已被更改为 vnode-。额外地,这些事件现在也可用于 HTML 元素,和在组件上的用法一样。
v2:
在 Vue 2 中,这些事件名和相应的生命周期钩子一致,并带有 hook: 前缀:

<template>
  <child-component @hook:updated="onUpdated">
template>

v3:
在 Vue 3 中,事件名附带的是 vnode- 前缀:

<template>
  <child-component @vnode-updated="onUpdated">
template>

34、watch侦听数组

在Vue3中,当使用 watch 选项侦听数组时,只有在数组被替换时才会触发回调。换句话说,在数组被改变时侦听回调将不再被触发。要想在数组被改变时触发侦听回调,必须指定 deep 选项。

watch: {
  bookList: {
    handler(val, oldVal) {
      console.log('book list changed')
    },
    deep: true
  },
}

上一章:Vue3较Vue2的更新内容(一)>>>

你可能感兴趣的:(vue3,javascript,vue.js,前端)