V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zhennann
V2EX  ›  Node.js

Vue3 开发新范式,不用`ref/reactive`,不用`ref.value`

  •  
  •   zhennann · 194 天前 · 4829 次点击
    这是一个创建于 194 天前的主题,其中的信息可能已经有所发展或是发生改变。

    什么是 Cabloy-Front ?

    Cabloy-Front 是一款支持 IOC 容器的 Vue3 框架。不用ref/reactive,不用ref.value,不用pinia

    与 UI 库的配合

    Cabloy-Front 可以搭配任何 UI 库使用,并且内置了几款 UI 库的项目模版,便于开箱即用,包括:

    • antdv
    • element-plus
    • quasar
    • vuetify

    特性

    Cabloy-Front 为 Vue3 引入了以下鲜明特征:

    • 不用 ref/reactive:因为在大多数场景下,不需要使用 ref 和 reactive
    • 不用 ref.value:因为在 Cabloy-Front 中定义响应式变量更加直观,不再需要 ref 语义
    • 不用 pinia:因为 Cabloy-Front 提供了 IOC 容器,可以更加灵活的定义和使用全局对象

    动图演示

    No ref/reactive

    演示:不用ref/reactive,不用ref.value

    1. 定义响应式状态

    @Local()
    export class MotherPageCounter extends BeanMotherPageBase {
      counter: number = 0;
    
      inrement() {
        this.counter++;
      }
    
      decrement() {
        this.counter--;
      }
    }
    

    2. 使用响应式状态

    @Local()
    export class RenderPageCounter extends BeanRenderBase {
      render() {
        return (
          <div>
            <div>counter(ref): {this.counter}</div>
            <button onClick={() => this.inrement()}>Inrement</button>
            <button onClick={() => this.decrement()}>Decrement</button>
          </div>
        );
      }
    }
    

    演示:依赖注入

    1. 逻辑抽离

    counter逻辑抽离出来,创建一个Counter Bean

    @Local()
    export class LocalCounter extends BeanBase {
      counter: number = 0;
    
      inrement() {
        this.counter++;
      }
    
      decrement() {
        this.counter--;
      }
    }
    

    2. 在组件中注入并使用

    @Local()
    export class MotherPageCounter extends BeanMotherPageBase {
      @Use()
      $$counter: LocalCounter;
    }
    
    @Local()
    export class RenderPageCounter extends BeanRenderBase {
      render() {
        return (
          <div>
            <div>counter(ref): {this.$$counter.counter}</div>
            <button onClick={() => this.$$counter.inrement()}>Inrement</button>
            <button onClick={() => this.$$counter.decrement()}>Decrement</button>
          </div>
        );
      }
    }
    

    框架已开源: https://github.com/cabloy/cabloy-front

    57 条回复    2024-05-29 15:35:00 +08:00
    sun2920989
        1
    sun2920989  
       194 天前   ❤️ 2
    按理说应该放到推广节点
    sjhhjx0122
        2
    sjhhjx0122  
       194 天前
    我也写过一个这方面的库,后来觉得只要提供依赖注入,其他还是标准 vue 的范式比较好
    zhennann
        3
    zhennann  
    OP
       194 天前
    @sjhhjx0122 思路是一致的。对于组件的类型导出,仍然延用 vue3 setup 的特性。依赖注入主要是面向业务层面。
    Terry05
        4
    Terry05  
       194 天前
    等等后续
    linzhe141
        5
    linzhe141  
       194 天前   ❤️ 1
    都这样了,那为什么不去用 ng
    FrankFang128
        6
    FrankFang128  
       194 天前
    extends 太多了,不喜欢
    nulIptr
        7
    nulIptr  
       194 天前
    光看你截图这 class 写法,这 render 函数,有点像 react 。。。。
    相当于整个把 vue 的范式都变了,新框架+1
    ixoy
        8
    ixoy  
       194 天前
    都魔改成这样了,直接 react 。Vue3 定义数据都搞这样。真无语。
    zhennann
        9
    zhennann  
    OP
       194 天前
    @linzhe141 ng 的 ioc 太繁琐了。cabloy-front 采用依赖注入和依赖查找相结合的方式,大量减少装饰器函数的使用,让代码更加简洁,再加上 vue3 的响应式和 tsx 的灵活性,整体效果比 ng 好太多。
    zhennann
        10
    zhennann  
    OP
       194 天前
    @FrankFang128 extends 某个基类,就可以通过`this.`直接使用大量常用的功能,减少 import 和 use 等导入代码。虽然使用了`this.`一样有类型校验,自动完成提示,也可以跟踪其源码出处
    zhennann
        11
    zhennann  
    OP
       194 天前
    @ixoy 这样就可以不再纠结使用 ref 还是 reactive ,不用担心失去响应式的烦恼,也不用再写大量 ref.value ,同时又能利用 vue3 的响应式
    crocoBaby
        12
    crocoBaby  
       194 天前
    不好用
    Kalan
        13
    Kalan  
       194 天前
    我决定命名为 veact ,谁赞成谁反对
    timedivision
        14
    timedivision  
       194 天前   ❤️ 2
    @Kalan revue 比较好
    LandCruiser
        15
    LandCruiser  
       194 天前
    我之前发过一个吐槽接收离职同事的项目代码的帖子,我接手的代码就有往这个方向封装的趋势,完全没必要,引入了一套有复杂度的东西,但是没解决任何问题。有自己喜欢的开发范式没问题,但好坏是客观的。
    ref 和 react 的 useState 都是其各自的 api 而已,尤其是 vue 的 ref ,尽管 vue3 的 ref ,reactive 及其自动解包,解构等等有一系列问题,但不要再打这些东西的主意了。
    weijancc
        16
    weijancc  
       194 天前
    用 class 还是算了
    Track13
        17
    Track13  
       194 天前
    vue3 的响应式和 tsx 的灵活性,要不试试看 solidjs
    kneo
        18
    kneo  
       194 天前   ❤️ 1
    vue 定义了 ref 和 reactive 就是为了让你别自己写这些玩意。你自己把这些反模式包装了一下又塞回来,真是个小天才。
    CHTuring
        19
    CHTuring  
       194 天前   ❤️ 1
    vue2 不支持 ts 拆 hack 的这种写法,被你又从 vue3 上加回来了,小天才。
    zhudapaooo
        20
    zhudapaooo  
       194 天前   ❤️ 1
    四不像了
    zhennann
        21
    zhennann  
    OP
       194 天前
    在面向大型的业务开发场景中,需要两个层面的架构设计:
    1. 与界面交互的架构,这个使用 vue3 setup 来做
    2. 与业务相关的架构,这个使用 ioc 容器来做。大量的工程实践证明,在业务层面,class 比 function 好用很多
    shizhibuyu2023
        22
    shizhibuyu2023  
       194 天前
    很多年不写 class 了,你懂我意思吧
    wu67
        23
    wu67  
       194 天前   ❤️ 1
    不如叫 javue 或者 sprivue 算了...
    zhennann
        24
    zhennann  
    OP
       194 天前
    @kneo 那么什么是反模式呢?为什么那么多人纠结用 ref 还是 reactive ,为什么有的地方推荐 ref 而不是 reactive ,为什么 ref.value 无法规避。为什么代码多了一样乱。
    dai269619118
        25
    dai269619118  
       194 天前 via iPhone
    为什么我还是觉得 vue2 好用
    tikazyq
        26
    tikazyq  
       194 天前   ❤️ 1
    开始想来吐槽闭门造车,但后来发现这个开源项目专业搞笑的

    https://github.com/cabloy/cabloy-front/issues/1

    ---

    Why is mother?

    index.vue is just a facade used to define Vue component. After invoking the useMother function, the work is transferred to mother.ts. If necessary, the definitions of props, emits and slots are all in mother.ts, and most business logics will also be placed in mother.ts

    This is just like the behavior of lions: the male lions are the facade, and the female lions do the work. Therefore, if you think of index.vue as father, then mother.ts is the one who actually does the work
    coolcoffee
        27
    coolcoffee  
       194 天前
    相比.value ,我更不想写 this 。在 vue 里面写 jsx ,像比较方便的双向绑定都丢失了,写成两不像心智负担反而更大。

    所以为啥不用 react 呢?
    Rrrrrr
        28
    Rrrrrr  
       194 天前
    我也觉得 react 好,搞了几年 vue2 再也不想写
    zhennann
        29
    zhennann  
    OP
       194 天前
    @coolcoffee 为什么不用 react ?参见我上面的回复。在面向大型的业务开发场景中,需要两个层面的架构设计。否则,代码多了一定会乱
    Ma4cus
        30
    Ma4cus  
       194 天前
    我记得 vue 官方文档不是不推荐在 vue3 使用 class 写法吗
    zhennann
        31
    zhennann  
    OP
       194 天前   ❤️ 1
    @Ma4cus 确实有几个 class 的实现效果不理想,所以 vue 官方不推荐。不理想的原因是他们把 class 用在了“与界面交互的架构”层面。而 cabloy-front 在“与界面交互的架构”层面仍然使用 vue setup 语法,在“与业务相关的架构”层面使用 class 和 ioc 。所以,与官方的说法并不相悖,只是站在不同的角度做的判断。
    miaowo
        32
    miaowo  
       194 天前
    不喜欢用 class 写
    charlie21
        33
    charlie21  
       194 天前
    “在组件中注入并使用” 这一步仅仅是让组件消费数据。若是让组件消费一个数据,则直接使用 vue composable 提供一个数据足矣

    依赖注入可以直接用 inversify.js 的 container , inversify.js 的 container 的定义是支持 class 的,一个 container 单例是独立于 vue instance 的,哪个组件需要它就 import 就完事了,根本不用耦合到 vue instance 里
    leokun
        34
    leokun  
       194 天前
    我觉得还是挺有意思的,虽然一直很抵制继承、装饰器等类上的用法
    不过在做编辑器等复杂的项目时,代码更加清晰可读。
    现在 vue 、react 都是组合式、函数式,op 这个库有点过于固执己见了。
    chuck1in
        35
    chuck1in  
       194 天前
    等等,这个为啥要发到 node 不发到前端开发节点。
    zhennann
        36
    zhennann  
    OP
       194 天前
    @charlie21 cabloy-front 提供了两类 container ,一类如你所说是 global container ,实现全局状态的消费,可以直接代替 pinia 的能力。还有一类是组件 container ,与 vue instance 绑定。提供 vue instance 级别 container 的好处就是,在这个容器中的所有 bean 实例都可以在 vue instance 这个范围共享和消费数据。这种机制其实要比 composable 的耦合性低很多了
    zhonj
        37
    zhonj  
       194 天前
    vue 本来就是要简单上手,学习成本低,你倒好给 vue3 套了一层复杂 buff 。用这玩意代码简洁灵活,也要看人的,后端写 java 的都那样分层了,业务逻辑一多一复杂还不是一坨屎。最近写前端颇有感悟啊,一个 js 这么轻的语言,npm i 一下 2000 多个依赖,前端这群家伙是真的闲没事就去造轮子
    brookegas
        38
    brookegas  
       193 天前   ❤️ 3
    被 Spring 大法霍霍过的 Java 程序员,不管什么都喜欢来个 IOC“容器”
    连 js 这种人畜无害的前端语言都不放过

    看了评论,幸好大多数人还都是正常的
    Cbdy
        39
    Cbdy  
       193 天前
    笑死,请不要闭门造车
    xntzmk
        40
    xntzmk  
       193 天前
    感觉写 this 更让人讨厌的
    angrylid
        41
    angrylid  
       193 天前 via Android
    @brookegas js 已经够糟了,还有人致力于让他更糟🥲
    xujiahui
        42
    xujiahui  
       193 天前
    不喜欢 class 和 this
    skipwitit
        43
    skipwitit  
       193 天前
    实属自我感动
    ooolooo
        44
    ooolooo  
       193 天前
    vue 仔表示项目里没有写过 class, 更讨厌 this
    uni
        45
    uni  
       193 天前
    看见 class 就烦
    R1hu6Hs2sSN8pkVX
        46
    R1hu6Hs2sSN8pkVX  
       193 天前
    不用.value 用 this 了。。。
    brookegas
        47
    brookegas  
       193 天前
    @angrylid 就算是个很丑的女人,也不能根据自己的喜好去随意糟蹋人家,是吧 😂
    xFrye
        48
    xFrye  
       193 天前
    求放过,一股 java 味不要开倒车好不
    Daotin
        49
    Daotin  
       193 天前
    看到代码以为是 java 直接略过,看了评论翻上去回看才知道是 vue😂。。。。直接用 template 多简单?
    ceilingyear
        50
    ceilingyear  
       187 天前
    不懂就问,为啥一个文件就能解决的问题,用了框架要搞三个文件,还有怎么组件化
    humbass
        51
    humbass  
       186 天前
    这个就是 java for js
    zhennann
        52
    zhennann  
    OP
       183 天前
    @humbass 更准确的说法是,ioc 容器和 oop 适合业务领域的建模和抽象。后端采用 ioc 容器自是当然。如果前端项目比较大,业务复杂,引入 IOC 容器可以简化业务设计。此外,Cabloy-Front 采用依赖注入和依赖查找相结合的方式,大量减少装饰器的使用,让代码更简洁、更优雅。优先使用依赖查找的机制可以达到化类型于无形的效果?简而言之,就是无须标注类型,却能享受到“类型约束”和“智能提示”的好处。这个是基于 Typescript 的强大类型系统实现的,在 java 中很难做到,因此大家普遍认为 java 很繁琐,就很好理解了。
    zhennann
        53
    zhennann  
    OP
       183 天前
    @ceilingyear 一个文件确实能解决问题,但是使用三个文件是为了解耦合,以便更好的适应业务的膨胀。
    1. index.vue:在这个文件中,使用 vue3 的语法糖定义组件的 props 和 emits
    2. mother.ts:一个 vue 组件实例对应一个 ioc 容器。该容器与 Vue 组件实例绑定,在这个容器中的所有 Class 实例都可以在组件实例范围之内共享数据和逻辑。那么,mother class 就是这个 ioc 容器中的第一个 class 。组件的业务逻辑就从这里展开
    3. render.tsx:在这个 render class 中编写 tsx 代码,实现界面渲染。在一个独立的文件中书写 tsx 代码,从而让 tsx 代码更加舒展、从容。不知你是否有如此体验:如果仅仅在一个 SFC 文件写 tsx 代码,总是很局促的。当业务比较复杂的时候,展开很麻烦,代码逻辑不容易区分开

    此外,Cabloy-Front 所采用的 class 机制,与社区现有的多个 class 方案有本质的区别,因此,逻辑更清晰,代码更优雅。可以看一下这篇文章:为什么需要 Vue3+IOC: https://front.cabloy.com/zh/guide/start/why.html
    zhennann
        54
    zhennann  
    OP
       183 天前
    @Daotin 简单的方案容易上手,却不容易适应项目的膨胀。为什么许多项目,代码一多就乱,就是因为前期没有规划,怎么简单怎么来。可以看一下这篇文章:为什么需要 Vue3+IOC: https://front.cabloy.com/zh/guide/start/why.html
    zhennann
        55
    zhennann  
    OP
       181 天前
    @tikazyq 已经将 mother 相关的术语改为 controller 。多谢建议🙏
    zhongs
        56
    zhongs  
       181 天前
    看着感觉好麻烦
    zhennann
        57
    zhennann  
    OP
       181 天前
    @zhongs Cabloy-Front 提供了许多 cli 命令行工具,帮助我们搭建代码骨架,所以有些代码不需要我们写,只需要写业务代码即可。可以看一下 codesandbox 在线代码演示: https://codesandbox.io/p/github/zhennann/cabloy-front-demo-codesandbox2/main?checkout=true&embed=1&file=%2Fsrc%2Fsuite%2Fa-demo%2Fmodules%2Fa-demo%2Fsrc%2Fpage%2Fcounter%2Fcontroller.ts
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3041 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 14:28 · PVG 22:28 · LAX 06:28 · JFK 09:28
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.