Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vue 3.0 #5

Open
hex11o opened this issue Sep 12, 2020 · 1 comment
Open

Vue 3.0 #5

hex11o opened this issue Sep 12, 2020 · 1 comment
Labels

Comments

@hex11o
Copy link
Owner

hex11o commented Sep 12, 2020

  1. 项目结构改变,变为monorepo,模块拆分, 依赖更加明确。
  2. vue2静态类型定义从flow换为ts
  3. 性能优化:1. 移除冷门feature,比如filter, inline-template;2.引入 tree-shaking(基于ES6的import, export), 减少打包体积(?之前webpack编译不会处理吗)
  4. 数据劫持:Object.defineproperty如名称所言,处理的是对象的属性,如果需要监听深层对象,还需要需要递归遍历所有属性,Proxy劫持整个对象,虽然也不能深层监听,但是通过getter中递归可以实现使用到才进行监听。
  5. 编译优化: 2.0 diff的最小单位是组件,连非动态节点也会进行diff, 导致vnode性能跟组件大小相关,3.0生成block tree, 更新性能提升为只与动态节点相关。
  6. composition API: 2.0 组件逻辑全混在一起,解决方案一般是用mixins抽离,但是mixin会有命名冲突和来源不明的问题,composition可以将逻辑抽离,并且避免命名重复,类型推断也容易。
@hex11o
Copy link
Owner Author

hex11o commented Apr 23, 2021

翻译:为什么放弃Class Api提案

原因

主要有两个原因:

  1. 目前的Class Api有很多边际问题|特性依赖|未解决的问题
  2. 新的Composition Api提案作为Component Api是比Class Api更好的解决方案,同时支持composition 和class 两个提案本质上是导致�产生三种做同一件事情的方案。

目前Class提案的的问题

类型复杂性

本来引入Class提案是为了提供一个TS接口支持更友好的供选择API, 然而,Vue的组件需要merge不同来源声明的的属性,导致对Class Api来说也是不小的挑战
一个例子就是props的类型定义,如果想merge进this, 我们要么使用一个通用参数(generic argument)或者使用装饰器(decorator),然而,这两个选择都有问题:

  • 通用参数仍然需要一个运行时(runtime) props属性声明,这样就导致了一个尴尬的结果,重复声明了两次
  • 使用装饰器则需要依赖一个处于stage-2的特性,尤其是现在ts目前的实行完全与TC39提案是不同步的,另外,通过装饰器没有办法在this.$props上来暴露出props的类型声明,因为破坏了tsx支持

并且,目前没有方法对class方法的参数进行上下文类型推断——意味着不能通过Class的其他属性来对传递给Class render函数的参数进行推断。

Also, currently there is no way to leverage contextual typing for the arguments of class methods - which means the arguments passed to a Class' render function cannot have inferred types based on the Class' other properties.

给预留方法的命名空间

已经讨论过了class声明下如何处理预留方法,目前没有一个提案方案比较完美。

实现的复杂性

支持Class带来了一系列需要额外代码来cover的边际问题,主要是因为我们对使用了一个Proxy作为this来进行响应式,事实是在constructor(所有class初始化)的this将与所有其他地方的this不一致

This mostly has to do with our need of using a Proxy as this for reactivity tracking, and the fact that the this in the constructor (and thus all class field initializers) will be different from the this in all other places.

收益质疑

综合上面的问题,引入class api的收益是需要质疑的

  • 首先并没有达到更好支持ts的目的
  • 使内部实现的复杂度增加
  • 并没有对逻辑模块带来提高

替代:Composition Api

在Class Api之后,有两个新的API提案,[Advanced Reactivity API]和[动态生命周期注入],通过结合这些我们发现了一个新的方法来声明组件逻辑:使用函数调用,是从React hooks中得到的启发, 但是基于Vue自身的响应式系统
这些方法调用能与现在所有组件options特性对等。

// everything tree-shakable
import {
  value,
  computed,
  watch,
  onMounted,
  inject
} from 'vue'

const App = {
  // same as before
  props: {
    a: String,
    b: Number
  },

  // same as before
  components: {
    // ...
  },

  setup(props) {
    // data
    const count = value(1)

    // computed
    const plusOne = computed(() => count.value + 1)

    // methods
    function inc() {
      count.value++
    }

    // watch
    watch(() => props.b + count.value, val => {
      console.log('changed: ', val)
    })

    // lifecycle
    onMounted(() => {
      console.log('mounted!')
    })

    // dependency injection
    const injected = inject(SomeSymbol)

    // other options like el, extends and mixins are no longer necessary

    // expose bindings on render context
    // any value containers will be unwrapped when exposed
    // any non-containers will be exposed as-is, including functions
    return {
      count,
      plusOne,
      inc,
      injected
    }
  },

  // template: `same as before`,

  render({ state, props, slots }) {
    // `this` points to the render context and works same as before (exposes everything)
    // `state` exposes bindings returned from `setup()` (with value wrappers unwrapped)
  }
}

更好的TypeScript支持

上面的例子可以很好的进行推行推断,并且没有边界问题,只要放在参数位置

import { createComponent } from 'vue'

const App = createComponent({
  props: {
    // ...
  },
  setup(props) {
    // props type inferred from `props` option
    // composition functions are all easily typed since they
    // don't rely on `this`
    return {
      // ...
    }
  },
  render({ state, props }) {
    // `state` type inferred from return value of setup()
    // `this` type inferred from a merge of state and props
  }
})

// The resulting type of `App` also supports TSX props inference

内部的类型同样更加简单

更好的模块能力

Compostion 能够简单的通过逻辑而不是类型来区分,同时能增强复用性,并且能避免Mixins的缺点(命名冲突与不确定的属性来源)

@hex11o hex11o added the Vue3 label Oct 8, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant