美文网首页前端
vue2.x与vue3.x的对比

vue2.x与vue3.x的对比

作者: 南崽 | 来源:发表于2021-05-17 16:29 被阅读0次

    异步组件(vue3.x新增)

    vue3.x

    • 由于函数式组件被定义为纯函数,因此异步组件的定义需要通过将其包装在新的 defineAsyncComponent助手方法中来显式地定义
    import { defineAsyncComponent } from 'vue'
    import ErrorComponent from './components/ErrorComponent.vue'
    import LoadingComponent from './components/LoadingComponent.vue'
    
    // 不带选项的异步组件
    const asyncPage = defineAsyncComponent(() => import('./NextPage.vue'))
    
    // 带选项的异步组件
    const asyncPageWithOptions = defineAsyncComponent({
      loader: () => import('./NextPage.vue'),
      delay: 200,
      timeout: 3000,
      errorComponent: ErrorComponent,
      loadingComponent: LoadingComponent
    })
    
    • component选项现在被重命名为loader,loader函数不再接收resolvereject参数,且必须返回promise
    const asyncComponent = defineAsyncComponent(
      ()=>new Promise((resolve,reject)=>{
        /*...*/
      })
    )
    

    片段(vue3.x新增)

    vue3.x
    组件可以有多个根节点

    // vue2.x
    <template>
      <div>
        <header>...</header>
        <main>...</main>
        <footer>...</footer>
      </div>
    </template>
    
    // vue3.x
    <template>
      <header>...</header>
      <main v-bind="$attrs">...</main>
      <footer>...</footer>
    </template>
    

    v-for

    vue2.x
    v-for指令可以绑定数组的数据来渲染列表

    <div v-for="item in items" :key="item.message">
        {{ item.message }}
      </div>
    

    vue3.x
    从单个绑定获取多个ref,ref会通过迭代的key被设置(新特性)

    <div v-for="item in list" :ref="setItemRef"></div>
    

    自定义元素交互

    vue2.x
    通过Vue.config.ignoredElements配置自定义元素白名单

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

    vue3.x
    在模板编译期间执行指示编译器将<plastic-button>视为自定义元素

    • 如果使用生成步骤:将isCustomElement传递给 Vue模板编译器,如果使用vue-loader,则应通过 vue-loader 的compilerOptions选项传递
    rules: [
      {
        test: /\.vue$/,
        use: 'vue-loader',
        options: {
          compilerOptions: {
            isCustomElement: tag => tag === 'plastic-button'
          }
        }
      }
    ]
    
    • 如果使用动态模板编译,通过 app.config.isCustomElement传递
    const app = Vue.createApp({})
    app.config.isCustomElement = tag => tag === 'plastic-button'
    

    自定义内置元素的方法是向内置元素添加is属性
    v-is要使用注册名称来渲染组件,其值应为 JavaScript字符串文本

    <tr v-is="'blog-post-row'"></tr>
    

    Data选项

    vue2.x
    可以自定义data选项是objectfunction

    // object 声明
    <script>
      const app = new Vue({
        data: {
          num: '123'
        }
      })
    </script>
    
    // function 声明 
    <script>
      const app = new Vue({
        data() {
          return {
            num: '123'
          }
        }
      })
    </script>
    

    vue3.x
    data选项只接受返回objectfunction

    <script>
      import { createApp } from 'vue'
    
      createApp({
        data() {
          return {
             num: '123'
          }
        }
      }).mount('#app')
    </script>
    

    全局API

    vue2.x
    有许多全局API和配置,会全局改变vue的行为

    vue3.x
    调用createApp返回一个应用实例

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

    config.productionTip移除
    config.ignoredElements替换为 config.isCustomElement

    下表为2.x与3.x的对比

    2.x 全局 API 3.x 实例 API (app)
    Vue.config app.config
    Vue.config.productionTip 已移除
    Vue.config.ignoredElements app.config.isCustomElement
    Vue.component app.component
    Vue.directive app.directive
    Vue.mixin app.mixin
    Vue.use app.use

    全局 API Treeshaking

    vue2.x
    Vue.nextTick()是一个全局的 API 直接暴露在单个 Vue 对象上,回调的this上下文自动绑定到当前实例
    webpack支持tree-shaking,但Vue 2.x 的全局 API 比如 nextTick 无法被 TreeShake,所以就算没有用到这些 API,它们还是会被打包到你的生产版本的代码包里

    vue3.x
    全局和内部API进行了重构,支持使用tree-shaking
    需要注意的是:
    当使用全局 API 时,需要主动将其导入到目标文件中

    import { nextTick } from 'vue';
     
    nextTick(() => {
      // 和 DOM 有关的一些操作
    });
    

    如果直接调用Vue.nextTick(),会导致报错:undefined is not a function

    key attribute

    vue2.x
    建议在v-if/v-else/v-else-if的分支中使用key

    // vue2.x
    <div v-if="hhhh" key = "yes">YES</div>
    <div v-else key = "no">NO</div>
    

    vue3.x
    vue会自动生成唯一的key

    <div v-if="hhhh">YES</div>
    <div v-else>NO</div>
    

    按键修饰符

    vue2.x

    • 支持keyCodes作为修改v-on的方法
    • 可以通过全局config.keyCodes
    <!-- 键码版本 -->
    <input v-on:keyup.13="submit" />
    
    <!-- 别名版本 -->
    <input v-on:keyup.enter="submit" />
    

    vue3.x

    • 不再支持使用数字 (即键码) 作为v-on 修饰符,建议使用kebab-cased大小写名称
    • 不再支持 config.keyCodes
    <input v-on:keyup.delete="confirmDelete" />
    

    在 prop 的默认函数中访问this

    vue3.x
    生成 prop 默认值的工厂函数不再能访问 this

    渲染函数API

    vue2.x

    • render函数参数
      render函数自动接收h函数作为参数
    // vue2.x
    export default
      render(h){
        return h('div')
      }
    }
    
    • render函数签名更改
      render函数自动接收诸如 h 之类的参数
    // vue2.x
    export default{
      render(h){
        return h('div')
      }
    }
    

    vue3.x

    • render函数参数
      h是全局引入的,而不是作为参数自动传递
    // vue 3.x
    import {h} from 'vue'
    export default{
      render(){
        return h('div')
      }
    }
    
    • render函数签名更改
      render函数不再接收任何参数,将主要用于setup()内部,可以访问作用域中声明的响应式状态和函数以及传递给setup()的参数
    import { h, reactive } from 'vue'
    
    export default {
      setup(props, { slots, attrs, emit }) {
        const state = reactive({
          count: 0
        })
    
        function increment() {
          state.count++
        }
    
        // 返回render函数
        return () =>
          h(
            'div',
            {
              onClick: increment
            },
            state.count
          )
      }
    }
    

    slot统一

    vue2.x
    在内容节点上定义slot data property

    h(LayoutComponent,[
      h('div',{slot:'header'},this.header),
      h('div',{slot:'content'},this.content)
    ])
    
    // 引用时
    this.$scopedSlots.header
    

    vue3.x

    • 插槽被定义为当前节点的子对象
    h(LayoutComponent,{},{
      header:()=>h('div',this.header),
      content:()=>h('div',this.content)
    })
    
    • 当需要以编程方式引用作用域slot时,被统一到$slot选项中
    this.$slots.header
    

    过渡类名更改

    vue3.x
    过渡类名 v-enter修改为 v-enter-from、过渡类名v-leave修改为v-leave-from

    <transition>组件相关属性名也发生了变化:
    leave-class已经被重命名为leave-from-class(在渲染函数或 JSX 中可以写为:leaveFromClass)
    enter-class已经被重命名为enter-from-class (在渲染函数或 JSX 中可以写为:enterFromClass)

    v-model

    vue2.x

    • 使用v-model指令必须使用valueprop;
    <ChildComponent v-model="pageTitle" />
    
    • 如果出于不同的目的使用其他的prop,需要使用v-bind.sync
    <ChildComponent :title.sync="pageTitle" />
    

    vue3.x

    • 如果要改变绑定的属性名,而不是更改组件内绑定的选项,只需要给 v-model 传递一个参数就可以了;
    <ChildComponent v-model:title = 'pageitle' />
    
    • 可以自定义多个v-model;
    <ChildComponent v-model:title="pageTitle" v-model:content="pageContent" />
    
    • 支持自定义修饰符
    <ChildComponent v-model.capitalize="pageTitle" />
    

    v-if与v-for的优先级比较

    vue2.x
    在同一个元素上同时使用v-ifv-for,v-for会优先使用;

    vue3.x
    v-if总是优先于v-for生效

    v-bind合并行为

    vue2.x
    如果一个元素同时定义了v-bind="object"和一个相同的单独的property,那么这个单独的 property总是会覆盖object中的绑定

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

    vue3.x
    如果一个元素同时定义了v-bind="object"和一个相同的单独的property,那么声明绑定的顺序决定了它们如何合并

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

    函数式组件

    vue2.x

    • 作为性能优化
    • 返回多个根节点
    export default {
      functional: true,
      props: ['level'],
      render(h, { props, data, children }) {
        return h(`h${props.level}`, data, children)
      }
    }
    

    vue3.x

    • 通过函数创建组件
      所有的函数式组件都是用普通函数创建的,不需要定义{function:true}组件选项
    import { h } from 'vue'
    
    const DynamicHeading = (props, context) => {
      return h(`h${props.level}`, context.attrs, context.slots)
    }
    
    DynamicHeading.props = ['level']
    
    export default DynamicHeading
    
    • 单文件组件
    <template>
      <component
        v-bind:is="`h${$props.level}`"
        v-bind="$attrs"
      />
    </template>
    
    <script>
    export default {
      props: ['level']
    }
    </script>
    

    function attribute 在<template>中移除
    listeners现在作为$attrs的一部分传递,可以删除

    下表为vue3.x已移除的api:

    已移除的api vue2.x vue3.x
    $children 可以使用this.$children直接访问当前实例的子组件 $children已移除,如需访问子组件,建议使用$refs
    事件API vue实例可用于触发通过事件触发API强制附加发处理程序已创建全局事件监听器 移除了$on,$off,$once方法,但仍可用$emit触发由父组件以声明方式附加的事件处理程序
    过滤器 可以使用过滤器来处理通用文本格式 过滤器已删除,可以用方法调用或计算属性替换过滤器
    内联模块Attribute Vue 为子组件提供了inline-template attribute,以便将其内部内容用作模板,而不是将其作为分发内容 不再支持此功能,所有模板写在HTML页面中

    相关文章

      网友评论

        本文标题:vue2.x与vue3.x的对比

        本文链接:https://www.haomeiwen.com/subject/nazdjltx.html