Vue3较Vue2的更新内容(一)

Vue3较Vue2的更新内容(一),第1张

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

1、使用Ref绑定元素

v2:

<div ref="xxx">my refdiv>
this.$refs.xxx//获取ref绑定元素

v3:

<div :ref="xxx">my refdiv>
export default {
	methods: {
		xxx(el){
			console.log(el);//获取绑定元素
			//this.myRef = el;//(保存获取到的元素)
		}
	}
}
2、新增 异步组件

v2:
在v2是通过返回Promise函数来创建的

const Component1 = () => import('./Component1.vue')//v2 异步组件
//或者,对于带有选项的更高阶的组件语法:
const Component2 = {//v2 异步组件
	component: () => import('./Component2.vue'),
	delay: 200,
	timeout: 3000,
	error: ErrorComponent,
	loading: LoadingComponent
}

v3
v3新增了defineAsyncComponent 方法来定义异步组件

import {defineAsyncComponent} from 'vue'
// 无选项异步组件
const Component1 = defineAsyncComponent(() => import('./Component1.vue'))
// 带选项异步组件
const Component2 = defineAsyncComponent({
	loader: () => import('./Component2.vue'),
	delay: 200,
	timeout: 3000,
	errorComponent: ErrorComponent,
	loadingComponent: LoadingComponent
})
3、Vue3中$attrs包含class & style

给组件添加属性

<TestAttrs id="my-id" class="my-class">TestAttrs>

TestAttrs.vue:

<template>
	<label>
		<input type="text" v-bind="$attrs" />
		<!--VUE2 class .my-class不生效 -->
		<!--VUE3 class .my-class生效 -->
	</label>
</template>
<script>
	export default {
		inheritAttrs: false,
		created() {
			console.log(this.$attrs);
			//VUE2:  {id: "my-id"}
			//VUE3:  {class: "my-class",id: "my-id"}
		}
	}
</script>

<style scoped="scoped">
	input.my-class {
		background: red;
	}
</style>

v2生成html:

<label class="my-class">
  <input type="text" id="my-id" />
label>

input.my-class 的 样式没生效
this.$attrs:{id: “my-id”}

v3生成html:

<label>
  <input type="text" id="my-id" class="my-class" />
label>

input.my-class 的 样式生效
this.$attrs:{class: “my-class”,id: “my-id”}

4、Vue3移除了 $children

在Vue2,可以使用 this.$children 访问当前实例的直接子组件。
但在Vue3, $children property 已被移除,且不再支持。如果你需要访问子组件实例,我们建议使用 $refs。

5、使用自定义指令
<p v-highlight="'yellow'">以亮黄色高亮显示此文本p>

v2:

// v2 自定义指令
Vue.directive('highlight', {
	bind(el, binding, vnode) {
		el.style.background = binding.value
		const vm = vnode.context//获取vue实例
	}
})

钩子(可选):
bind - 指令绑定到元素后调用。只调用一次。
inserted - 元素插入父 DOM 后调用。
update - 当元素更新,但子元素尚未更新时,将调用此钩子。
componentUpdated - 一旦组件和子级被更新,就会调用这个钩子。
unbind - 一旦指令被移除,就会调用这个钩子。也只调用一次。

v3:

const app = Vue.createApp({})
// v3 自定义指令
app.directive('highlight', {
	beforeMount(el, binding, vnode) {
		el.style.background = binding.value
		const vm = binding.instance //获取vue实例
	}
})

钩子(可选):
created - 新增!在元素的 attribute 或事件监听器被应用之前调用。
bind → beforeMount
inserted → mounted
beforeUpdate:新增!在元素本身被更新之前调用,与组件的生命周期钩子十分相似。
update → 移除!该钩子与 updated 有太多相似之处,因此它是多余的。请改用 updated。
componentUpdated → updated
beforeUnmount:新增!与组件的生命周期钩子类似,它将在元素被卸载之前调用。
unbind -> unmounted

*需要注意的是 v2通过 vnode.context 获取实例对象,现在v3 通过binding.instance 获取

6、使用自定义元素

自定义元素

<plastic-button>plastic-button>

v2语法:

Vue.config.ignoredElements = ['plastic-button']

v3语法:
如果使用动态模板编译,使用app.config.compilerOptions.isCustomElement

const app = Vue.createApp({})
app.config.compilerOptions.isCustomElement = tag => tag === 'plastic-button'

可能会有 warn 警告

如果使用了 vue-loader,则通过 vue-loader 的 compilerOptions 选项传递

// webpack 中的配置
rules: [
  {
    test: /\.vue$/,
    use: 'vue-loader',
    options: {
      compilerOptions: {
        isCustomElement: tag => tag === 'plastic-button'
      }
    }
  }
  // ...
]

*需要注意的是,运行时配置只会影响运行时的模板编译——它不会影响预编译的模板。

7、data选项 用法

在 v2 中,开发者可以通过 object 或者是 function 定义 data 选项。

data: {
      apiKey: 'a1b2c3'
    }

在 v3 中,data 选项已标准化为只接受返回 object 的 function。

data() {
      return {
        apiKey: 'a1b2c3'
      }
    }
8、Mixin 合并行为变更

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

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

v2 生成的 $data:

{
  "user": {
    "id": 2,
    "name": "Jack"
  }
}
9、新增emits选项

Vue 3 提供一个 emits 选项,和现有的 props 选项类似。这个选项可以用来定义一个组件可以向其父组件触发的事件。

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

