• Vue3较Vue2的更新内容(一)


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

    1、使用Ref绑定元素

    v2:

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

    v3:

    <div :ref="xxx">my ref</div>
    
    • 1
    export default {
    	methods: {
    		xxx(el){
    			console.log(el);//获取绑定元素
    			//this.myRef = el;//(保存获取到的元素)
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    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
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    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
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    3、Vue3中$attrs包含class & style

    给组件添加属性

    <TestAttrs id="my-id" class="my-class"></TestAttrs>
    
    • 1

    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>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    v2生成html:

    <label class="my-class">
      <input type="text" id="my-id" />
    </label>
    
    • 1
    • 2
    • 3

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

    v3生成html:

    <label>
      <input type="text" id="my-id" class="my-class" />
    </label>
    
    • 1
    • 2
    • 3

    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>
    
    • 1

    v2:

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

    钩子(可选):
    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实例
    	}
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    钩子(可选):
    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>
    
    • 1

    v2语法:

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

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

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

    可能会有 warn 警告

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

    // webpack 中的配置
    rules: [
      {
        test: /\.vue$/,
        use: 'vue-loader',
        options: {
          compilerOptions: {
            isCustomElement: tag => tag === 'plastic-button'
          }
        }
      }
      // ...
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

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

    7、data选项 用法

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

    data: {
          apiKey: 'a1b2c3'
        }
    
    • 1
    • 2
    • 3

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

    data() {
          return {
            apiKey: 'a1b2c3'
          }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    8、Mixin 合并行为变更

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

    const Mixin = {
      data() {
        return {
          user: {
            name: 'Jack',
            id: 1
          }
        }
      }
    }
    const CompA = {
      mixins: [Mixin],
      data() {
        return {
          user: {
            id: 2
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    v2 生成的 $data:

    {
      "user": {
        "id": 2,
        "name": "Jack"
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    v3 生成的 $data:

    {
      "user": {
        "id": 2
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    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)
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    14、全局 API

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

    import {
    	createApp
    } from 'vue'
    import App from './App.vue'
    const app = createApp(App)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    挂载:

    app.mount('#app')
    
    • 1

    任何全局改变 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 有关的东西
    })
    
    • 1
    • 2
    • 3
    • 4

    v3:

    import { nextTick } from 'vue'
    
    nextTick(() => {
      // 一些和 DOM 有关的东西
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5

    16、内联模板 Attribute

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

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

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

    17、key Attribute 改动

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

    在 Vue 2.x 的 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>
    
    • 1
    • 2
    • 3

    这个示例在 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>
    
    • 1
    • 2
    • 3

    结合 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>
    
    • 1
    • 2
    • 3
    • 4
    • 5

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

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

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

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

  • 相关阅读:
    数据结构入门 — 二叉树的概念、性质及结构
    【DZBS-202/T低电流启动中间继电器】
    java8 新特性4 Stream Api-1
    Unreal引擎自带的有用的工具函数,持续更新中
    正则表达式笔记
    springboot项目中使用minio进行对象存储
    运输层总结(未完待续)
    tokenizers pre_tokenizers模块
    SAP ABAP BAPI_SALESORDER_CREATEFROMDAT2 成本中心 kostl
    数据标注是一块肥肉,盯上这块肉的不止中国丨曼孚科技
  • 原文地址:https://blog.csdn.net/weixin_44646763/article/details/124711990