• vue3 的组件通信以及ref的使用


    一. 组件通信

    1. props=>父向子传值

    props主要用于父组件向子组件通信。在父组件中通过用 :msg=“msg” 绑定需要传给子组件的属性值,然后再在子组件中用 props 接收该属性值。

    方法一 普通方式:

    // 父组件 传值
    <child :msg1="msg1" :list="list"></child>
    <script>
    import child from "./child.vue";
    import { ref, reactive } from "vue";
    export default {
        setup() {
            //基础类型传值
            const msg1 = ref("父组件传给子组件的msg1");
            // 复杂类型(数组或对象)传值
             const list = reactive(['苹果', '梨', '香蕉'])
            return {
                msg1,
                list
            }
        }
    }
    </script>
     
    // 子组件 接收
    <template>
      <ul >
        <li  v-for="i in list" :key="i">{{ i }}</li>
      </ul>
    </template>
    <script>
    export default {
      // props接受父组件传过来的值
      props: ["msg1", "list"],
      setup(props) {
        console.log(props);
        // { msg1:"父组件传给子组件的msg1", list:['苹果', '梨', '香蕉'] }
      },
    }
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    方法二:使用 setup 语法糖

    // 父组件 传值
    <child :msg="msg" :list="list">
    </child>
    <script setup>
        import child from "./child.vue";
         const list = reactive(['苹果', '梨', '香蕉'])
        const msg = ref("父组件传给子组件的值");
    </script>
     
    // 子组件 接收
    <template>
      <ul >
        <li  v-for="i in list" :key="i">{{ i }}</li>
      </ul>
    </template>
    <script setup>
        // 这里不需要在从vue中引入defineProps,直接用
        const props = defineProps({
            // 第一种写法
            msg: String,
            // 第二种写法
            list: {
    	    	type: Array,
    	   	 	default: () => [],
    	  	}
        })
        console.log(props);
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    2.emit方式=>子向父传值

    $emit 也就是通过自定义事件传值,主要用于子组件向父组件通信
    在子组件的点击事件中,通过触发父组件中的自定义事件,把想传给父组件的信息以参数的形式带过去,父组件便可以拿到子组件传过来的参数值。

    // 子组件 派发
    <template>
      <button @click="handleClick">按钮</button>
    </template>
    <script setup>
      let infos = ref('还好');
      const handleClick = () => {
        // 触发父组件中的方法,并把值以参数的形式传过去
        emit('myClick', infos);
      };
      const emit = defineEmits(['myClick']);
    </script>
    
     
    // 父组件 接收
    <template>
        <child @myClick="onMyClick"></child>
    </template>
    <script setup>
        import child from "./child.vue";
        // 父组件接受到子组件传过来的值
        const onMyClick = (msg) => {
            console.log(msg);
        }
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    3.expose / ref=》父获取子得属性或方法

    expose与ref 主要用于父组件获取子组件的属性或方法。在子组件中,向外暴露出属性或方法,父组件便可以使用 ref 获取到子组件身上暴露的属性或方法。

    <template>
      <div>父组件:拿到子组件的message数据:{{ msg }}</div>
      <button @click="callChildFn">调用子组件的方法</button>
    
      <hr />
    
      <Child ref="com" />
    </template>
    
    <script setup>
      import Child from './child.vue';
    
      const com = ref(null); // 通过 模板ref 绑定子组件
    
      const msg = ref('');
    
      onMounted(() => {
        // 在加载完成后,将子组件的 message 赋值给 msg
        msg.value = com.value.message;
      });
    
      function callChildFn() {
        console.log(com.value, '====');
        // 调用子组件的 changeMessage 方法
        com.value.show();
    
        //  重新将 子组件的message 赋值给 msg
        msg.value = com.value.message;
      }
    </script>
    
    子组件:
    <template>
      <div> 子组件:</div>
    </template>
    <script setup>
      const message = ref('子组件传递得信息');
      const show = () => {
        console.log('子组件得方法');
      };
      defineExpose({
        message,
        show,
      });
    </script>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    4.attrs

    attrs 主要用于子组件获取父组件中没有通过 props 接收的属性

    <template>
      <Child :msg1="msg1" :msg2="msg2" title="子组件" />
    </template>
    
    <script setup>
      import Child from './child.vue';
      const msg1 = ref('信息1');
      const msg2 = ref('信息2');
    </script>
    
    子组件
    <template>
      <div> 子组件:{{ msg1 }}-{{ attrs.msg2 }}-{{ attrs.title }}</div>
    </template>
    <script setup>
      // 子组件接收msg1
      defineProps({
        msg1: String,
      });
    
      const attrs = useAttrs();
      // 因为子组件接收了msg1,所以打印的结果中不会包含msg1, { msg2:"信息1", title: "子组件" }
      // 如果子组件没有接收msg1,打印的结果就是 { msg1: "信息1", msg2:"信息12", title: "子组件" }
      console.log(attrs);
    </script>
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    5. provide / inject

    遇到多层传值时,使用 props 和 emit 的方式会显得比较笨拙。这时就可以用 provide 和 inject 了。
    provide与inject 主要为父组件向子组件或多级嵌套的子组件通信
    provide:在父组件中可以通过 provide 提供需要向后代组件传送的信息。
    inject:从父组件到该组件无论嵌套多少层都可以直接用 inject 拿到父组件传送的信息。

    <template>
      <div>------祖父组件---------</div>
      <button @click="fn">改变location的值</button>
      <br />
      <div>双向数据绑定:</div>
      姓名 {{ userInfos.username }}<input v-model="userInfos.username" />
      <Child />
    </template>
    
    <script setup>
      import Child from './child.vue';
      let location = ref('传递祖父的参数');
      var userInfos = reactive({
        username: '张三',
        age: 20,
      });
      let fn = () => {
        location.value = '改变值';
      };
      provide('location', location);
      provide('userInfos', readonly(userInfos));
    </script>
    
    子组件:
    <template>
    	<div>
    		  <Sun />
    	</div>
    </template>
    
    <script>
    import Sun from "./sun.vue";
    </script>
    孙组件:
    <template>
      <div>
        <h5>-------------孙组件接受参数-------------</h5>
        <div>1.祖父组件定义provide,孙组件inject接受:{{ location }}</div>
        <p>用户信息: {{ userInfos.username }}</p>
        <br />
        <br />
        <div>2.provide inject实现父子组件传值的时候,子组件改变数据也会影响父组件</div>
        <br />姓名:
        <input v-model="userInfos.username" />
      </div>
    </template>
    <script setup>
      let location = inject('location');
      let userInfos = inject('userInfos');
    </script>
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    注意:增加readonly后,子组件修改后,不会影响到父组件

    6.readonly

    获取一个对象 (响应式或纯对象) 或 ref 并返回原始代理的只读代理,不能给属性重新赋值。只读代理是递归的:访问的任何嵌套 property 也是只读的。
    简单得理解:要确保父组件传递得数据不会被子孙组件更改时,增加readonly

    7.v-model

    v-model 是 Vue 的一个语法糖。在 Vue3 中的玩法就更多了

    单个 v-model 绑定

    <template>
      <Child v-model="message" />
    </template>
    
    <script setup>
      import Child from './child.vue';
      const message = ref('父传给子');
    </script>
    子组件:
    <template>
      <div>
        <button @click="handleClick">修改model</button>
        {{ modelValue }}
      </div>
    </template>
    <script setup>
      // 接收
      defineProps([
        'modelValue', // 接收父组件使用 v-model 传进来的值,必须用 modelValue 这个名字来接收
      ]);
    
      const emit = defineEmits(['update:modelValue']); // 必须用 update:modelValue 这个名字来通知父组件修改值
    
      function handleClick() {
        // 参数1:通知父组件修改值的方法名
        // 参数2:要修改的值
        emit('update:modelValue', '子改变值');
      }
    </script>
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    多个 v-model 绑定

    <template>
      <Child v-model:msg1="message1" v-model:msg2="message2" />
    </template>
    
    <script setup>
      import Child from './child.vue';
      const message1 = ref('水果1');
      const message2 = ref('水果2');
    </script>
    子组件:
    <template>
      <div>
        <div><button @click="changeMsg1">修改msg1</button> {{ msg1 }}</div>
        <div><button @click="changeMsg2">修改msg2</button> {{ msg2 }}</div>
      </div>
    </template>
    <script setup>
      // 接收
      defineProps({
        msg1: String,
        msg2: String,
      });
    
      const emit = defineEmits(['update:msg1', 'update:msg2']);
    
      function changeMsg1() {
        emit('update:msg1', '蔬菜1');
      }
    
      function changeMsg2() {
        emit('update:msg2', '蔬菜2');
      }
    </script>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    v-model 修饰符

    v-model 还能通过 . 的方式传入修饰。v-model 有内置修饰符——.trim、.number 和 .lazy。但是,在某些情况下,你可能还需要添加自己的自定义修饰符。

    <template>
      <Child v-model.uppercasefn="message" />
    </template>
    
    <script setup>
      import Child from './child.vue';
      const message = ref('水果');
    </script>
    子组件:
    <template>
      <div>
        <div>{{ modelValue }}</div>
      </div>
    </template>
    <script setup>
      const props = defineProps(['modelValue', 'modelModifiers']);
    
      const emit = defineEmits(['update:modelValue']);
    
      onMounted(() => {
        console.log(props.modelModifiers, '自定义v-model 修饰符');
        // 判断有没有uppercasefn修饰符,有的话就执行 下面得方法 方法
        if (props.modelModifiers.uppercasefn) {
          emit('update:modelValue', '蔬菜');
        }
      });
    </script>
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    8.插槽 slot

    插槽可以理解为传一段 HTML 片段给子组件。子组件将 元素作为承载分发内容的出口。

    默认插槽

    插槽的基础用法非常简单,只需在 子组件 中使用 标签,就会将父组件传进来的 HTML 内容渲染出来。

    <template>
      <Child>
        <div>渲染</div>
      </Child>
    </template>
    子组件:
    // Child.vue
    
    <template>
      <div>
        <slot></slot>
      </div>
    </template>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    具名插槽

    具名插槽 就是在 默认插槽 的基础上进行分类,可以理解为对号入座。

    <template>
      <Child>
        <template v-slot:monkey>
          <div>渲染</div>
        </template>
    
        <button>按钮</button>
      </Child>
    </template>
    子组件:
    <template>
      <div>
        <!-- 默认插槽 -->
        <slot></slot>
        <!-- 具名插槽 -->
        <slot name="monkey"></slot>
      </div>
    </template>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    父组件需要使用 标签,并在标签上使用 v-solt: + 名称 。子组件需要在 标签里用 name= 名称 对应接收。

    作用域插槽

    <template>
      <!-- v-slot="{scope}" 获取子组件传上来的数据 -->
      <!-- :list="list" 把list传给子组件 -->
      <Child v-slot="{ scope }" :list="list">
        <div>
          <div>{{ scope.name }}--职业:{{ scope.occupation }}</div>
          <hr />
        </div>
      </Child>
    </template>
    <script setup>
      import Child from './child.vue';
      const list = reactive([
        { name: '鲁班', occupation: '辅助' },
        { name: '貂蝉', occupation: '刺客和法师' },
        { name: '虞姬', occupation: '射手' },
      ]);
    </script>
    子组件:
    <template>
      <div>
        <!-- 用 :scope="item" 返回每一项 -->
        <slot v-for="item in list" :scope="item"></slot>
      </div>
    </template>
    <script setup>
      defineProps({
        list: {
          type: Array,
          default: () => [],
        },
      });
    </script>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    9.事件总线(mitt&tiny-emitter)

    Vue3中移除了事件总线,但是可以借助于第三方工具来完成,Vue官方推荐mitttiny-emitter
    在大多数情况下不推荐使用全局事件总线的方式来实现组件通信,虽然比较简单粗暴,但是长久来说维护事件总线是一个大难题。

    mitt

    mitt.js 不是专门给 Vue 服务的,但 Vue 可以利用 mitt.js 做跨组件通信。(vue3去掉了 o n 、 on、 onoff后,使用mitt第三方库替代eventBus的原理。)

    比起 Vue 实例上的 EventBus,mitt.js 好在哪里呢?

    1. 首先它足够小,仅有200bytes。
    2. 其次支持全部事件的监听和批量移除。
    3. 它还不依赖 Vue 实例,可以跨框架使用,React 或者Vue,甚至 jQuery 项目都能使用同一套库。

    npm install --save mitt

    父组件:
    <template>
    	<div>
    		<Home />
            <Mitt/>
        <div>
    </template>
    <script >
    import Home from "@/views/home.vue";
    import Mitt from "@/views/mitt.vue";
    </script >
    emiter.js
    // mitt库默认导出的是一个函数,我们需要执行它从而得到事件总线的对象
    import mitt from 'mitt'
    const emiter = mitt()
    export default emiter
    
    子组件Home:
    <template>
    	<div>
             <p>这里是home组件</p>
    	<button @click="sendHomeContent">$mitt发送数据</button>  
    	</div>
    </template>
    
    <script>
    import { ref}from 'vue'
    import emitter from "./../model/emitter.js";
    export default {
        setup(props,ctx) {
            const money = ref(98);
            var sendHomeContent=()=>{
                // emit发送信息
                emitter.emit("moneyEvent",money.value += 2);// 触发自定义总线moneyEvent,并传入一个对象 。
            }
            return{
                sendHomeContent
            }
        }
    };
    </script>
    子组件 Mitt:
    <template>
    	<div>
    		<p>这里是Mitt组件</p>
            <p>接收到的数据:{{ amount }}</p>
    	</div>
    </template>
    
    import { ref,   onUnmounted, onMounted } from 'vue';
    import emitter from "../model/event";
    export default {
    	setup(props,ctx) {
            const amount = ref(0);
            const callback = (res) => {
                if (res) {
                    amount.value = res;
                }
            }
            onMounted(() => {
               //DOM挂载完毕
                emitter.on('moneyEvent', callback );
            })
            onUnmounted(() => {
                //销毁完毕
                emitter.off('moneyEvent',callback );
            });
            return {
                amount
            }
        }
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73

    在这里插入图片描述
    总结:
    emit 发送信息
    on 接收信息
    off 取消监听
    清除所有的事件写法
    emitter.all.clear()

    10.状态管理工具

    Vuex和Pinia是Vue3中的状态管理工具,使用这两个工具可以轻松实现组件通信。
    Pinia 是最近比较火热的一个工具,也是用来处理 跨组件通信 的,极大可能成为 Vuex 5

    二. 细节

    1.Vue3中的ref如何使用?v-for有如何使用ref?

    Vue2 中的 ref

    获取节点:这是 ref 的基本功能之一,目的就是获取元素节点,在 Vue 中使用方式也很简单

    <template>
      <div id="app">
        <div ref="test">你好!</div>
      </div>
    </template>
    <script>
    export default {
      mounted() {
        console.log(this.$refs.test); // <div>你好!</div>
      },
    };
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    Vue3 中 ref 访问元素

    Vue3 中通过 ref 访问元素节点与 Vue2 不太一样,在 Vue3 中我们是没有 this 的,也没有 this.$refs。想要获取 ref,我们只能通过声明变量的方式。

    <template>
      <div ref="test">你好!</div>
    </template>
    <script setup >
    import { onMounted, ref } from "vue";
    const test = ref(null);
    onMounted(() => {
      console.log(test.value); // <div>你好!</div>
    });
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    注意点:
    • 变量名称必须要与 ref 命名的属性名称一致。
    • 通过 test.value 的形式获取 DOM 元素。
    • 必须要在 DOM 渲染完成后才可以获取 test.value,否则就是 null。

    v-for 中使用 ref

    使用 ref 的场景有多种,一种是单独绑定在某一个元素节点上,另一种便是绑定在 v-for 循环出来的元素上了。这是一种非常常见的需求,在 Vue2 中我们通常使用:ref="…"的形式,只要能够标识出每个 ref 不一样即可。
    但是在 Vue3 中又不太一样,不过还是可以通过变量的形式接收。

    <template>
    	<div>
             <p ref="test">1. v-for 中的 Ref 数组</p>
                <div v-for="item in 5" :key="item"  :ref="setItemRef">
                      {{ item }} -水果
                </div>
              <button @click="printFN">点击2</button>
    	</div>
    </template>
    
    <script>
    import { ref,onMounted}from 'vue'
    export default {
        setup(props,ctx) {
            const test = ref(null);
            let itemRefs = [];
            const setItemRef = el => {
            if (el) {
                itemRefs.push(el)
            }
            }
            onMounted(() => {
                console.log(test.value,'在 vue3 中'); // <div>小猪课堂</div>
            });
            const printFN=()=>{
                console.log(itemRefs,'在嵌套 vue3 中')
            }
            return {
                test,
                setItemRef,
                printFN
            }
        }
    };
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    在这里插入图片描述
    这里我们需要注意一下:我们似乎没办法区分哪个 li 标签哪个 ref,初次之外,我们的 itemRefs 数组不能够保证与原数组顺序相同,即与 list 原数组中的元素一一对应。

    ref 绑定函数

    前面我们在组件上定义 ref 时,都是以一个字符串的形式作为 ref 的名字,其实我们的 ref 属性还可以接收一个函数作为属性值,这个时候我们需要在 ref 前面加上:。

    <template>
    	   <div :ref="setHelloRef">水果</div>
    </template>
    
    <script>
    import { ref}from 'vue'
    export default {
        setup(props,ctx) {
            const setHelloRef = (el) => {
              console.log(el); // <div>水果</div>
            };
            return {
                setHelloRef
            }
        }
    };
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    上段代码中 ref 属性接收的是一个 setHelloRef 函数,该函数会默认接收一个 el 参数,这个参数就是我们需要获取的 div 元素。假如需求中我们采用这种方式的话,那么完全可以把 el 保存到一个变量中去,供后面使用。

    v-for 中使用ref 函数

    <template>
        <div v-for="item in 10" :key="item" :ref="(el) => setItemRefs(el, item)">
                {{ item }} -水果
        </div>
    </template>
    
    <script>
    import { ref,onMounted}from 'vue'
    export default {
        setup(props,ctx) { 
            let itemRefs = [];
            const setItemRefs = (el,item) => {
                if(el) {
                    itemRefs.push({
                        id: item,
                        el,
                    });
                }
            }
            onMounted(() => {
                console.log(itemRefs,'在 vue3 中'); // <div>小猪课堂</div>
            });
            return {
                setItemRefs
            }
        }
    };
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    在 v-for 中使用函数的形式传入 ref 与不使用 v-for 时的形式差不多,不过这里我们做了一点变通,为了区别出哪个 ref 是哪一个 li 标签,我们决定将 item 传入函数,也就是(el) => setItemRefs(el, item)的写法。
    这种形式的好处既让我们的操作性变得更大,还解决了 v-for 循环是 ref 数组与原数组顺序不对应的问题。
    在这里插入图片描述

    组件上使用 ref

    之前所使用 ref 时,都是在一个具体的 dom 元素上绑定,但是我们也可以将 ref 绑定在组件上,比如在 Vue2 中,我们将 ref 绑定在组件上时,便可以获取到该组件里面的所有数据和方法.在 Vue3 中,使用 ref 获取子组件时,如果想要获取子组件的数据或者方法,子组件可以通过defineExpose 方法暴露数据
    参考上面“expose / ref=》父获取子得属性或方法”

  • 相关阅读:
    redisson中的分布式锁
    Python学习第八篇:requests 库学习
    【树莓派 Pico 和 Pico W】
    Mysql数据重复问题处理
    SpringBoot+Redis实现接口幂等性,就看这篇了
    Java进阶(十)File、方法递归、IO流
    【开源电商网站】(2),使用docker-compose和dockerfile进行配置,设置自定义的镜像,安装插件,增加汉化包,支持中文界面汉化。
    SpringBoot(One·上)
    这资源也太强了!8月版最新AI脚本插件合集来了
    想看Vue文档,cn放错位置,误入xx网站...
  • 原文地址:https://blog.csdn.net/gao_xu_520/article/details/125596347