请教一个 vue 中组件复用的问题 - V2EX
请不要在回答技术问题时复制粘贴 AI 生成的内容
yezheyu

请教一个 vue 中组件复用的问题

  •  
  •   yezheyu Sep 27, 2022 3033 views
    This topic created in 1334 days ago, the information mentioned may be changed or developed.

    如何让复用的组件内部代码随着切换多次执行呢?

    App.vue 组件:有两个按钮,点击按钮下面 div 显示对应按钮中的文字

    <template> <button @click="changeData($event)">user1</button> <button @click="changeData($event)">user2</button> <User :name="data"></User> </template> <script setup> import { ref } from 'vue'; import User from './components/user.vue'; let data = ref('') function changeData(e) { data.value = e.target.innerText } </script> 

    User.vue 组件:

    <template> <div> {{ name }} </div> <!-- <div> {{ attrs.name }} </div> --> </template> <script setup> import { useAttrs } from 'vue'; let attrs = useAttrs() let name = attrs.name console.log(name); </script> 

    User 组件内部的代码只会执行一次,`console.log` 不会随着 button 的点击事件执行多次,不符合预期

    如果在 template 中直接使用 attrs.name 是没问题的,不会丢失响应式

    如果使用变量 name 接收,因为组件内部代码只执行一次的缘故,就不能实现切换文字效果

    如何才能让 User 组件内部的代码随着 button 点击多次执行呢?

    23 replies    2022-10-02 12:40:16 +08:00
    sunny1688
        1
    sunny1688  
       Sep 27, 2022
    定义 props
    optional
        2
    optional  
       Sep 27, 2022 via iPhone
    name 定义成 computed
    musi
        3
    musi  
       Sep 27, 2022
    props + watch
    cydysm
        4
    cydysm  
       Sep 27, 2022
    凑活看吧
    <template>
    <div> {{ name }} </div>
    </template>

    <script setup>
    import {watch} from 'vue'
    let props = defineProps({
    name:String
    })
    watch(props.name, (val) => {
    console.log(val)
    })
    </script>
    HugoChao
        5
    HugoChao  
       Sep 27, 2022
    看了半天都怀疑自己有没有学 vue 了,发现是 vue3 语法
    EyebrowsWhite
        6
    EyebrowsWhite  
       Sep 27, 2022
    接 4 楼, 可以不用 watch, 用 toRef 或者 toRefs,
    `const name = toRef(props, 'name')`
    EyebrowsWhite
        7
    EyebrowsWhite  
       Sep 27, 2022
    额, 好吧, 没看清楚, 如果要是想运行 console 的话, 还是要 watch 的
    vinsony
        8
    vinsony  
       Sep 27, 2022
    <User :name="data" :key="data" />
    yezheyu
        9
    yezheyu  
    OP
       Sep 27, 2022
    @cydysm
    @EyebrowsWhite

    就是说把需要变化的逻辑写在 watch 中是吗
    EyebrowsWhite
        10
    EyebrowsWhite  
       Sep 27, 2022 via iPhone
    @yezheyu 是的,如果你想在某个值变化之后执行一些逻辑,那么这些逻辑要写在 watch 里面
    cydysm
        11
    cydysm  
       Sep 27, 2022
    @yezheyu setup 简单理解取代了 beforecate 和 created ,只会触发一次
    你写成选项式,就明白了
    export default defineComponent({
    setup(){},
    mounted(){}
    })
    setup 中只会走一次 mounted 也是
    yezheyu
        12
    yezheyu  
    OP
       Sep 27, 2022
    @vinsony
    好使,多谢

    能稍微解释下吗
    cydysm
        13
    cydysm  
       Sep 27, 2022
    @yezheyu #8 加 key 属性,每次只要变了都会认为是一个新的组件 而不是复用
    在这个基础上的话 我觉得 key 可以改成 symbol
    yezheyu
        15
    yezheyu  
    OP
       Sep 27, 2022 via iPhone
    @cydysm
    多谢老哥,明白了
    bebop
        16
    bebop  
       Sep 27, 2022
    我觉得最合适的办法是,在 User.vue 中定义一个方法,然后暴露给父组件。父组件每次点击按钮的时候,调用这个方法,把新的数据传递给子组件。
    horizon
        17
    horizon  
       Sep 27, 2022
    这明显是 Props 。。
    yoghurtoreo
        18
    yoghurtoreo  
       Sep 27, 2022
    @bebop 俺也觉得
    Zzzz77
        19
    Zzzz77  
       Sep 27, 2022   1
    这就是最基础的父子组件啊,首先 props 的定义是必须的,不理解 OP 为什么会选择用 attrs.name 这种方式来取父组件的值..

    其次`User 组件内部的代码只会执行一次,`console.log` 不会随着 button 的点击事件执行多次`,这是当然的,和响应式无关,不管 name 变不变,console.log 肯定都只会执行一次。如果需要在 name 变化时执行一些副作用,watch 是最正统的方式,#8 的方法不建议...#16 的方法可行,但这明显更倾向 React 的思维
    yezheyu
        20
    yezheyu  
    OP
       Sep 29, 2022
    @Zzzz77
    那复用的组件生成的页面之间不希望有任何的关联,是不是用绑定 key 的方式最合适。

    例如有下面一个场景:
    user 组件中有个输入框,点击按钮切换页面时,希望表单数据只停留在当前页面,新切换的页面不能包含上一个页面的表单数据。

    这种是不是最好就是借助绑定 key 渲染出的页面,同时使用 keepAlive 缓存

    `<keep-alive> <User :name="data" :key="data" /> </keep-alive>`
    Zzzz77
        21
    Zzzz77  
       Sep 30, 2022
    @yezheyu #20 这种情况你不需要绑定这个 key 啊,父组件传递的 data 发生了改变,User 中接收的 data 这个 prop 自然会跟着变。楼上让绑定 key 只是为了让组件重新渲染从而达到重新执行生命周期这个目的,这是一种偏门骚操作,除非有什么极其特殊的需求(反正我没遇到过),不然绝对不推荐这么做,而你的需求只是最基本的父子组件传值而已,当然也不该这么做,如果有取值以外的副作用需要执行,正常 watch 就行。
    BaiLinfeng
        22
    BaiLinfeng  
       Oct 2, 2022
    @Zzzz77 这句话是说组件只会运行一次吗?不理解,可以详细解说下,感谢。“楼上让绑定 key 只是为了让组件重新渲染从而达到重新执行生命周期这个目的,”
    Zzzz77
        23
    Zzzz77  
       Oct 2, 2022
    @BaiLinfeng 当然呀,一般情况组件只有被载入的时候会初始化一次,例如第一次加载,例如从 v-if="false"到 v-if="true"后。各个生命周期也就是在这时候开始执行的。
    About     Help     Advertise     Blog     API     FAQ     Solana     853 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 69ms UTC 20:49 PVG 04:49 LAX 13:49 JFK 16:49
    Do have faith in what you're doing.
    ubao msn 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