记一次给 vue 3.x 搭建脚手架遇到的问题之组件编写

匆匆过客 提交于 2020-11-12 11:56:15

劳动节就好好在家写代码了,毕竟我们现在居家就是在为国家做贡献,而且劳动节不劳动和咸鱼有什么区别,手动🐶保命。

前言

vue 3 刚出几个月,现在是一步一个坑,但是坑还是要填的,毕竟生活还是要继续的么。

目前 vue 3.x 基本上是已经可以工作了,刚出不久的那段时间还看👀到掘金上有人说生产上有 3.x ,对这种大佬只能佩服,毕竟新东西出来,光是想想出了问题,这么解决就是非常头疼的事情

比如我现在搭个脚手架基本就是一路爬过来的,还好目前还没开始深入开发,出的都是周边配套和类型这些小问题。

另外说和 react 很像的,我只能说,这不光是像,你们的代码估计都可以拷过来改改就能用了呢,看下完整的函数式组件的代码

不过 vue 的双向数据绑定用的很舒服,这个才是最主要的,毕竟手写 set 真的麻烦。

读书人的事情这么能叫抄呢?这叫借鉴,这叫共同进步 --- by 鲁迅

不过这种事情其实说多了也没意义,比如 python 和 js 或其他语言之间,你敢说没有互相借鉴。

而且前端的口号不就是:“走别人的路,让别人无路可走”,我们要团结一致,毕竟前端这个岗位真的很容易被替代掉,我们求发展,求稳定,技术人用实力说话,才能让这个岗位越走越远。

目前的脚手架的开发进度

基本上已经可以支持你跑,但是打包工具还在纠结,我喜欢 rollupjs,但是项目已经引入了 webpack,到底要不要再引一个新的,还在思考中

  • 支持 [typescript][typescript] 语法开发
  • 支持 [storybook][storybook] 构建 UI 组件
  • 支持 [lerna][lerna] 管理工程
  • 支持 [prettier][prettier] 格式化代码
  • 支持 [typedoc][typedoc] 自动生成 api 文档
  • 支持主题与组件分离
  • 支持使用 sass,采用 bem 的方式编写样式
  • 支持 rollup 或 webpack 构建工具打包

问题列表

问题一:选择 vue 包

这个不算问题,主要是第一次为了这么选择包而头疼,以前写 vue 组件,基本就是直接引入 vue 就行了,其他交给构建工具处理。

但是看到 vue 3 支持模块化了,就想着把 @vue/compiler-dom 作为框架依赖引入,项目中引入 vue ,结果坑到了自己。

中间出现了一些很诡异的事情,所以我现在不管是项目还是组件库都直接引入的 vue@next,还有和 vue2 选择主文件的问题,不过这个目前应该都明白应该这么选择了

问题二:初期使用障碍,类型定义的问题

这个目前比较头大的时候,要么变成 AnyScript,要么别名一堆,虽然还有 js 可选,但是都有火了,为什么还要吃生的,不知道 0202 年开始禁野味了么。

我们在这里举个🌰,比如你的组件库是这样导出的

import type { App, Component, Plugin } from 'vue'

// Component 是一个复合类型,里面已经有 函数组件的定义了, 照理说应该没问题的
const Components: Component[] = [
  // Button 是一个纯函数组件,但是在这里就会出现签名不一致的情况
  Button as  Component
]

// app 不是以前的 Vue 类了
function install(app: App<any>) {
  Components.forEach(Component => {
    app.component(Component.name as string, Component)
  })
}

export default {
  version: process.env.VERSION || 'dev',
  install: install
// vue 没有暴露 PluginInstallFunction 类型
// 只有 Plugin 类型,在定义类型的的时候就只能进行联合声明了
} as { version: string } & Plugin
复制代码

看着没有报错,信心满满,然后代码里面你就很放心的开始用了

import VueUI from 'vue-next-ui'

const app = createApp(App)

app.use(VueUI)
复制代码

然而实际是会告诉你类型有问题,就算你改成这样导出也没用

export default {
  install(app: App<any>): void {
    Components.forEach(Component => {
      app.component(Component.name as string, Component)
    })
  }
} as Plugin
复制代码

就算你直接改 d.ts 也没用,但是 vue-router@next 就可以,不明觉厉。

这里想说的是,后面这样不兼容的问题还有很多,可能是多方原因,但情况就是这样,所以后面有的忙了。

类型问题可以参考下我的处理:

方式一:@ts-ignore 一把梭

@ts-ignore 一把梭只有对你的代码非常自信才应该这样做,一般推荐已经进行判断之后,还存在类型签名问题时使用。

方式二:显示转换

其实还可以使用 anyany 大法是真好用,就和 eval 一样,谁用谁知道

问题三:尤大大已经说过,vue 3 已经没有任何类了

这个问题这么说呢,你们看下这段代码和 vue 2.x 比比

import { createApp, reactive, h } from 'vue'

import App from './App.vue'
import router from './router'

const store = reactive({
  // global state
})

const app = createApp({
  render() {
    // h 已经是全局函数了
    return h(App)
  }
})

// 现在 config 在 app 上,意不意外
app.config.errorHandler = () => {}

// 经常往 Vue.prototype 挂东西的行为可以停停了
// 现在应该推荐这样玩
app.provide('state', store)

// 全局组件注册也在这里
app.component('page', Page)

// 现在 router 是这样用的
// 而且不需要再把 router 作为参数丢进 app 中了
app.use(router)

// 以前所有带 $ 符号的大部分都已经去除前缀了
app.mount('#app')
复制代码

写法本身没大问题,但是想当于以前的 hack 手段,大家可以停下了,因为没有原型可以给大家玩了,主要是习惯问题

基本上适应下就好了,唯一比较麻烦的是组件那块。

问题三:jsx 和 render 的问题

ps: 模板不算哈,那个编译支持的,我说的是手动写的情况下

1. 现在更新需要 flag 支持

在 babel 插件没有跟上的情况,写的特别难受,因为 vue3 的响应式数据是需要 flag 支持的,也就是如果没有 flag,那你的数据就是个纯数据,没有任何响应式变化。

要下面这样写,带 flag 才行,这个值的说明,看直播的应该都了解过了。

之所以拿这个说明是因为写通用组件的时候,这种手写 render 的情况其实挺多的,这样对于开发者来说,不借助官方的插件,可能是一个不小的挑战

2. 子元素不支持数组了

另外不知道为什么不支持直接传递数组了,你如果传递就会给你提示

这个其实挺麻烦的,因为你需要包一层,下面的写法才可以

或者无聊翻人家 api,找一可能的挂上去,我就找到了 createSlots 的,但其实不用也可以的,你们等官方出文档再说吧。

不过比较好的是,终于有了 renderSlot 方法,不用再每次手动写判断了,👏👏🎉🎉

结束

其实还有周边的问题,比如你们看到的 storybook 其实是我把官方的下过来,直接改上去的,还好人家写的比较好,不然又要头疼了

另外类型其实还有包本身的问题,我已经提了一个了,但是还是有好多,不过毕竟刚出,还是可以理解的,希望 vue 能越走越远吧,毕竟不是所有人都能认同同一个框架的,只有适合的才是好的。

最后献上我未完成的脚手架地址:✈️飞机

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!