emits内定义可向其父组件触发的事件,即 $emit()的第一个参数
该选项也可以接收一个对象,该对象允许开发者定义传入事件参数的验证器,和 props 定义里的验证器类似。
尝试后发现,当向其父组件触发的事件未在emits选项定义或未验证成功,控制台会出现warn警告,但父级仍然触发了该事件

10、移除 事件API: $on, $off 和 $once

Vue3中完全移除了 o n 、 on、 onoff 和 o n c e 方 法 , 组 件 实 例 不 再 实 现 事 件 触 发 接 口 。 once 方法,组件实例不再实现事件触发接口。 onceemit 仍然包含于现有的 API 中,因为它用于触发由父组件声明式添加的事件处理函数。

11、移除 过滤器(filters)

在 vue3 中,过滤器已移除,且不再支持。取而代之的是,用方法调用或计算属性来替换它们。
有点心痛呀,觉得 filters 还挺好用的
不少项目在处理时间格式的时候会选择全局过滤器处理格式,迁移的话也需一定的成本

12、支持多根节点的组件(片段)

Vue 3 现在正式支持了多根节点的组件,也就是片段!
在 v2 ,由于不支持多根节点组件,当其被开发者意外地创建时会出现报错。结果是,为了修复这个问题,许多组件被包裹在了一个

中。
在 v3 中,组件可以包含多个根节点!但是,这要求开发者显式定义 attribute 应该分布在哪里。

13、函数式组件

在 v3 中,v2 带来的函数式组件的性能提升可以忽略不计,因此官方建议只使用有状态的组件
所以这部分内容可以只了解了解
vue 2 使用函数式组件

export default {
  functional: true,
  props: ['level'],
  render(h, { props, data, children }) {
    return h(`h${props.level}`, data, children)
  }
}

vue 3 使用函数式组件
在 v3 中,所有的函数式组件都是用普通函数创建的。换句话说,不需要定义 { functional: true } 组件选项。如果是单文件组件中使用 创建函数式组件的话,functional属性也已被移除。
它们将接收两个参数:props 和 context。context 参数是一个对象,包含组件的 attrs、slots 和 emit property。
此外,h 现在是全局导入的,而不是在 render 函数中隐式提供。

import { h } from 'vue'
const DynamicHeading = (props, context) => {
  return h(`h${props.level}`, context.attrs, context.slots)
}
DynamicHeading.props = ['level']
export default DynamicHeading
14、全局 API

在vue2,全局配置使得在同一页面上的多个“应用”在全局配置不同时共享同一个 Vue 副本非常困难,使用Vue.mixin会影响到所有根实例,为了避免这些问题,在 Vue 3 中引入了一个新的全局 API:createApp
调用 createApp 创建一个应用实例:

import {
	createApp
} from 'vue'
import App from './App.vue'
const app = createApp(App)

挂载:

app.mount('#app')

任何全局改变 Vue 行为的 API 现在都会移动到应用实例上,下面选自官方的内容图片:

15、全局 API Treeshaking

由于之前的 Vue 版本中的代码编写方式,如 Vue.nextTick() 这样的全局 API 是不支持 tree-shake 的,不管它们实际上是否被使用了,都会被包含在最终的打包产物中。在 Vue 3 中,全局和内部 API 都经过了重构,并考虑到了 tree-shaking 的支持。因此,对于 ES 模块构建版本来说,全局 API 现在通过具名导出进行访问。
以 全局 API Vue.nextTick() 为例:

v2:

import Vue from 'vue'
Vue.nextTick(() => {
  // 一些和 DOM 有关的东西
})

v3:

import { nextTick } from 'vue'

nextTick(() => {
  // 一些和 DOM 有关的东西
})
16、内联模板 Attribute

在 v2 中,Vue 为子组件提供了 inline-template attribute,以便将其内部内容作为模板使用,而不是作为分发内容。

<my-component inline-template>
  <div>
    <p>它们将被编译为组件自己的模板,</p>
    <p>而不是父级所包含的内容。</p>
  </div>
</my-component>

而现在v3将不再支持此功能。

17、key Attribute 改动

对于 v-if/v-else/v-else-if 的各分支项 key 将不再是必须的,因为现在 Vue 会自动生成唯一的 key。
如果你手动提供 key,那么每个分支必须使用唯一的 key。你将不再能通过故意使用相同的 key 来强制重用分支。
v2 v-if/v-else/v-else-if 使用key:

<!-- Vue 2.x -->
<div v-if="condition" key="yes">Yes</div>
<div v-else key="no">No</div>

这个示例在 Vue 3.x 中仍能正常工作。但是我们不再建议在 v-if/v-else/v-else-if 的分支中继续使用 key attribute,因为没有为条件分支提供 key 时,也会自动生成唯一的 key。

<!-- Vue 3.x -->
<div v-if="condition">Yes</div>
<div v-else>No</div>

结合 template v-for
在 Vue 2.x 中, 标签不能拥有 key。不过,你可以为其每个子节点分别设置 key。

<!-- Vue 2.x -->
<template v-for="item in list">
  <div :key="'heading-' + item.id">...</div>
  <span :key="'content-' + item.id">...</span>
</template>

在 Vue 3.x 中,key 则应该被设置在 标签上。

<!-- Vue 3.x -->
<template v-for="item in list" :key="item.id">
  <div>...</div>
  <span>...</span>
</template>

类似地,当使用 时如果存在使用 v-if 的子节点,则 key 应改为设置在 标签上。

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

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1296498.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-10
下一篇 2022-06-10

发表评论

登录后才能评论

评论列表(0条)

保存