Wang's blog Wang's blog
首页
  • 前端文章

    • HTML教程
    • CSS
    • JavaScript
  • 前端框架

    • Vue
    • React
    • VuePress
    • Electron
  • 后端技术

    • Npm
    • Node
    • TypeScript
  • 编程规范

    • 规范
  • 我的笔记
  • Git
  • GitHub
  • VSCode
  • Mac工具
  • 数据库
  • Google
  • 服务器
  • Python爬虫
  • 前端教程
更多
收藏
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Wang Mings

跟随大神,成为大神!
首页
  • 前端文章

    • HTML教程
    • CSS
    • JavaScript
  • 前端框架

    • Vue
    • React
    • VuePress
    • Electron
  • 后端技术

    • Npm
    • Node
    • TypeScript
  • 编程规范

    • 规范
  • 我的笔记
  • Git
  • GitHub
  • VSCode
  • Mac工具
  • 数据库
  • Google
  • 服务器
  • Python爬虫
  • 前端教程
更多
收藏
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • Python爬虫

  • 前端教程

    • 团队规范

    • Project

    • JS

    • NodeJS

    • Vue

      • 个人理解Vue和React区别
      • Vue高级用法
      • Vue2.x源码分析 - 框架结构
      • Vue2.x源码分析 - 模版编译以及挂载
      • 虚拟dom算法库 - snabbdom
      • Vue2.x源码分析 - Virtual DOM实现
      • Vue2.x源码分析 - 事件系统
      • Vue2.x源码分析 - 组件系统
      • Vue2.x源码分析 - Vue.nextTick
      • Vue2.x源码分析 - inject provide
      • Vue2.x源码分析 - 解析Template模板
      • Vue2.x源码分析 - 响应式原理
      • Vue2.x源码分析 - v-model
      • Vue CLI3 插件系统原理
      • Vue Loader v15 源码解析
      • Vue3 设计思想
      • Vue3 RFCS导读
        • [#](#_1-componsition-api) 1. componsition api \(opens new window\)
        • [#](#_2-slot统一) 2. slot统一
        • [#](#_3-动态指令参数) 3. 动态指令参数 \(opens new window\)
        • [#](#_4-v-model变动) 4. v-model变动
        • [#](#_5-functional-api去除) 5. functional api去除 \(opens new window\)
        • [#](#_6-全局api-tree-shaking) 6. 全局api tree shaking \(opens new window\)
        • [#](#_7-render-api修改) 7. render api修改 \(opens new window\)
        • [#](#_8-增加createapp-api) 8. 增加createApp api \(opens new window\)
        • [#](#_9-自定义指令api变更) 9. 自定义指令api变更 \(opens new window\)
        • [#](#_10-废弃keycode修饰符) 10. 废弃keycode修饰符 \(opens new window\)
        • [#](#_11-移除filter-api) 11. 移除filter api \(opens new window\)
        • [#](#_12-组件过渡类名重命名) 12. 组件过渡类名重命名 \(opens new window\)
        • [#](#_13-响应式data-api只支持function方式) 13. 响应式data api只支持function方式 \(opens new window\)
        • [#](#_14-移除-on-off-once) 14. 移除\$on, \$off, \$once \(opens new window\)
        • [#](#_15-嵌套路由meta自动合并) 15. 嵌套路由meta自动合并 \(opens new window\)
        • [#](#_16-css中scope变更) 16. css中scope变更 \(opens new window\)
        • [#](#_17-falsy属性转换策略) 17. falsy属性转换策略 \(opens new window\)
        • [#](#_18-异步组件api) 18. 异步组件api \(opens new window\)
        • [#](#_19-移除内联模板api) 19. 移除内联模板api \(opens new window\)
        • [#](#_20-emit事件数据校验) 20. emit事件数据校验 \(opens new window\)
        • [#](#_21-vue-test-utils提升异步流) 21. Vue Test Utils提升异步流 \(opens new window\)
        • [#](#_22-router路由改动) 22. router路由改动
      • Vue3 响应式原理 - Ref Reactive Effect源码分析
      • Vue3 API 源码解析
      • 为何Vue3 Proxy 更快
      • Vue核心原理 - 笔记
    • React

    • 效率工具

    • 读书笔记

  • 教程
  • 前端教程
  • Vue
wangmings
2022-07-19
目录

Vue3 RFCS导读

# # Vue3 RFCS导读

为了对即将到来的vue3有个全面的认识,通读Vue3 rfcs (opens new window) (opens new window)(意见修改稿)是有必要的。但原版英文内容比较长,通读时间比较耗时。这里笔者根据原文内容总结输出,方便大家对Vue3细节改动有个全局的认识。更多详细设计请在每个章节链接进去查看。

# # 1. componsition api (opens new window) (opens new window)

核心变动,增加setup选项,更多动机和设计看官方教程 (opens new window) (opens new window)

    // 基础示例
    <template>
      <button @click="increment">
        Count is: {{ state.count }}, double is: {{ state.double }}
      </button>
    </template>
    
    <script>
    import { reactive, computed } from 'vue'
    
    export default {
      setup() {
        const state = reactive({
          count: 0,
          double: computed(() => state.count * 2)
        })
    
        function increment() {
          state.count++
        }
    
        return {
          state,
          increment
        }
      }
    }
    </script>
    
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

# # 2. slot统一

  1. 模板上slot和slot-scope统一为v-slot
  2. 模板上支持v-slot简写为#
  3. this.$slots和this.$scopedSlots统一为this.$slots,并且暴露为funciton函数。(ps:集合了this.$slots和this.$scopedSlots各自特点)

相关rfcs:

  1. https://github.com/vuejs/rfcs/blob/master/active-rfcs/0001-new-slot-syntax.md
  2. https://github.com/vuejs/rfcs/blob/master/active-rfcs/0002-slot-syntax-shorthand.md
  3. https://github.com/vuejs/rfcs/blob/master/active-rfcs/0006-slots-unification.md

# # 3. 动态指令参数 (opens new window) (opens new window)

指令参数支持动态设置

    <div v-bind:[key]="value"></div>
    <div v-on:[event]="handler"></div>
    
1
2
3

# # 4. v-model变动

  1. v-model支持参数: 使用v-model:arg语法 代替:arg.sync
  2. 不带参数的v-model,默认事件名为update:modelValue,而不是以前的事件名:input。(ps:主要还是统一上一条变动)

相关rfcs:

  1. https://github.com/vuejs/rfcs/blob/master/active-rfcs/0005-replace-v-bind-sync-with-v-model-argument.md
  2. https://github.com/vuejs/rfcs/blob/master/active-rfcs/0011-v-model-api-change.md
    <!--模版里不再有.sync语法-->
    <MyComponent v-model:title="title" />
    
1
2
3

# # 5. functional api去除 (opens new window) (opens new window)

关键点:

  1. 不再需要有functional选项api
  2. 函数式组件不再是对象,而变成类React函数式
  3. 入参有变化
    // 基本展示
    import { h } from 'vue'
    
    const FunctionalComp = (props, { slots, attrs, emit }) => {
      return h('div', `Hello! ${props.name}`)
    }
    
1
2
3
4
5
6
7

# # 6. 全局api tree shaking (opens new window) (opens new window)

所有挂载在Vue对象的方法,都单独出去了,比如Vue.nextTick、Vue.observable

# # 7. render api修改 (opens new window) (opens new window)

关键点:

  1. h函数全局导入
  2. h函数参数统一,不管是有状态的组件还是函数式组件
  3. VNodes数据结构优化展平(ps:非常实用的改动,写jsx简单了)
    // 全局导入 `h`函数
    import { h } from 'vue'
    
    export default {
      render() {
        return h(
          'div',
          // // vnode数据结构更直观
          {
            id: 'app',
            onClick() {
              console.log('hello')
            }
          },
          [
            h('span', 'child')
          ]
        )
      }
    }
    
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# # 8. 增加createApp api (opens new window) (opens new window)

创建app实例,而不是像以前共享同一个Vue实例

    import { createApp } from 'vue'
    import App from './App.vue'
    
    const app = createApp(App)
    
    app.config.isCustomElement = tag => tag.startsWith('app-')
    app.use(/* ... */)
    app.mixin(/* ... */)
    app.component(/* ... */)
    app.directive(/* ... */)
    
    app.config.globalProperties.customProperty = () => {}
    
    app.mount(App, '#app')
    
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# # 9. 自定义指令api变更 (opens new window) (opens new window)

自定义指令跟vue hook命名一致

    const MyDirective = {
      beforeMount(el, binding, vnode, prevVnode) {},
      mounted() {},
      beforeUpdate() {},
      updated() {},
      beforeUnmount() {}, // new
      unmounted() {}
    }
    
1
2
3
4
5
6
7
8
9

# # 10. 废弃keycode修饰符 (opens new window) (opens new window)

因为KeyboardEvent.keyCode (opens new window) (opens new window)已经被废弃,故在vue3中移除

# # 11. 移除filter api (opens new window) (opens new window)

使用方法或computed代替filter

    <!-- before -->
    {{ msg | format }}
    
    <!-- after -->
    {{ format(msg) }}
    
1
2
3
4
5
6

# # 12. 组件过渡类名重命名 (opens new window) (opens new window)

from/to名称对称,更好理解

  1. v-enter 重命名为 v-enter-from
  2. v-leave 重命名为 v-leave-from
    .v-enter-from, .v-leave-to {
      opacity: 0;
    }
    .v-enter-active {
      opacity: 0.5;
    }
    .v-leave-from, .v-enter-to {
      opacity: 1
    }
    .v-leave-active {
      opacity: 0.5;
    }
    
1
2
3
4
5
6
7
8
9
10
11
12
13

对于这些在过渡中切换的类名来说,如果你使用一个没有名字的 <transition>,则 v- 是这些类名的默认前缀。如果你使用了 <transition name="my-transition">,那么 v-enter-from 会替换为 my-transition-enter-from

# # 13. 响应式data api只支持function方式 (opens new window) (opens new window)

以前2.x响应式data定义,支持object和function方式(当然大部分人约定俗成的都使用function方式),在vue3中强制data只能用function。

因为如果使用object定义data时,当有多个组件实例共用同一个引用类型data,容易造成错乱。

    import { createApp, h } from 'vue'
    
    createApp().mount({
      data() { // data一定是个函数
        return {
          counter: 1,
        }
      },
      render() {
        return [
          h('span', this.counter),
          h('button', {
            onClick: () => { this.counter++ }
          }),
        ]
      },
    }, '#app')
    
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# # 14. 移除$on, $off, $once (opens new window) (opens new window)

Vue3不再提供事件发布接口,如果有发布事件需要,可以使用mitt (opens new window) (opens new window)库代替

# # 15. 嵌套路由meta自动合并 (opens new window) (opens new window)

以前处理页面权限时,常使用meta作为配置方案,当匹配到单个页面时,判断to.meta.requiresAuth即可。但在嵌套路由页面时,子路由页面一般没有再设置requiresAuth,所以在Vue2.x中只能通过to.matched获得匹配数组再逻辑判断。

Vue3提供了嵌套路由meta的自动合并,使得逻辑判断更加简单。注意这里的合并是Object.assign浅拷贝。

加入给定嵌套路由如下:

    {
      path: '/parent',
      meta: { requiresAuth: true, isChild: false },
      children: [
        { path: 'child', meta: { isChild: true }}
      ]
    }
    
1
2
3
4
5
6
7
8

导航到/parent/child时,to.meta属性变为:

    { requiresAuth: true, isChild: true }
    
1
2

# # 16. css中scope变更 (opens new window) (opens new window)

使用::v-deep()代替Vue2.x中的 >>> 和 /deep/

    <style scoped>
    /* deep selectors */
    ::v-deep(.foo) {}
    
    /* targeting slot content */
    ::v-slotted(.foo) {}
    
    /* one-off global rule */
    ::v-global(.foo) {}
    </style>
    
1
2
3
4
5
6
7
8
9
10
11

# # 17. falsy属性转换策略 (opens new window) (opens new window)

在Vue2.x template模板中,属性为“falsy”值(undefined,null,false)时,会被“removeAttribute”,源码可看这里 (opens new window) (opens new window)。

在Vue3中,“falsy”中去掉了false。当为false时,会作为attribute=false,当为undefined或null,跟2.x一致会removeAttribute。

# # 18. 异步组件api (opens new window) (opens new window)

新语法defineAsyncComponent支持

    import { defineAsyncComponent } from "vue"
    
    // simple usage
    const AsyncFoo = defineAsyncComponent(() => import("./Foo.vue"))
    
    // with options
    const AsyncFooWithOptions = defineAsyncComponent({
      loader: () => import("./Foo.vue"),
      loadingComponent: LoadingComponent,
      errorComponent: ErrorComponent,
      delay: 200,
      timeout: 3000
    })
    
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# # 19. 移除内联模板api (opens new window) (opens new window)

冷门的api,这个api可以看Vue官方内联模板使用说明 (opens new window) (opens new window)

# # 20. emit事件数据校验 (opens new window) (opens new window)

增加新的 emits 选项api,可以对emit触发的事件数据,进行校验

    const Comp = {
      emits: {
        submit: payload => {
          // validate payload by returning a boolean
        }
      },
    
      created() {
        this.$emit('submit', {
          /* payload */
        })
      }
    }
    
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# # 21. Vue Test Utils提升异步流 (opens new window) (opens new window)

Vue单元测试时,允许使用await语法触发re-render

    const wrapper = mount(Component)
    await wrapper.find('.element').trigger('click')
    // 不再需要如下,在下一个事件循环中拿到dom值
    //  await wrapper.vm.$nextTick()
    expect(wrapper.find('.finish').attributes('disabled')).toBeFalsy()
    
1
2
3
4
5
6

# # 22. router路由改动

  • 路由新增router.push返回Promise值,router.afterEach、router.onError也返回Promise值
  • 更方便的动态增、删、查路由信息,对应api:router.addRoute、router.removeRoute、router.hasRoute、router.getRoutes

相关rfcs:

  • https://github.com/vuejs/rfcs/blob/master/active-rfcs/0033-router-navigation-failures.md
  • https://github.com/vuejs/rfcs/blob/master/active-rfcs/0029-router-dynamic-routing.md
编辑 (opens new window)
Vue3 设计思想
Vue3 响应式原理 - Ref Reactive Effect源码分析

← Vue3 设计思想 Vue3 响应式原理 - Ref Reactive Effect源码分析→

最近更新
01
theme-vdoing-blog博客静态编译问题
09-16
02
搜索引擎
07-19
03
友情链接
07-19
更多文章>
Theme by Vdoing | Copyright © 2019-2022 Evan Xu | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式