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 体验报告 #27

Open
CyanSalt opened this issue Jul 12, 2020 · 0 comments
Open

Vue 3 体验报告 #27

CyanSalt opened this issue Jul 12, 2020 · 0 comments

Comments

@CyanSalt
Copy link
Owner

CyanSalt commented Jul 12, 2020


path: vue3-experience-report


详细文档参见 https://composition-api.vuejs.org/zh/api.html

本文主要记录 https://github.com/CyanSalt/commas 重构过程中对于 Vue 3 的一些体验

0. 生态对 ES Module 的支持稀烂

尽管 Node.js 14 已经正式支持了 ES Module,但相关的工具链对于 .mjs 的支持依然不佳。点名批评:

  • webpack@4:需要手动为 .mjs 指定 javascript/auto 类型的解析。v5 版本似乎支持 ES Module,但可能也需要开启实验性特性(暂未测试)
  • electron:内置的 Node 禁用了命令行参数 --experiment-module,按照核心团队的说法(issue 找不到了),引入 Node 14 时也将会出于安全性考虑禁用 ES Module 功能
  • typescript:不支持 .mjs 文件的类型检查,即使开了 checkJs 编译选项。这导致依赖 typescript 的 VSCode 等对于 .mjs 的支持也很差(缺少自动补全、智能提示等功能,通过 import 的类型推导总是 any

1. 代理对象对于常量的影响

问题描述

举一个栗子

import { reactive, watchEffect } from 'vue'

const MY_CONSTANT = {
  foo: 1,
  bar: 2,
}

const state = reactive({})
state.mapping = MY_CONSTANT

watchEffect(() => {
  console.log(state.mapping === MY_CONSTANT) // false
})

可以看到,通过 reactive 对象获取的属性会和原本的对象不相同,这是因为 reactive 对象会对访问的属性也做深层处理,也就是说

import { isProxy } from 'vue'

isProxy(state.mapping) // true

解决方案

像上面的这种常量的情况,可以通过

import { markRaw } from 'vue'

state.mapping = markRaw(MY_CONSTANT)

来规避。如果需要依赖属性的 reactive 特性,可以

import { watchEffect, toRaw } from 'vue'

watchEffect(() => {
  console.log(toRaw(state.mapping) === MY_CONSTANT) // true
})

2. 浅层代理和深层代理混用的问题

问题描述

考虑一个使用浅层代理的情况:

import { shallowReactive } from 'vue'

const state = shallowReactive({
  list: [],
})

state.list.push(data) // will not trigger reactivity mutations

shallowReactive 对象修改时,后续传入的数据将不会被响应式系统监管。通常来说如果是某个类的实例,通过这种方式来保存引用是安全的。但是

import { readonly } from 'vue'

function useList() {
  return readonly(state.list)
}

看起来是一个更加安全的对外提供 state.list 的方式,但是注意 readonly 是深层的,这会导致 state.list 在执行 useList 时被响应式系统监管。

解决方案

一种方式是使用 shallowReadonly

import { shallowReadonly } from 'vue'

function useList() {
  return shallowReadonly(state.list)
}

但通常来说,不使用 shallowReactive 而是使用 markRaw 可能更好

import { reactive, markRaw } from 'vue'

const state = reactive({
  list: markRaw([]),
})

state.list.push(data) // will not trigger reactivity mutations

3. emits 是一个非常有用的特性

4. 总是把非声明的语句放在 watchEffect

5. 严格执行命名约定

@CyanSalt CyanSalt added the vue label Jul 12, 2020
@CyanSalt CyanSalt transferred this issue from another repository Feb 24, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant