vue 指令更新问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
leaveeel
V2EX    Vue.js

vue 指令更新问题

  •  
  •   leaveeel 191 天前 2811 次点击
    这是一个创建于 191 天前的主题,其中的信息可能已经有所发展或是发生改变。
    昨天下班前碰到一个问题,我是自己写的 loading 组件,注册了全局指令。在指令引用的时候如果 loading 是对象在更新属性时指令方法 updated 不会捕获到修改,v-loading 用扩展运算或者在 template 里引用则能正确更新状态。能在哪里做些调整吗?

    ![code]( https://imgur.com/a/1GmgAgO)

    ![direactive]( https://imgur.com/a/mLmEw9I)



    另外,不确定自己封装通用组件的必要性,现在的是 C 端项目有 ui 要求没用模板,但也有像 form 、table 、dialog 等模块,因为工作量不大我现在都单独抽出了组件库写了文档。越优化越觉得和 element 的组件功能是差不多的只是 ui 不同,引用 element 然后自定义样式,不满足的功能也可以二次封装自己添加,按需加载打包可能更方便?
    15 条回复    2025-04-01 18:23:28 +08:00
    wangtian2020
        1
    wangtian2020  
       191 天前   1
    let loading = ref(false)
    ljl024
        2
    ljl024  
       191 天前   1
    在 mounted 和 updated 中 watch 一下 bindingValue ,根据这边变量的用法,属性变化不会触发 updated 。用 element-plus 覆盖样式也挺香,或者 fork 下来改改
    ooo4
        3
    ooo4  
       191 天前   3
    https://github.com/vuejs/core/blob/f6e84af30aeffd281aebbab02b0e623e5fc159e0/packages/runtime-core/src/directives.ts#L95

    有一个 deep 的配置,如果加一个 deep:ture 就可以了,因为在 mount 时,默认没有对这个响应式数据的各个 key 进行依赖收集,所以才没有触发对应的 update 钩子,

    如果你在模板中使用使用{{loadingValueObj}},是直接编译成_toDisplayString($setup.loadingValueObj),里面是使用的 JSON.stringify ,就对各个属性进行了依赖收集了
    leaveeel
        4
    leaveeel  
    OP
       191 天前
    @wangtian2020 boolean 是正常的,用 object 是因为要设置其他属性,已经按 3#的方法修改了
    leaveeel
        5
    leaveeel  
    OP
       191 天前
    @ljl024 原本建项目的时候就在想要不要引 elementplus ,因为以前也一直用这个,原本二次封装的也能直接拿来用。最后还是感觉太重了就自己撸,现在想想可能草率了。XD
    leaveeel
        6
    leaveeel  
    OP
       191 天前
    @ooo4 非常感谢!这是不爱读源码的坏处吗 XD
    NerbraskaGuy
        7
    NerbraskaGuy  
       191 天前
    ref 也能处理 object 啊,reactive 就是因为使用中容易出现像你这种丢失响应性的问题,其实官方更推荐 ref
    ooo4
        8
    ooo4  
       191 天前   1
    @NerbraskaGuy 这个问题的本质是,渲染函数的副作用没有对这种情况进行依赖收集,这就会导致组件始终不会更新了,那么自定义指令的 update 钩子也当然无法执行了
    leaveeel
        9
    leaveeel  
    OP
       191 天前
    @NerbraskaGuy ref 之前试过了也不会更新, @ooo4 说的是对的
    wangtian2020
        10
    wangtian2020  
       191 天前
    ref 和 reactive 的本质区别就是 ref 一定不会出错 reactive 就是会出现意料之外的情况
    只要 ref.value 去重新赋值,一定触发更新。我从来不在项目里写 reactive
    leaveeel
        11
    leaveeel  
    OP
       191 天前
    @NerbraskaGuy
    @wangtian2020
    修正一下我 9#的错误回复,我又试了一下 ref 定义 loading 变量,在对 loading.value 整体重新赋值后确实会触发更新,我的结论是基于对 loading.value.xx 赋值,这是不能捕获修改的,原因就是 @ooo4 说的创建时默认没有对 object key 监听,进行引用和扩展类似创建新对象则会触发 update ,deep 和`watch binding`则是主动激活监听。

    ```
    const loading = ref(false)
    loading.value = { loading: true, text: 'loading...' }
    // 状态更新正常

    const loading = ref({ loading: false })
    loading.value = { loading: true }
    // 状态更新正常

    const loading = ref({ loading: false })
    loading.value.loading = true
    // 无法更新
    ```

    不过从组件的角度肯定是不限制 ref 和 reactive 更合适,因为没有严格的代码规范并不能要求所有人都用 ref.value 赋值。
    wangtian2020
        12
    wangtian2020  
       191 天前
    loading.value.loading = true 按照道理是会触发更新的,我一直所有代码都是这么写的,肯定是哪里写错了引用变了,Vue devtools 你点进去看看就知道了
    喜欢用 reactive 就用,就像有些人喜欢父子传值传进去再 watch 写的复杂的不得了,我是感觉不如 expose 个方法出去让父组件 ref 调用方法一次性传值。这种写法出来的程序只能在中午运行,早晚出问题
    sakura1988
        13
    sakura1988  
       191 天前
    还 ref 一定不出错,对象用 ref 声明,ref.value 就是个 reactive ,用得不好一样出错
    Tokin
        14
    Tokin  
       191 天前
    @leaveeel watch 默认下不会深入观察 ref ,要加 deep 参数:
    ```Javascript
    watch(loading, () => {
    console.log('ref deep watch')
    }, { deep: true })
    ```
    SanjinGG
        15
    SanjinGG  
       191 天前
    @leaveeel 这句话并不对啊,确实没有规范要求用 ref 还是 reactive ,但作为组件,我只需要规定 binding.value 是一个 bool 类型就好了,不管你是基本类型还是对象类型,如果用对象,就应该吧 loading 这单个属性传递给我。参考 element ui ,你的其他 text ,color ,size 属性,应该通过 el 的 dataset 获取,不应该在 binding.value 中。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1152 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 23:28 PVG 07:28 LAX 16:28 JFK 19:28
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86